b=364742, Update cairo to git 473ae3aa95, r=stuart

This commit is contained in:
vladimir%pobox.com 2006-12-23 01:15:54 +00:00
Родитель 4243a33bb0
Коммит 83f4546038
70 изменённых файлов: 7639 добавлений и 2832 удалений

Просмотреть файл

@ -1,9 +1,4 @@
Snapshots of cairo and glitz for mozilla usage. A git branch
of this version of cairo is available at
vladimir@git.cairographics.org:~vladimir/cairo
in the 'mozilla-tree-cairo' branch.
Snapshots of cairo and glitz for mozilla usage.
We only include the relevant parts of each release (generally, src/*.[ch]),
as we have Makefile.in's that integrate into the Mozilla build system. For
@ -12,7 +7,7 @@ http://www.cairographics.org/.
VERSIONS:
cairo 1.3.1 (cvs - 2006-07-13)
cairo (git 473ae3aa9510b750f54cbf889180e3c4784da1b7)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****

Просмотреть файл

@ -63,6 +63,7 @@ CSRCS = \
cairo-analysis-surface.c \
cairo-arc.c \
cairo-array.c \
cairo-bentley-ottmann.c \
cairo-cache.c \
cairo-clip.c \
cairo-color.c \
@ -70,6 +71,7 @@ CSRCS = \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \
cairo-hash.c \
cairo-hull.c \
@ -82,8 +84,8 @@ CSRCS = \
cairo-paginated-surface.c \
cairo-path.c \
cairo-path-bounds.c \
cairo-path-data.c \
cairo-path-fill.c \
cairo-path-fixed.c \
cairo-path-stroke.c \
cairo-pattern.c \
cairo-pen.c \
@ -92,6 +94,7 @@ CSRCS = \
cairo-region.c \
cairo-scaled-font.c \
cairo-scaled-font-subsets.c \
cairo-skiplist.c \
cairo-slope.c \
cairo-spline.c \
cairo-stroke-style.c \

Просмотреть файл

@ -154,7 +154,7 @@ static cairo_int_status_t
_cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -363,28 +363,30 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font,
cairo_text_extents_t extents;
OSStatus err;
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
ATSGlyphIdealMetrics metricsH, metricsV;
ATSUStyle style;
ATSGlyphScreenMetrics metricsH, metricsV;
ATSUStyle style,style1;
ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
const ByteCount theSizes[] = { sizeof(verticalType) };
ATSUAttributeValuePtr theValues[] = { &verticalType };
double xscale;
double yscale;
ATSUCreateAndCopyStyle(font->unscaled_style, &style);
_cairo_matrix_compute_scale_factors(&font->base.scale, &xscale, &yscale, 1);
err = ATSUGlyphGetIdealMetrics(style,
1, &theGlyph, 0, &metricsH);
ATSUCreateAndCopyStyle(font->style, &style);
err = ATSUGlyphGetScreenMetrics(style,
1, &theGlyph, 0, false, false, &metricsH);
err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
err = ATSUGlyphGetIdealMetrics(style,
1, &theGlyph, 0, &metricsV);
err = ATSUGlyphGetScreenMetrics(style,
1, &theGlyph, 0, false, false, &metricsV);
extents.x_bearing = metricsH.sideBearing.x;
extents.y_bearing = metricsV.advance.y;
extents.width =
metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
extents.height =
-metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
extents.x_advance = metricsH.advance.x;
extents.width = metricsH.width/xscale;
extents.height = metricsH.height/yscale;
extents.x_bearing = metricsH.sideBearing.x/xscale;
extents.y_bearing = metricsV.sideBearing.y/yscale - extents.height;
extents.x_advance = metricsH.deviceAdvance.x/xscale;
extents.y_advance = 0;
_cairo_scaled_glyph_set_metrics (scaled_glyph,
@ -578,7 +580,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_atsui_font_t *font = abstract_font;
@ -656,6 +658,10 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
CGContextSetFont(drawingContext, cgFont);
if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) {
CGContextSetShouldAntialias (drawingContext, false);
}
textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
@ -718,9 +724,11 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
for (i = 0; i < num_glyphs; i++) {
CGGlyph theGlyph = glyphs[i].index;
/* round glyph locations to the nearest pixel */
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
CGContextShowGlyphsAtPoint(drawingContext,
glyphs[i].x,
glyphs[i].y,
_cairo_lround (glyphs[i].x),
_cairo_lround (glyphs[i].y),
&theGlyph, 1);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -101,17 +101,17 @@ _cairo_beos_surface_create_internal (BView* view,
bool owns_bitmap_view = false);
static BRect
_cairo_rect_to_brect (const cairo_rectangle_fixed_t* rect)
_cairo_rect_to_brect (const cairo_rectangle_int16_t* rect)
{
// A BRect is one pixel wider than you'd think
return BRect(rect->x, rect->y, rect->x + rect->width - 1,
rect->y + rect->height - 1);
}
static cairo_rectangle_fixed_t
static cairo_rectangle_int16_t
_brect_to_cairo_rect (const BRect& rect)
{
cairo_rectangle_fixed_t retval;
cairo_rectangle_int16_t retval;
retval.x = int(rect.left + 0.5);
retval.y = int(rect.top + 0.5);
retval.width = rect.IntegerWidth() + 1;
@ -550,9 +550,9 @@ _cairo_beos_surface_release_source_image (void *abstract_surfac
static cairo_status_t
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
@ -615,9 +615,9 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
static void
_cairo_beos_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *intersect_rect,
cairo_rectangle_int16_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
fprintf(stderr, "Fallback drawing\n");
@ -768,7 +768,7 @@ _cairo_beos_surface_composite (cairo_operator_t op,
static void
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_fixed_t *rect)
cairo_rectangle_int16_t *rect)
{
BRect brect(_cairo_rect_to_brect(rect));
surface->view->FillRect(brect);
@ -778,7 +778,7 @@ static cairo_int_status_t
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
@ -863,7 +863,7 @@ _cairo_beos_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_beos_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);

Просмотреть файл

@ -563,7 +563,12 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
}
if (other->surface) {
_cairo_surface_clone_similar (target, other->surface, &clip->surface);
_cairo_surface_clone_similar (target, other->surface,
other->surface_rect.x,
other->surface_rect.y,
other->surface_rect.width,
other->surface_rect.height,
&clip->surface);
clip->surface_rect = other->surface_rect;
}
@ -649,6 +654,16 @@ _cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate)
return list;
}
/**
* cairo_rectangle_list_destroy:
* @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles()
*
* Unconditionally frees @rectangle_list and all associated
* references. After this call, the @rectangle_list pointer must not
* be dereferenced.
*
* Since: 1.4
**/
void
cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list)
{

Просмотреть файл

@ -89,19 +89,27 @@ _cairo_color_init_rgb (cairo_color_t *color,
_cairo_color_init_rgba (color, red, green, blue, 1.0);
}
/* We multiply colors by (0x10000 - epsilon), such that we get a uniform
* range even for 0xffff. In other words, (1.0 - epsilon) would convert
* to 0xffff, not 0xfffe.
/* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
* The conversion is designed to divide the input range into 65536
* equally-sized regions. This is achieved by multiplying by 65536 and
* then special-casing the result of an input value of 1.0 so that it
* maps to 65535 instead of 65536.
*/
#define CAIRO_COLOR_ONE_MINUS_EPSILON (65536.0 - 1e-5)
static inline uint16_t _color_to_short (double d)
{
uint32_t i;
i = (uint32_t) (d * 65536);
i -= (i >> 16);
return i;
}
static void
_cairo_color_compute_shorts (cairo_color_t *color)
{
color->red_short = color->red * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
color->green_short = color->green * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
color->blue_short = color->blue * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
color->alpha_short = color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
color->red_short = _color_to_short (color->red * color->alpha);
color->green_short = _color_to_short (color->green * color->alpha);
color->blue_short = _color_to_short (color->blue * color->alpha);
color->alpha_short = _color_to_short (color->alpha);
}
void

Просмотреть файл

@ -548,6 +548,10 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf
static cairo_status_t
_cairo_directfb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -583,19 +587,23 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
cairo_surface_destroy ((cairo_surface_t *)clone);
return CAIRO_STATUS_NO_MEMORY;
}
dst += pitch * src_y;
src += image_src->stride * src_y;
if (image_src->format == CAIRO_FORMAT_A1) {
/* A1 -> A8 */
for (i = 0; i < image_src->height; i++) {
for (j = 0; j < image_src->width; j++)
for (i = 0; i < height; i++) {
for (j = src_x; j < src_x + width; j++)
dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
dst += pitch;
src += image_src->stride;
}
}
else {
for (i = 0; i < image_src->height; i++) {
direct_memcpy( dst, src, image_src->stride );
else {
/* A8 -> A8 */
for (i = 0; i < height; i++) {
direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width );
dst += pitch;
src += image_src->stride;
}
@ -881,10 +889,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
TRANSFORM_POINT (m, sr.x, sr.y, x1, y1);
TRANSFORM_POINT (m, sr.x+sr.w, sr.y+sr.h, x2, y2);
dr.x = floor (x1+.5);
dr.y = floor (y1+.5);
dr.w = floor (x2-x1+.5);
dr.h = floor (y2-y1+.5);
dr.x = _cairo_lround (x1);
dr.y = _cairo_lround (y1);
dr.w = _cairo_lround (x2-x1);
dr.h = _cairo_lround (y2-y1);
D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
@ -1275,8 +1283,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
points[n].x = floor (glyphs[i].x + img->base.device_transform.x0 + .5);
points[n].y = floor (glyphs[i].y + img->base.device_transform.y0 + .5);
points[n].x = _cairo_lround (glyphs[i].x + img->base.device_transform.x0);
points[n].y = _cairo_lround (glyphs[i].y + img->base.device_transform.y0);
if (points[n].x >= surface->width ||
points[n].y >= surface->height ||
@ -1442,7 +1450,7 @@ static cairo_int_status_t
_cairo_directfb_surface_show_glyphs ( void *abstract_dst,
cairo_operator_t op,
cairo_pattern_t *pattern,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -53,9 +53,9 @@
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 3
#define CAIRO_VERSION_MICRO 1
#define CAIRO_VERSION_MICRO 8
#define CAIRO_VERSION_STRING "1.3.1"
#define CAIRO_VERSION_STRING "1.3.8"
@PS_SURFACE_FEATURE@

Просмотреть файл

@ -42,10 +42,56 @@ _cairo_fixed_from_int (int i)
return i << 16;
}
/* This is the "magic number" approach to converting a double into fixed
* point as described here:
*
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
*
* The basic idea is to add a large enough number to the double that the
* literal floating point is moved up to the extent that it forces the
* double's value to be shifted down to the bottom of the mantissa (to make
* room for the large number being added in). Since the mantissa is, at a
* given moment in time, a fixed point integer itself, one can convert a
* float to various fixed point representations by moving around the point
* of a floating point number through arithmetic operations. This behavior
* is reliable on most modern platforms as it is mandated by the IEEE-754
* standard for floating point arithmetic.
*
* For our purposes, a "magic number" must be carefully selected that is
* both large enough to produce the desired point-shifting effect, and also
* has no lower bits in its representation that would interfere with our
* value at the bottom of the mantissa. The magic number is calculated as
* follows:
*
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
*
* where in our case:
* - MANTISSA_SIZE for 64-bit doubles is 52
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
*
* Although this approach provides a very large speedup of this function
* on a wide-array of systems, it does come with two caveats:
*
* 1) It uses banker's rounding as opposed to arithmetic rounding.
* 2) It doesn't function properly if the FPU is in single-precision
* mode.
*/
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
cairo_fixed_t
_cairo_fixed_from_double (double d)
{
return (cairo_fixed_t) floor (d * 65536 + 0.5);
union {
double d;
int32_t i[2];
} u;
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
#ifdef FLOAT_WORDS_BIGENDIAN
return u.i[1];
#else
return u.i[0];
#endif
}
cairo_fixed_t

Просмотреть файл

@ -0,0 +1,73 @@
/*
* Copyright © 2006 Joonas Pihlaja
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef CAIRO_FREELIST_H
#define CAIRO_FREELIST_H
#include "cairoint.h"
#include <stddef.h>
/* Opaque implementation types. */
struct _cairo_freelist;
struct _cairo_freelist_node;
typedef struct _cairo_freelist cairo_freelist_t;
typedef struct _cairo_freelist_node cairo_freelist_node_t;
struct _cairo_freelist_node {
cairo_freelist_node_t *next;
};
struct _cairo_freelist {
cairo_freelist_node_t *first_free_node;
unsigned nodesize;
};
/* Initialise a freelist that will be responsible for allocating
* nodes of size nodesize. */
cairo_private void
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize);
/* Deallocate any nodes in the freelist. */
cairo_private void
_cairo_freelist_fini (cairo_freelist_t *freelist);
/* Allocate a new node from the freelist. If the freelist contains no
* nodes, a new one will be allocated using malloc(). The caller is
* responsible for calling _cairo_freelist_free() or free() on the
* returned node. Returns NULL on memory allocation error. */
cairo_private void *
_cairo_freelist_alloc (cairo_freelist_t *freelist);
/* Allocate a new node from the freelist. If the freelist contains no
* nodes, a new one will be allocated using calloc(). The caller is
* responsible for calling _cairo_freelist_free() or free() on the
* returned node. Returns NULL on memory allocation error. */
cairo_private void *
_cairo_freelist_calloc (cairo_freelist_t *freelist);
/* Return a node to the freelist. This does not deallocate the memory,
* but makes it available for later reuse by
* _cairo_freelist_alloc(). */
cairo_private void
_cairo_freelist_free (cairo_freelist_t *freelist, void *node);
#endif /* CAIRO_FREELIST_H */

Просмотреть файл

@ -0,0 +1,72 @@
/*
* Copyright © 2006 Joonas Pihlaja
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "cairo-freelist-private.h"
void
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
{
memset (freelist, 0, sizeof(cairo_freelist_t));
freelist->nodesize = nodesize;
}
void
_cairo_freelist_fini (cairo_freelist_t *freelist)
{
cairo_freelist_node_t *node = freelist->first_free_node;
while (node) {
cairo_freelist_node_t *next = node->next;
free (node);
node = next;
}
}
void *
_cairo_freelist_alloc (cairo_freelist_t *freelist)
{
if (freelist->first_free_node) {
cairo_freelist_node_t *node = freelist->first_free_node;
freelist->first_free_node = node->next;
return (void*)node;
}
return malloc (freelist->nodesize);
}
void *
_cairo_freelist_calloc (cairo_freelist_t *freelist)
{
void *node = _cairo_freelist_alloc (freelist);
if (node)
memset (node, 0, freelist->nodesize);
return node;
}
void
_cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
{
cairo_freelist_node_t *node = voidnode;
if (node) {
node->next = freelist->first_free_node;
freelist->first_free_node = node;
}
}

Просмотреть файл

@ -1191,8 +1191,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
cairo_surface_destroy (&old_image->base);
cairo_surface_set_device_offset (&(*surface)->base,
- floor (origin_x + 0.5),
- floor (origin_y + 0.5));
- _cairo_lround (origin_x),
- _cairo_lround (origin_y));
return status;
}
@ -1216,8 +1216,8 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
* antialiasing. Here we compute them from the fields of a FcPattern.
*/
static cairo_ft_options_t
_get_pattern_ft_options (FcPattern *pattern)
static void
_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
{
FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
cairo_ft_options_t ft_options;
@ -1341,7 +1341,7 @@ _get_pattern_ft_options (FcPattern *pattern)
if (embolden)
ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
return ft_options;
*ret = ft_options;
}
static void
@ -1581,7 +1581,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
if (!unscaled)
goto FREE_RESOLVED;
ft_options = _get_pattern_ft_options (resolved);
_get_pattern_ft_options (resolved, &ft_options);
new_font = _cairo_ft_scaled_font_create (unscaled,
&toy_face->base,
@ -1996,23 +1996,6 @@ _cairo_ft_ucs4_to_index (void *abstract_font,
return index;
}
static cairo_int_status_t
_cairo_ft_show_glyphs (void *abstract_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_ft_load_truetype_table (void *abstract_font,
unsigned long tag,
@ -2050,7 +2033,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
_cairo_ft_scaled_glyph_init,
NULL, /* text_to_glyphs */
_cairo_ft_ucs4_to_index,
_cairo_ft_show_glyphs,
NULL, /* show_glyphs */
_cairo_ft_load_truetype_table,
};
@ -2154,7 +2137,7 @@ static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
static cairo_font_face_t *
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
cairo_ft_options_t ft_options)
cairo_ft_options_t *ft_options)
{
cairo_ft_font_face_t *font_face;
@ -2163,9 +2146,9 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
font_face;
font_face = font_face->next)
{
if (font_face->ft_options.load_flags == ft_options.load_flags &&
font_face->ft_options.extra_flags == ft_options.extra_flags &&
cairo_font_options_equal (&font_face->ft_options.base, &ft_options.base))
if (font_face->ft_options.load_flags == ft_options->load_flags &&
font_face->ft_options.extra_flags == ft_options->extra_flags &&
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
return cairo_font_face_reference (&font_face->base);
}
@ -2177,7 +2160,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
font_face->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
font_face->ft_options = ft_options;
font_face->ft_options = *ft_options;
font_face->next = unscaled->faces;
unscaled->faces = font_face;
@ -2316,6 +2299,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
cairo_ft_options_t ft_options;
unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
if (unscaled == NULL) {
@ -2323,8 +2307,8 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
font_face = _cairo_ft_font_face_create (unscaled,
_get_pattern_ft_options (pattern));
_get_pattern_ft_options (pattern, &ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face)
@ -2379,7 +2363,7 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
ft_options.extra_flags = 0;
_cairo_font_options_init_default (&ft_options.base);
font_face = _cairo_ft_font_face_create (unscaled, ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face) {

Просмотреть файл

@ -0,0 +1,41 @@
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*/
#ifndef CAIRO_GLITZ_PRIVATE_H
#define CAIRO_GLITZ_PRIVATE_H
#include "cairoint.h"
#include "cairo-glitz.h"
slim_hidden_proto (cairo_glitz_surface_create);
#endif /* CAIRO_GLITZ_PRIVATE_H */

Просмотреть файл

@ -26,6 +26,7 @@
#include "cairoint.h"
#include "cairo-glitz.h"
#include "cairo-glitz-private.h"
typedef struct _cairo_glitz_surface {
cairo_surface_t base;
@ -207,8 +208,9 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
}
/* clear out the glitz clip; the clip affects glitz_get_pixels */
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
if (surface->clip)
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
glitz_get_pixels (surface->surface,
x1, y1,
@ -219,8 +221,14 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
surface->base.current_clip_serial = 0;
_cairo_surface_set_clip (&surface->base, surface->base.clip);
if (surface->clip) {
glitz_box_t *box;
int n;
box = (glitz_box_t *) pixman_region_rects (surface->clip);
n = pixman_region_num_rects (surface->clip);
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
}
image = (cairo_image_surface_t *)
_cairo_image_surface_create_with_masks (pixels,
@ -243,8 +251,12 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
static cairo_status_t
_cairo_glitz_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image,
int x_dst,
int y_dst)
int src_x,
int src_y,
int width,
int height,
int x_dst,
int y_dst)
{
cairo_glitz_surface_t *surface = abstract_surface;
glitz_buffer_t *buffer;
@ -264,8 +276,8 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
pf.masks.red_mask = rm;
pf.masks.green_mask = gm;
pf.masks.blue_mask = bm;
pf.xoffset = 0;
pf.skip_lines = 0;
pf.xoffset = src_x;
pf.skip_lines = src_y;
/* check for negative stride */
if (image->stride < 0)
@ -287,7 +299,7 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
glitz_set_pixels (surface->surface,
x_dst, y_dst,
image->width, image->height,
width, height,
&pf,
buffer);
@ -347,7 +359,8 @@ _cairo_glitz_surface_release_dest_image (void *abstract_surfa
{
cairo_glitz_surface_t *surface = abstract_surface;
_cairo_glitz_surface_set_image (surface, image,
_cairo_glitz_surface_set_image (surface, image, 0, 0,
image->width, image->height,
image_rect->x, image_rect->y);
cairo_surface_destroy (&image->base);
@ -356,6 +369,10 @@ _cairo_glitz_surface_release_dest_image (void *abstract_surfa
static cairo_status_t
_cairo_glitz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -374,6 +391,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
{
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
cairo_content_t content;
cairo_rectangle_int16_t image_extent;
cairo_rectangle_int16_t extent;
content = _cairo_content_from_format (image_src->format);
@ -384,7 +403,21 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
_cairo_glitz_surface_set_image (clone, image_src, 0, 0);
image_extent.x = 0;
image_extent.y = 0;
image_extent.width = image_src->width;
image_extent.height = image_src->height;
extent.x = src_x;
extent.y = src_y;
extent.width = width;
extent.height = height;
_cairo_rectangle_intersect(&extent, &image_extent);
_cairo_glitz_surface_set_image (clone, image_src,
extent.x, extent.y,
extent.width, extent.height,
extent.x, extent.y);
*clone_out = &clone->base;
@ -1183,7 +1216,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_glitz_surface_set_image (mask, image, 0, 0);
_cairo_glitz_surface_set_image (mask, image, 0, 0, width, height, 0, 0);
cairo_surface_destroy(&image->base);
}
_cairo_glitz_surface_set_attributes (src, &attributes);
@ -1665,10 +1700,14 @@ _cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface,
drawable = glitz_surface_get_drawable (surface->surface);
switch (format) {
case CAIRO_FORMAT_A1:
case CAIRO_FORMAT_A8:
surface_format =
glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
break;
case CAIRO_FORMAT_RGB24:
ASSERT_NOT_REACHED;
break;
case CAIRO_FORMAT_ARGB32:
surface_format =
glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32);
@ -1870,7 +1909,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
int dst_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_glitz_surface_attributes_t attributes;
@ -1941,6 +1980,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (!buffer)
goto FAIL2;
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++)
{
status = _cairo_scaled_glyph_lookup (scaled_font,
@ -1953,6 +1994,17 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
goto UNLOCK;
}
glyph_private = scaled_glyphs[i]->surface_private;
if (!glyph_private || !glyph_private->area)
{
status = _cairo_glitz_surface_add_glyph (dst,
scaled_font,
scaled_glyphs[i]);
if (status != CAIRO_STATUS_SUCCESS) {
num_glyphs = i;
goto UNLOCK;
}
}
glyph_private = scaled_glyphs[i]->surface_private;
if (glyph_private && glyph_private->area)
{
@ -1963,8 +2015,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
x1 = floor (glyphs[i].x + 0.5) + x_offset;
y1 = floor (glyphs[i].y + 0.5) + y_offset;
x1 = _cairo_lround (glyphs[i].x) + x_offset;
y1 = _cairo_lround (glyphs[i].y) + y_offset;
x2 = x1 + glyph_private->area->width;
y2 = y1 + glyph_private->area->height;
@ -1988,42 +2040,18 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
glyph_private = scaled_glyphs[i]->surface_private;
if (!glyph_private || !glyph_private->area)
{
status = _cairo_glitz_surface_add_glyph (dst,
scaled_font,
scaled_glyphs[i]);
if (status)
goto UNLOCK;
int glyph_width, glyph_height;
glyph_private = scaled_glyphs[i]->surface_private;
}
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
x1 = floor (glyphs[i].x + 0.5) + x_offset;
y1 = floor (glyphs[i].y + 0.5) + y_offset;
if (glyph_private->area)
{
if (glyph_private->area->width)
{
x2 = x1 + glyph_private->area->width;
y2 = y1 + glyph_private->area->height;
WRITE_BOX (vertices, x1, y1, x2, y2,
&glyph_private->p1, &glyph_private->p2);
glyph_private->locked = TRUE;
cached_glyphs++;
}
}
else
{
image = &scaled_glyphs[i]->surface->base;
glyph_width = scaled_glyphs[i]->surface->width;
glyph_height = scaled_glyphs[i]->surface->height;
status =
_cairo_glitz_surface_clone_similar (abstract_surface,
image,
0,
0,
glyph_width,
glyph_height,
(cairo_surface_t **)
&clone);
if (status)
@ -2037,8 +2065,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
src_y + attributes.base.y_offset + y1,
0, 0,
x1, y1,
scaled_glyphs[i]->surface->width,
scaled_glyphs[i]->surface->height);
glyph_width,
glyph_height);
cairo_surface_destroy (&clone->base);
@ -2081,6 +2109,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
}
UNLOCK:
_cairo_scaled_font_thaw_cache (scaled_font);
if (cached_glyphs)
{
for (i = 0; i < num_glyphs; i++)
@ -2196,3 +2226,4 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
return (cairo_surface_t *) crsurface;
}
slim_hidden_def (cairo_glitz_surface_create);

Просмотреть файл

@ -61,6 +61,12 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
static void
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_glyph_t *transformed_glyphs);
/**
* _cairo_gstate_create:
* @target: a #cairo_surface_t, not NULL
@ -712,17 +718,12 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
double *x2, double *y2,
cairo_bool_t *is_tight)
{
double width = *x2 - *x1;
double height = *y2 - *y1;
cairo_matrix_t matrix_inverse;
cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse,
&gstate->target->device_transform_inverse);
cairo_matrix_transform_bounding_box (
&matrix_inverse, x1, y1, &width, &height, is_tight);
*x2 = *x1 + width;
*y2 = *y1 + height;
cairo_matrix_transform_bounding_box (&matrix_inverse,
x1, y1, x2, y2, is_tight);
}
/* XXX: NYI
@ -1117,7 +1118,6 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
@ -1447,7 +1447,7 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
@ -1464,6 +1464,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
@ -1472,7 +1473,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_status_t status;
cairo_pattern_union_t source_pattern;
cairo_glyph_t *transformed_glyphs;
int i;
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
if (gstate->source->status)
return gstate->source->status;
@ -1485,20 +1487,17 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
if (status)
return status;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
_cairo_gstate_user_to_backend (gstate,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
if (num_glyphs <= STACK_GLYPHS_LEN) {
transformed_glyphs = stack_transformed_glyphs;
} else {
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_surface_show_glyphs (gstate->target,
@ -1509,46 +1508,47 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
gstate->scaled_font);
_cairo_pattern_fini (&source_pattern.base);
free (transformed_glyphs);
if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs);
return status;
}
cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path)
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path)
{
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_glyph_t *transformed_glyphs;
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (num_glyphs < STACK_GLYPHS_LEN)
transformed_glyphs = stack_transformed_glyphs;
else
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
_cairo_gstate_user_to_backend (gstate,
&(transformed_glyphs[i].x),
&(transformed_glyphs[i].y));
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
path);
free (transformed_glyphs);
if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs);
return status;
}
#undef STACK_GLYPHS_LEN
cairo_status_t
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
@ -1564,3 +1564,66 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
{
return gstate->antialias;
}
/**
* _cairo_gstate_transform_glyphs_to_backend:
* @gstate: a #cairo_gstate_t
* @glyphs: the array of #cairo_glyph_t objects to be transformed
* @num_glyphs: the number of elements in @glyphs
* @transformed_glyphs: a pre-allocated array of at least @num_glyphs
* #cairo_glyph_t objects
*
* Transform an array of glyphs to backend space by first adding the offset
* of the font matrix, then transforming from user space to backend space.
* The result of the transformation is placed in @transformed_glyphs.
**/
static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_glyph_t *transformed_glyphs)
{
int i;
cairo_matrix_t *ctm = &gstate->ctm;
cairo_matrix_t *device_transform = &gstate->target->device_transform;
if (_cairo_matrix_is_identity (ctm) &&
_cairo_matrix_is_identity (device_transform) &&
gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
{
memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
}
else if (_cairo_matrix_is_translation (ctm) &&
_cairo_matrix_is_translation (device_transform))
{
double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + tx;
transformed_glyphs[i].y = glyphs[i].y + ty;
}
}
else
{
cairo_matrix_t aggregate_transform;
cairo_matrix_init_translate (&aggregate_transform,
gstate->font_matrix.x0,
gstate->font_matrix.y0);
cairo_matrix_multiply (&aggregate_transform,
&aggregate_transform, ctm);
cairo_matrix_multiply (&aggregate_transform,
&aggregate_transform, device_transform);
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&aggregate_transform,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
}
}
}

Просмотреть файл

@ -36,6 +36,52 @@
#include "cairoint.h"
const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
{
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_INVALID_FORMAT, /* status */
FALSE, /* finished */
{ 0, /* size */
0, /* num_elements */
0, /* element_size */
NULL, /* elements */
}, /* user_data */
{ 1.0, 0.0,
0.0, 1.0,
0.0, 0.0
}, /* device_transform */
{ 1.0, 0.0,
0.0, 1.0,
0.0, 0.0
}, /* device_transform_inverse */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
0, /* next_clip_serial */
0, /* current_clip_serial */
FALSE, /* is_snapshot */
FALSE, /* has_font_options */
{ CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
} /* font_options */
}, /* base */
CAIRO_FORMAT_ARGB32, /* format */
NULL, /* data */
FALSE, /* owns_data */
FALSE, /* has_clip */
0, /* width */
0, /* height */
0, /* stride */
0, /* depth */
NULL /* pixman_image */
};
static int
_cairo_format_bpp (cairo_format_t format)
{
@ -248,8 +294,10 @@ cairo_image_surface_create (cairo_format_t format,
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format))
return (cairo_surface_t*) &_cairo_surface_nil;
if (! CAIRO_FORMAT_VALID (format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
}
pixman_format = _create_pixman_format (format);
if (pixman_format == NULL) {
@ -617,6 +665,10 @@ _cairo_image_surface_release_dest_image (void *abstract_surfa
static cairo_status_t
_cairo_image_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_image_surface_t *surface = abstract_surface;

Просмотреть файл

@ -357,35 +357,30 @@ slim_hidden_def(cairo_matrix_transform_point);
void
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height,
double *x1, double *y1,
double *x2, double *y2,
cairo_bool_t *is_tight)
{
int i;
double quad_x[4], quad_y[4];
double dx1, dy1;
double dx2, dy2;
double min_x, max_x;
double min_y, max_y;
quad_x[0] = *x;
quad_y[0] = *y;
quad_x[0] = *x1;
quad_y[0] = *y1;
cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
dx1 = *width;
dy1 = 0;
cairo_matrix_transform_distance (matrix, &dx1, &dy1);
quad_x[1] = quad_x[0] + dx1;
quad_y[1] = quad_y[0] + dy1;
quad_x[1] = *x2;
quad_y[1] = *y1;
cairo_matrix_transform_point (matrix, &quad_x[1], &quad_y[1]);
dx2 = 0;
dy2 = *height;
cairo_matrix_transform_distance (matrix, &dx2, &dy2);
quad_x[2] = quad_x[0] + dx2;
quad_y[2] = quad_y[0] + dy2;
quad_x[2] = *x1;
quad_y[2] = *y2;
cairo_matrix_transform_point (matrix, &quad_x[2], &quad_y[2]);
quad_x[3] = quad_x[0] + dx1 + dx2;
quad_y[3] = quad_y[0] + dy1 + dy2;
quad_x[3] = *x2;
quad_y[3] = *y2;
cairo_matrix_transform_point (matrix, &quad_x[3], &quad_y[3]);
min_x = max_x = quad_x[0];
min_y = max_y = quad_y[0];
@ -402,10 +397,10 @@ cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
max_y = quad_y[i];
}
*x = min_x;
*y = min_y;
*width = max_x - min_x;
*height = max_y - min_y;
*x1 = min_x;
*y1 = min_y;
*x2 = max_x;
*y2 = max_y;
if (is_tight) {
/* it's tight if and only if the four corner points form an axis-aligned
@ -555,31 +550,34 @@ _cairo_matrix_is_identity (const cairo_matrix_t *matrix)
}
cairo_bool_t
_cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
int *itx, int *ity)
_cairo_matrix_is_translation (const cairo_matrix_t *matrix)
{
cairo_bool_t is_integer_translation;
cairo_fixed_t x0_fixed, y0_fixed;
return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
matrix->xy == 0.0 && matrix->yy == 1.0);
}
x0_fixed = _cairo_fixed_from_double (m->x0);
y0_fixed = _cairo_fixed_from_double (m->y0);
cairo_bool_t
_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
int *itx, int *ity)
{
if (_cairo_matrix_is_translation (matrix))
{
cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0);
cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0);
is_integer_translation = ((m->xx == 1.0) &&
(m->yx == 0.0) &&
(m->xy == 0.0) &&
(m->yy == 1.0) &&
(_cairo_fixed_is_integer(x0_fixed)) &&
(_cairo_fixed_is_integer(y0_fixed)));
if (_cairo_fixed_is_integer (x0_fixed) &&
_cairo_fixed_is_integer (y0_fixed))
{
if (itx)
*itx = _cairo_fixed_integer_part (x0_fixed);
if (ity)
*ity = _cairo_fixed_integer_part (y0_fixed);
if (! is_integer_translation)
return FALSE;
return TRUE;
}
}
if (itx)
*itx = _cairo_fixed_integer_part(x0_fixed);
if (ity)
*ity = _cairo_fixed_integer_part(y0_fixed);
return TRUE;
return FALSE;
}
/*
@ -728,15 +726,26 @@ void
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
pixman_transform_t *pixman_transform)
{
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
static const pixman_transform_t pixman_identity_transform = {{
{1 << 16, 0, 0},
{ 0, 1 << 16, 0},
{ 0, 0, 1 << 16}
}};
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
if (_cairo_matrix_is_identity (matrix)) {
*pixman_transform = pixman_identity_transform;
}
else {
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
pixman_transform->matrix[2][0] = 0;
pixman_transform->matrix[2][1] = 0;
pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1);
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
pixman_transform->matrix[2][0] = 0;
pixman_transform->matrix[2][1] = 0;
pixman_transform->matrix[2][2] = 1 << 16;
}
}

Просмотреть файл

@ -416,7 +416,7 @@ static cairo_int_status_t
_cairo_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -498,7 +498,8 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
cairo_surface_t *new_surf = NULL;
_cairo_surface_clone_similar (dummy, pat_surf, &new_surf);
_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
rect.width, rect.height, &new_surf);
cairo_surface_destroy(dummy);
@ -1063,6 +1064,10 @@ _cairo_nquartz_surface_create_similar (void *abstract_surface,
static cairo_status_t
_cairo_nquartz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
@ -1142,7 +1147,7 @@ _cairo_nquartz_surface_clone_similar (void *abstract_surface,
nquartz_image_to_png (quartz_image, NULL);
CGContextDrawImage (new_surface->cgContext,
CGRectMake (0, 0, CGImageGetWidth (quartz_image), CGImageGetHeight (quartz_image)),
CGRectMake (src_x, src_y, width, height),
quartz_image);
CGImageRelease (quartz_image);
@ -1341,7 +1346,7 @@ static cairo_int_status_t
_cairo_nquartz_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -437,7 +437,7 @@ static cairo_int_status_t
_cairo_paginated_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -1,481 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@redhat.com>
*/
#include "cairo-path-data-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-gstate-private.h"
const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
int count;
double tolerance;
cairo_point_t current_point;
} cpdc_t;
static cairo_status_t
_cpdc_move_to (void *closure, cairo_point_t *point)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
cpdc->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdc_line_to (void *closure, cairo_point_t *point)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
cpdc->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdc_curve_to (void *closure,
cairo_point_t *p1,
cairo_point_t *p2,
cairo_point_t *p3)
{
cpdc_t *cpdc = closure;
cpdc->count += 4;
cpdc->current_point = *p3;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdc_curve_to_flatten (void *closure,
cairo_point_t *p1,
cairo_point_t *p2,
cairo_point_t *p3)
{
cpdc_t *cpdc = closure;
cairo_status_t status;
cairo_spline_t spline;
int i;
cairo_point_t *p0 = &cpdc->current_point;
status = _cairo_spline_init (&spline, p0, p1, p2, p3);
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_spline_decompose (&spline, cpdc->tolerance);
if (status)
goto out;
for (i=1; i < spline.num_points; i++)
_cpdc_line_to (cpdc, &spline.points[i]);
cpdc->current_point = *p3;
status = CAIRO_STATUS_SUCCESS;
out:
_cairo_spline_fini (&spline);
return status;
}
static cairo_status_t
_cpdc_close_path (void *closure)
{
cpdc_t *cpdc = closure;
cpdc->count += 1;
return CAIRO_STATUS_SUCCESS;
}
static int
_cairo_path_data_count (cairo_path_t *path,
cairo_path_fixed_t *path_fixed,
double tolerance,
cairo_bool_t flatten)
{
cpdc_t cpdc;
cpdc.count = 0;
cpdc.tolerance = tolerance;
cpdc.current_point.x = 0;
cpdc.current_point.y = 0;
_cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpdc_move_to,
_cpdc_line_to,
flatten ?
_cpdc_curve_to_flatten :
_cpdc_curve_to,
_cpdc_close_path,
&cpdc);
return cpdc.count;
}
/* Closure for path interpretation. */
typedef struct cairo_path_data_populate {
cairo_path_data_t *data;
cairo_gstate_t *gstate;
cairo_point_t current_point;
} cpdp_t;
static cairo_status_t
_cpdp_move_to (void *closure, cairo_point_t *point)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
double x, y;
x = _cairo_fixed_to_double (point->x);
y = _cairo_fixed_to_double (point->y);
_cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
data->header.type = CAIRO_PATH_MOVE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
cpdp->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdp_line_to (void *closure, cairo_point_t *point)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
double x, y;
x = _cairo_fixed_to_double (point->x);
y = _cairo_fixed_to_double (point->y);
_cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
data->header.type = CAIRO_PATH_LINE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
cpdp->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdp_curve_to (void *closure,
cairo_point_t *p1,
cairo_point_t *p2,
cairo_point_t *p3)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
double x1, y1;
double x2, y2;
double x3, y3;
x1 = _cairo_fixed_to_double (p1->x);
y1 = _cairo_fixed_to_double (p1->y);
_cairo_gstate_backend_to_user (cpdp->gstate, &x1, &y1);
x2 = _cairo_fixed_to_double (p2->x);
y2 = _cairo_fixed_to_double (p2->y);
_cairo_gstate_backend_to_user (cpdp->gstate, &x2, &y2);
x3 = _cairo_fixed_to_double (p3->x);
y3 = _cairo_fixed_to_double (p3->y);
_cairo_gstate_backend_to_user (cpdp->gstate, &x3, &y3);
data->header.type = CAIRO_PATH_CURVE_TO;
data->header.length = 4;
/* We index from 1 to leave room for data->header */
data[1].point.x = x1;
data[1].point.y = y1;
data[2].point.x = x2;
data[2].point.y = y2;
data[3].point.x = x3;
data[3].point.y = y3;
cpdp->data += data->header.length;
cpdp->current_point = *p3;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cpdp_curve_to_flatten (void *closure,
cairo_point_t *p1,
cairo_point_t *p2,
cairo_point_t *p3)
{
cpdp_t *cpdp = closure;
cairo_status_t status;
cairo_spline_t spline;
int i;
cairo_point_t *p0 = &cpdp->current_point;
status = _cairo_spline_init (&spline, p0, p1, p2, p3);
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_spline_decompose (&spline, cpdp->gstate->tolerance);
if (status)
goto out;
for (i=1; i < spline.num_points; i++)
_cpdp_line_to (cpdp, &spline.points[i]);
cpdp->current_point = *p3;
status = CAIRO_STATUS_SUCCESS;
out:
_cairo_spline_fini (&spline);
return status;
}
static cairo_status_t
_cpdp_close_path (void *closure)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_CLOSE_PATH;
data->header.length = 1;
cpdp->data += data->header.length;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_path_data_populate (cairo_path_t *path,
cairo_path_fixed_t *path_fixed,
cairo_gstate_t *gstate,
cairo_bool_t flatten)
{
cpdp_t cpdp;
cpdp.data = path->data;
cpdp.gstate = gstate;
cpdp.current_point.x = 0;
cpdp.current_point.y = 0;
_cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpdp_move_to,
_cpdp_line_to,
flatten ?
_cpdp_curve_to_flatten :
_cpdp_curve_to,
_cpdp_close_path,
&cpdp);
/* Sanity check the count */
assert (cpdp.data - path->data == path->num_data);
}
static cairo_path_t *
_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
cairo_gstate_t *gstate,
cairo_bool_t flatten)
{
cairo_path_t *path;
path = malloc (sizeof (cairo_path_t));
if (path == NULL)
return (cairo_path_t*) &_cairo_path_nil;
path->num_data = _cairo_path_data_count (path, path_fixed,
gstate->tolerance, flatten);
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
if (path->data == NULL) {
free (path);
return (cairo_path_t*) &_cairo_path_nil;
}
path->status = CAIRO_STATUS_SUCCESS;
_cairo_path_data_populate (path, path_fixed,
gstate, flatten);
return path;
}
/**
* cairo_path_destroy:
* @path: a path previously returned by either cairo_copy_path() or
* cairo_copy_path_flat().
*
* Immediately releases all memory associated with @path. After a call
* to cairo_path_destroy() the @path pointer is no longer valid and
* should not be used further.
*
* NOTE: cairo_path_destroy function should only be called with a
* pointer to a #cairo_path_t returned by a cairo function. Any path
* that is created manually (ie. outside of cairo) should be destroyed
* manually as well.
**/
void
cairo_path_destroy (cairo_path_t *path)
{
if (path == NULL || path == &_cairo_path_nil)
return;
free (path->data);
path->num_data = 0;
free (path);
}
/**
* _cairo_path_data_create:
* @path: a fixed-point, device-space path to be converted and copied
* @gstate: the current graphics state
*
* Creates a user-space #cairo_path_t copy of the given device-space
* @path. The @gstate parameter provides the inverse CTM for the
* conversion.
*
* Return value: the new copy of the path. If there is insufficient
* memory a pointer to a special static cairo_path_nil will be
* returned instead with status==CAIRO_STATUS_NO_MEMORY and
* data==NULL.
**/
cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (path, gstate, FALSE);
}
/**
* _cairo_path_data_create_flat:
* @path: a fixed-point, device-space path to be flattened, converted and copied
* @gstate: the current graphics state
*
* Creates a flattened, user-space #cairo_path_t copy of the given
* device-space @path. The @gstate parameter provide the inverse CTM
* for the conversion, as well as the tolerance value to control the
* accuracy of the flattening.
*
* Return value: the flattened copy of the path. If there is insufficient
* memory a pointer to a special static cairo_path_nil will be
* returned instead with status==CAIRO_STATUS_NO_MEMORY and
* data==NULL.
**/
cairo_path_t *
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (path, gstate, TRUE);
}
/**
* _cairo_path_data_append_to_context:
* @path: the path data to be appended
* @cr: a cairo context
*
* Append @path to the current path within @cr.
*
* Return value: CAIRO_STATUS_INVALID_PATH_DATA if the data in @path
* is invalid, and CAIRO_STATUS_SUCCESS otherwise.
**/
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
cairo_t *cr)
{
int i;
cairo_path_data_t *p;
for (i=0; i < path->num_data; i += path->data[i].header.length) {
p = &path->data[i];
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
cairo_move_to (cr,
p[1].point.x, p[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
cairo_line_to (cr,
p[1].point.x, p[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
if (p->header.length != 4)
return CAIRO_STATUS_INVALID_PATH_DATA;
cairo_curve_to (cr,
p[1].point.x, p[1].point.y,
p[2].point.x, p[2].point.y,
p[3].point.x, p[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
if (p->header.length != 1)
return CAIRO_STATUS_INVALID_PATH_DATA;
cairo_close_path (cr);
break;
default:
return CAIRO_STATUS_INVALID_PATH_DATA;
}
}
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -194,9 +194,9 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
if (status)
goto BAIL;
status = _cairo_traps_tessellate_polygon (filler.traps,
&filler.polygon,
fill_rule);
status = _cairo_bentley_ottmann_tessellate_polygon (filler.traps,
&filler.polygon,
fill_rule);
if (status)
goto BAIL;

Просмотреть файл

@ -0,0 +1,639 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-path-fixed-private.h"
/* private functions */
static cairo_status_t
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
cairo_point_t *points,
int num_points);
static void
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
cairo_path_op_buf_t *op_buf);
static void
_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
cairo_path_arg_buf_t *arg_buf);
static cairo_path_op_buf_t *
_cairo_path_op_buf_create (void);
static void
_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf);
static void
_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
cairo_path_op_t op);
static cairo_path_arg_buf_t *
_cairo_path_arg_buf_create (void);
static void
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf);
static void
_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
cairo_point_t *points,
int num_points);
void
_cairo_path_fixed_init (cairo_path_fixed_t *path)
{
path->op_buf_head = NULL;
path->op_buf_tail = NULL;
path->arg_buf_head = NULL;
path->arg_buf_tail = NULL;
path->current_point.x = 0;
path->current_point.y = 0;
path->has_current_point = FALSE;
path->last_move_point = path->current_point;
}
cairo_status_t
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
cairo_path_fixed_t *other)
{
cairo_path_op_buf_t *op_buf, *other_op_buf;
cairo_path_arg_buf_t *arg_buf, *other_arg_buf;
_cairo_path_fixed_init (path);
path->current_point = other->current_point;
path->has_current_point = other->has_current_point;
path->last_move_point = other->last_move_point;
for (other_op_buf = other->op_buf_head;
other_op_buf;
other_op_buf = other_op_buf->next)
{
op_buf = _cairo_path_op_buf_create ();
if (op_buf == NULL) {
_cairo_path_fixed_fini (path);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t));
_cairo_path_fixed_add_op_buf (path, op_buf);
}
for (other_arg_buf = other->arg_buf_head;
other_arg_buf;
other_arg_buf = other_arg_buf->next)
{
arg_buf = _cairo_path_arg_buf_create ();
if (arg_buf == NULL) {
_cairo_path_fixed_fini (path);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t));
_cairo_path_fixed_add_arg_buf (path, arg_buf);
}
return CAIRO_STATUS_SUCCESS;
}
cairo_path_fixed_t *
_cairo_path_fixed_create (void)
{
cairo_path_fixed_t *path = malloc (sizeof (cairo_path_fixed_t));
if (!path)
return NULL;
_cairo_path_fixed_init (path);
return path;
}
void
_cairo_path_fixed_fini (cairo_path_fixed_t *path)
{
cairo_path_op_buf_t *op_buf;
cairo_path_arg_buf_t *arg_buf;
while (path->op_buf_head) {
op_buf = path->op_buf_head;
path->op_buf_head = op_buf->next;
_cairo_path_op_buf_destroy (op_buf);
}
path->op_buf_tail = NULL;
while (path->arg_buf_head) {
arg_buf = path->arg_buf_head;
path->arg_buf_head = arg_buf->next;
_cairo_path_arg_buf_destroy (arg_buf);
}
path->arg_buf_tail = NULL;
path->has_current_point = FALSE;
}
void
_cairo_path_fixed_destroy (cairo_path_fixed_t *path)
{
_cairo_path_fixed_fini (path);
free (path);
}
cairo_status_t
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y)
{
cairo_status_t status;
cairo_point_t point;
point.x = x;
point.y = y;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (status)
return status;
path->current_point = point;
path->has_current_point = TRUE;
path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
{
path->has_current_point = FALSE;
}
cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
cairo_fixed_t x, y;
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
y = path->current_point.y + dy;
return _cairo_path_fixed_move_to (path, x, y);
}
cairo_status_t
_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y)
{
cairo_status_t status;
cairo_point_t point;
point.x = x;
point.y = y;
/* When there is not yet a current point, the line_to operation
* becomes a move_to instead. Note: We have to do this by
* explicitly calling into _cairo_path_fixed_line_to to ensure
* that the last_move_point state is updated properly.
*/
if (! path->has_current_point)
status = _cairo_path_fixed_move_to (path, point.x, point.y);
else
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (status)
return status;
path->current_point = point;
path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
cairo_fixed_t x, y;
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
y = path->current_point.y + dy;
return _cairo_path_fixed_line_to (path, x, y);
}
cairo_status_t
_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t x0, cairo_fixed_t y0,
cairo_fixed_t x1, cairo_fixed_t y1,
cairo_fixed_t x2, cairo_fixed_t y2)
{
cairo_status_t status;
cairo_point_t point[3];
point[0].x = x0; point[0].y = y0;
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
if (! path->has_current_point) {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
&point[0], 1);
if (status)
return status;
}
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
path->current_point = point[2];
path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t dx0, cairo_fixed_t dy0,
cairo_fixed_t dx1, cairo_fixed_t dy1,
cairo_fixed_t dx2, cairo_fixed_t dy2)
{
cairo_fixed_t x0, y0;
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x0 = path->current_point.x + dx0;
y0 = path->current_point.y + dy0;
x1 = path->current_point.x + dx1;
y1 = path->current_point.y + dy1;
x2 = path->current_point.x + dx2;
y2 = path->current_point.y + dy2;
return _cairo_path_fixed_curve_to (path,
x0, y0,
x1, y1,
x2, y2);
}
cairo_status_t
_cairo_path_fixed_close_path (cairo_path_fixed_t *path)
{
cairo_status_t status;
if (! path->has_current_point)
return CAIRO_STATUS_SUCCESS;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
if (status)
return status;
status = _cairo_path_fixed_move_to (path,
path->last_move_point.x,
path->last_move_point.y);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
cairo_fixed_t *x,
cairo_fixed_t *y)
{
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
*x = path->current_point.x;
*y = path->current_point.y;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
cairo_point_t *points,
int num_points)
{
if (path->op_buf_tail == NULL ||
path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
{
cairo_path_op_buf_t *op_buf;
op_buf = _cairo_path_op_buf_create ();
if (op_buf == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_path_fixed_add_op_buf (path, op_buf);
}
_cairo_path_op_buf_add_op (path->op_buf_tail, op);
if (path->arg_buf_tail == NULL ||
path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
{
cairo_path_arg_buf_t *arg_buf;
arg_buf = _cairo_path_arg_buf_create ();
if (arg_buf == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_path_fixed_add_arg_buf (path, arg_buf);
}
_cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points);
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
cairo_path_op_buf_t *op_buf)
{
op_buf->next = NULL;
op_buf->prev = path->op_buf_tail;
if (path->op_buf_tail) {
path->op_buf_tail->next = op_buf;
} else {
path->op_buf_head = op_buf;
}
path->op_buf_tail = op_buf;
}
static void
_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
cairo_path_arg_buf_t *arg_buf)
{
arg_buf->next = NULL;
arg_buf->prev = path->arg_buf_tail;
if (path->arg_buf_tail) {
path->arg_buf_tail->next = arg_buf;
} else {
path->arg_buf_head = arg_buf;
}
path->arg_buf_tail = arg_buf;
}
static cairo_path_op_buf_t *
_cairo_path_op_buf_create (void)
{
cairo_path_op_buf_t *op_buf;
op_buf = malloc (sizeof (cairo_path_op_buf_t));
if (op_buf) {
op_buf->num_ops = 0;
op_buf->next = NULL;
}
return op_buf;
}
static void
_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf)
{
free (op_buf);
}
static void
_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
cairo_path_op_t op)
{
op_buf->op[op_buf->num_ops++] = op;
}
static cairo_path_arg_buf_t *
_cairo_path_arg_buf_create (void)
{
cairo_path_arg_buf_t *arg_buf;
arg_buf = malloc (sizeof (cairo_path_arg_buf_t));
if (arg_buf) {
arg_buf->num_points = 0;
arg_buf->next = NULL;
}
return arg_buf;
}
static void
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf)
{
free (arg_buf);
}
static void
_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
cairo_point_t *points,
int num_points)
{
int i;
for (i=0; i < num_points; i++) {
arg_buf->points[arg_buf->num_points++] = points[i];
}
}
#define CAIRO_PATH_OP_MAX_ARGS 3
static int const num_args[] =
{
1, /* cairo_path_move_to */
1, /* cairo_path_op_line_to */
3, /* cairo_path_op_curve_to */
0, /* cairo_path_op_close_path */
};
cairo_status_t
_cairo_path_fixed_interpret (cairo_path_fixed_t *path,
cairo_direction_t dir,
cairo_path_fixed_move_to_func_t *move_to,
cairo_path_fixed_line_to_func_t *line_to,
cairo_path_fixed_curve_to_func_t *curve_to,
cairo_path_fixed_close_path_func_t *close_path,
void *closure)
{
cairo_status_t status;
int i, arg;
cairo_path_op_buf_t *op_buf;
cairo_path_op_t op;
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
int buf_i = 0;
cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
int step = forward ? 1 : -1;
for (op_buf = forward ? path->op_buf_head : path->op_buf_tail;
op_buf;
op_buf = forward ? op_buf->next : op_buf->prev)
{
int start, stop;
if (forward) {
start = 0;
stop = op_buf->num_ops;
} else {
start = op_buf->num_ops - 1;
stop = -1;
}
for (i=start; i != stop; i += step) {
op = op_buf->op[i];
if (! forward) {
if (buf_i == 0) {
arg_buf = arg_buf->prev;
buf_i = arg_buf->num_points;
}
buf_i -= num_args[op];
}
for (arg = 0; arg < num_args[op]; arg++) {
point[arg] = arg_buf->points[buf_i];
buf_i++;
if (buf_i >= arg_buf->num_points) {
arg_buf = arg_buf->next;
buf_i = 0;
}
}
if (! forward) {
buf_i -= num_args[op];
}
switch (op) {
case CAIRO_PATH_OP_MOVE_TO:
status = (*move_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_LINE_TO:
status = (*line_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_CURVE_TO:
status = (*curve_to) (closure, &point[0], &point[1], &point[2]);
break;
case CAIRO_PATH_OP_CLOSE_PATH:
default:
status = (*close_path) (closure);
break;
}
if (status)
return status;
}
}
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t offx,
cairo_fixed_t offy,
cairo_fixed_t scalex,
cairo_fixed_t scaley)
{
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
int i;
cairo_int64_t i64temp;
cairo_fixed_t fixedtemp;
while (arg_buf) {
for (i = 0; i < arg_buf->num_points; i++) {
if (scalex == CAIRO_FIXED_ONE) {
arg_buf->points[i].x += offx;
} else {
fixedtemp = arg_buf->points[i].x + offx;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
if (scaley == CAIRO_FIXED_ONE) {
arg_buf->points[i].y += offy;
} else {
fixedtemp = arg_buf->points[i].y + offy;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
}
arg_buf = arg_buf->next;
}
}
/**
* _cairo_path_fixed_device_transform:
* @path: a #cairo_path_fixed_t to be transformed
* @device_transform: a matrix with only scaling/translation (no rotation or shear)
*
* Transform the fixed-point path according to the scaling and
* translation of the given matrix. This function assert()s that the
* given matrix has no rotation or shear elements, (that is, xy and yx
* are 0.0).
**/
void
_cairo_path_fixed_device_transform (cairo_path_fixed_t *path,
cairo_matrix_t *device_transform)
{
assert (device_transform->yx == 0.0 && device_transform->xy == 0.0);
/* XXX: FRAGILE: I'm not really sure whether we're doing the
* "right" thing here if there is both scaling and translation in
* the matrix. But for now, the internals guarantee that we won't
* really ever have both going on. */
_cairo_path_fixed_offset_and_scale (path,
_cairo_fixed_from_double (device_transform->x0),
_cairo_fixed_from_double (device_transform->y0),
_cairo_fixed_from_double (device_transform->xx),
_cairo_fixed_from_double (device_transform->yy));
}

Просмотреть файл

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -33,23 +34,26 @@
* Carl D. Worth <cworth@redhat.com>
*/
#ifndef CAIRO_PATH_DATA_PRIVATE_H
#define CAIRO_PATH_DATA_PRIVATE_H
#ifndef CAIRO_PATH_PRIVATE_H
#define CAIRO_PATH_PRIVATE_H
#include "cairoint.h"
extern const cairo_private cairo_path_t _cairo_path_nil;
cairo_private cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
_cairo_path_create (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
cairo_private cairo_path_t *
_cairo_path_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
cairo_private cairo_path_t *
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
_cairo_path_create_in_error (cairo_status_t status);
cairo_private cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
cairo_t *cr);
_cairo_path_append_to_context (const cairo_path_t *path,
cairo_t *cr);
#endif /* CAIRO_PATH_DATA_PRIVATE_H */

Просмотреть файл

@ -201,7 +201,6 @@ _cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out
static cairo_status_t
_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
{
cairo_status_t status;
int clockwise = _cairo_stroker_face_clockwise (out, in);
cairo_point_t *inpt, *outpt;
@ -296,8 +295,8 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
double x1, y1, x2, y2;
double mx, my;
double dx1, dx2, dy1, dy2;
cairo_polygon_t polygon;
cairo_point_t outer;
cairo_point_t quad[4];
/*
* we've got the points already transformed to device
@ -339,18 +338,13 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
*/
outer.x = _cairo_fixed_from_double (mx);
outer.y = _cairo_fixed_from_double (my);
_cairo_polygon_init (&polygon);
_cairo_polygon_move_to (&polygon, &in->point);
_cairo_polygon_line_to (&polygon, inpt);
_cairo_polygon_line_to (&polygon, &outer);
_cairo_polygon_line_to (&polygon, outpt);
_cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps,
&polygon,
CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return status;
quad[0] = in->point;
quad[1] = *inpt;
quad[2] = outer;
quad[3] = *outpt;
return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
}
/* fall through ... */
}
@ -424,7 +418,7 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
_cairo_polygon_line_to (&polygon, &f->ccw);
_cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return status;
@ -573,8 +567,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
cairo_slope_t *slope, cairo_stroke_face_t *start,
cairo_stroke_face_t *end)
{
cairo_status_t status;
cairo_polygon_t polygon;
cairo_point_t rectangle[4];
_compute_face (p1, slope, stroker, start);
@ -586,30 +579,12 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
if (p1->x == p2->x && p1->y == p2->y)
return CAIRO_STATUS_SUCCESS;
/* XXX: I should really check the return value of the
move_to/line_to functions here to catch out of memory
conditions. But since that would be ugly, I'd prefer to add a
status flag to the polygon object that I could check only once
at then end of this sequence, (like we do with cairo_t
already). */
_cairo_polygon_init (&polygon);
_cairo_polygon_move_to (&polygon, &start->cw);
_cairo_polygon_line_to (&polygon, &start->ccw);
_cairo_polygon_line_to (&polygon, &end->ccw);
_cairo_polygon_line_to (&polygon, &end->cw);
_cairo_polygon_close (&polygon);
rectangle[0] = start->cw;
rectangle[1] = start->ccw;
rectangle[2] = end->ccw;
rectangle[3] = end->cw;
/* XXX: We can't use tessellate_rectangle as the matrix may have
skewed this into a non-rectangular shape. Perhaps it would be
worth checking the matrix for skew so that the common case
could use the faster tessellate_rectangle rather than
tessellate_polygon? */
status = _cairo_traps_tessellate_polygon (stroker->traps,
&polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return status;
return _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
}
static cairo_status_t

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -48,40 +48,6 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_pattern_t *
_cairo_pattern_nil_for_status (cairo_status_t status)
{
/* A switch statement would be more natural here, but we're
* avoiding that to prevent a "false positive" warning from
* -Wswitch-enum, (and I don't want to maintain a list of all
* status values here). */
if (status == CAIRO_STATUS_NULL_POINTER)
return &cairo_pattern_nil_null_pointer.base;
if (status == CAIRO_STATUS_FILE_NOT_FOUND)
return &cairo_pattern_nil_file_not_found.base;
if (status == CAIRO_STATUS_READ_ERROR)
return &cairo_pattern_nil_read_error.base;
return &cairo_pattern_nil.base;
}
/**
* _cairo_pattern_set_error:
* @pattern: a pattern
@ -294,6 +260,20 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
return &pattern->base;
}
static const cairo_pattern_t *
_cairo_pattern_create_in_error (cairo_status_t status)
{
cairo_pattern_t *pattern;
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK));
if (cairo_pattern_status (pattern))
return pattern;
_cairo_pattern_set_error (pattern, status);
return pattern;
}
/**
* cairo_pattern_create_rgb:
* @red: red component of the color
@ -398,10 +378,10 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
cairo_surface_pattern_t *pattern;
if (surface == NULL)
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER);
return (cairo_pattern_t*) &cairo_pattern_nil_null_pointer;
if (surface->status)
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status);
return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
pattern = malloc (sizeof (cairo_surface_pattern_t));
if (pattern == NULL) {
@ -562,6 +542,7 @@ cairo_pattern_status (cairo_pattern_t *pattern)
{
return pattern->status;
}
slim_hidden_def (cairo_pattern_status);
/**
* cairo_pattern_destroy:
@ -1024,7 +1005,8 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
pixman_image_destroy (pixman_image);
status = _cairo_surface_clone_similar (dst, &image->base, out);
status = _cairo_surface_clone_similar (dst, &image->base,
0, 0, width, height, out);
cairo_surface_destroy (&image->base);
@ -1144,6 +1126,24 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
attr->acquired = FALSE;
attr->extend = pattern->base.extend;
attr->filter = pattern->base.filter;
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
&tx, &ty))
{
cairo_matrix_init_identity (&attr->matrix);
attr->x_offset = tx;
attr->y_offset = ty;
attr->filter = CAIRO_FILTER_NEAREST;
}
else
{
attr->matrix = pattern->base.matrix;
attr->x_offset = attr->y_offset = 0;
tx = 0;
ty = 0;
}
if (_cairo_surface_is_image (dst))
{
cairo_image_surface_t *image;
@ -1159,23 +1159,40 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
}
else
{
status = _cairo_surface_clone_similar (dst, pattern->surface, out);
}
/* If we're repeating, we just play it safe and clone the entire surface. */
if (attr->extend == CAIRO_EXTEND_REPEAT) {
cairo_rectangle_int16_t extents;
status = _cairo_surface_get_extents (pattern->surface, &extents);
x = extents.x;
y = extents.y;
width = extents.width;
height = extents.height;
} else {
/* Otherwise, we first transform the rectangle to the
* coordinate space of the source surface so that we can
* clone only that portion of the surface that will be
* read. */
if (! _cairo_matrix_is_identity (&attr->matrix)) {
double x1 = x;
double y1 = y;
double x2 = x + width;
double y2 = y + height;
cairo_bool_t is_tight;
attr->extend = pattern->base.extend;
attr->filter = pattern->base.filter;
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
&tx, &ty))
{
cairo_matrix_init_identity (&attr->matrix);
attr->x_offset = tx;
attr->y_offset = ty;
attr->filter = CAIRO_FILTER_NEAREST;
}
else
{
attr->matrix = pattern->base.matrix;
attr->x_offset = attr->y_offset = 0;
cairo_matrix_transform_bounding_box (&attr->matrix,
&x1, &y1, &x2, &y2,
&is_tight);
x = floor (x1);
y = floor (y1);
width = ceil (x2) - x;
height = ceil (y2) - y;
}
x += tx;
y += ty;
}
status = _cairo_surface_clone_similar (dst, pattern->surface,
x, y, width, height, out);
}
return status;
@ -1580,7 +1597,7 @@ cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (index < 0 || index >= gradient->n_stops)
if (index < 0 || (unsigned int) index >= gradient->n_stops)
return CAIRO_STATUS_INVALID_INDEX;
if (offset)

Просмотреть файл

@ -880,7 +880,7 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
xstep = image->width;
ystep = image->height;
break;
/* All the reset should have been analyzed away, so this case
/* All the rest should have been analyzed away, so this case
* should be unreachable. */
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
@ -1473,11 +1473,13 @@ _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
info = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Creator (cairographics.org)\r\n"
" /Producer (cairographics.org)\r\n"
"<< /Creator (cairo %s (http://cairographics.org))\r\n"
" /Producer (cairo %s (http://cairographics.org))\r\n"
">>\r\n"
"endobj\r\n",
info.id);
info.id,
cairo_version_string (),
cairo_version_string ());
return info;
}
@ -1577,6 +1579,109 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
"endobj\r\n");
}
static cairo_status_t
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
cairo_pdf_resource_t stream, descriptor, subset_resource;
cairo_status_t status;
cairo_pdf_font_t font;
cairo_cff_subset_t subset;
unsigned long compressed_length;
char *compressed;
unsigned int i;
char name[64];
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_cff_subset_init (&subset, name, font_subset);
if (status)
return status;
compressed = compress_dup (subset.data, subset.data_length, &compressed_length);
if (compressed == NULL) {
_cairo_cff_subset_fini (&subset);
return CAIRO_STATUS_NO_MEMORY;
}
stream = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Filter /FlateDecode\r\n"
" /Length %lu\r\n"
" /Subtype /Type1C\r\n"
">>\r\n"
"stream\r\n",
stream.id,
compressed_length);
_cairo_output_stream_write (surface->output, compressed, compressed_length);
_cairo_output_stream_printf (surface->output,
"\r\n"
"endstream\r\n"
"endobj\r\n");
free (compressed);
descriptor = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /FontDescriptor\r\n"
" /FontName /%s\r\n"
" /Flags 4\r\n"
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
" /ItalicAngle 0\r\n"
" /Ascent %ld\r\n"
" /Descent %ld\r\n"
" /CapHeight 500\r\n"
" /StemV 80\r\n"
" /StemH 80\r\n"
" /FontFile3 %u 0 R\r\n"
">>\r\n"
"endobj\r\n",
descriptor.id,
subset.base_font,
subset.x_min,
subset.y_min,
subset.x_max,
subset.y_max,
subset.ascent,
subset.descent,
stream.id);
subset_resource = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /Font\r\n"
" /Subtype /Type1\r\n"
" /BaseFont /%s\r\n"
" /FirstChar 0\r\n"
" /LastChar %d\r\n"
" /FontDescriptor %d 0 R\r\n"
" /Widths [",
subset_resource.id,
subset.base_font,
font_subset->num_glyphs,
descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %d",
subset.widths[i]);
_cairo_output_stream_printf (surface->output,
" ]\r\n"
">>\r\n"
"endobj\r\n");
font.font_id = font_subset->font_id;
font.subset_id = font_subset->subset_id;
font.subset_resource = subset_resource;
_cairo_array_append (&surface->fonts, &font);
_cairo_cff_subset_fini (&subset);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
@ -1707,7 +1812,7 @@ _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_fallback_init (&subset, name, font_subset);
status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
if (status)
return status;
@ -2057,6 +2162,10 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
cairo_pdf_surface_t *surface = closure;
cairo_status_t status;
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
#if CAIRO_HAS_FT_FONT
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -2537,6 +2646,11 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
info.output = surface->output;
info.ctm_inverse = ctm_inverse;
_cairo_output_stream_printf (surface->output,
"q %f %f %f %f %f %f cm\r\n",
ctm->xx, ctm->yx, ctm->xy, ctm->yy,
ctm->x0, ctm->y0);
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
@ -2545,11 +2659,6 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
_cairo_pdf_path_close_path,
&info);
_cairo_output_stream_printf (surface->output,
"q %f %f %f %f %f %f cm\r\n",
ctm->xx, ctm->yx, ctm->xy, ctm->yy,
ctm->x0, ctm->y0);
_cairo_output_stream_printf (surface->output, "S Q\r\n");
return status;
@ -2611,7 +2720,7 @@ static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -270,7 +270,12 @@ _cairo_pen_vertices_needed (double tolerance,
/* number of vertices must be even */
if (num_vertices % 2)
num_vertices++;
/* And we must always have at least 4 vertices. */
if (num_vertices < 4)
num_vertices = 4;
}
return num_vertices;
}
@ -315,6 +320,8 @@ _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
break;
}
assert (i < pen->num_vertices);
*active = i;
return CAIRO_STATUS_SUCCESS;
@ -441,7 +448,7 @@ _cairo_pen_stroke_spline (cairo_pen_t *pen,
return status;
_cairo_polygon_close (&polygon);
_cairo_traps_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return CAIRO_STATUS_SUCCESS;

Просмотреть файл

@ -82,4 +82,8 @@
#include "cairo-rename.h"
#endif
#ifdef IS_BIG_ENDIAN
#define FLOAT_WORDS_BIGENDIAN
#endif
#endif /* CAIRO_PLATFORM_H */

Просмотреть файл

@ -289,7 +289,7 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
}
slim_hidden_def (cairo_surface_write_to_png_stream);
static INLINE int
static inline int
multiply_alpha (int alpha, int color)
{
int temp = (alpha * color) + 0x80;

Просмотреть файл

@ -331,10 +331,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
_cairo_output_stream_printf (surface->final_stream,
"%%!PS-Adobe-3.0\n"
"%%%%Creator: cairo (http://cairographics.org)\n"
"%%%%Creator: cairo %s (http://cairographics.org)\n"
"%%%%CreationDate: %s"
"%%%%Pages: %d\n"
"%%%%BoundingBox: %d %d %d %d\n",
cairo_version_string (),
ctime (&now),
surface->num_pages,
0, 0,
@ -367,6 +368,9 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/P{closepath}bind def\n"
"/R{setrgbcolor}bind def\n"
"/S{show}bind def\n"
"/xS{xshow}bind def\n"
"/yS{yshow}bind def\n"
"/xyS{xyshow}bind def\n"
"%%%%EndProlog\n");
num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);
@ -430,14 +434,14 @@ _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_fallback_init (&subset, name, font_subset);
status = _cairo_type1_fallback_init_hex (&subset, name, font_subset);
if (status)
return status;
/* FIXME: Figure out document structure convention for fonts */
_cairo_output_stream_printf (surface->final_stream,
"%% _cairo_ps_surface_emit_type1_font_subset\n");
"%% _cairo_ps_surface_emit_type1_font_fallback\n");
length = subset.header_length + subset.data_length + subset.trailer_length;
_cairo_output_stream_write (surface->final_stream, subset.data, length);
@ -1666,55 +1670,84 @@ emit_solid_pattern (cairo_ps_surface_t *surface,
static void
emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern,
double x, double y)
cairo_surface_pattern_t *pattern)
{
cairo_rectangle_int16_t extents;
double bbox_width, bbox_height;
int xstep, ystep;
cairo_matrix_t inverse = pattern->base.matrix;
cairo_matrix_invert (&inverse);
if (_cairo_surface_is_meta (pattern->surface)) {
_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
_cairo_meta_surface_replay (pattern->surface, &surface->base);
extents.width = surface->width;
extents.height = surface->height;
bbox_width = surface->width;
bbox_height = surface->height;
xstep = surface->width;
ystep = surface->height;
_cairo_output_stream_printf (surface->stream, "} bind def\n");
} else {
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status;
cairo_matrix_t inverse = pattern->base.matrix;
cairo_matrix_invert (&inverse);
status = _cairo_surface_acquire_source_image (pattern->surface,
&image,
&image_extra);
assert (status == CAIRO_STATUS_SUCCESS);
_cairo_pattern_get_extents (&pattern->base, &extents);
emit_image (surface, image, &pattern->base.matrix, "MyPattern");
bbox_width = image->width;
bbox_height = image->height;
cairo_matrix_transform_distance (&inverse,
&bbox_width, &bbox_height);
/* In PostScript, (as far as I can tell), all patterns are
* repeating. So we support cairo's EXTEND_NONE semantics by
* setting the repeat step size to the larger of the image size
* and the extents of the destination surface. That way we
* guarantee the pattern will not repeat.
*/
switch (pattern->base.extend) {
case CAIRO_EXTEND_NONE:
xstep = MAX (image->width, surface->width);
ystep = MAX (image->height, surface->height);
break;
case CAIRO_EXTEND_REPEAT:
xstep = image->width;
ystep = image->height;
break;
/* All the rest should have been analyzed away, so these cases
* should be unreachable. */
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
default:
ASSERT_NOT_REACHED;
xstep = 0;
ystep = 0;
}
_cairo_surface_release_source_image (pattern->surface, image,
image_extra);
}
_cairo_output_stream_printf (surface->stream,
"%f %f translate\n",
x, y);
_cairo_output_stream_printf (surface->stream,
"<< /PatternType 1\n"
" /PaintType 1\n"
" /TilingType 1\n");
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %d %d]\n",
extents.width, extents.height);
(int) bbox_width, (int) bbox_height);
_cairo_output_stream_printf (surface->stream,
" /XStep %d /YStep %d\n",
extents.width, extents.height);
xstep, ystep);
_cairo_output_stream_printf (surface->stream,
" /PaintProc { MyPattern } bind\n"
">> matrix makepattern setpattern\n");
">>\n");
_cairo_output_stream_printf (surface->stream,
"-%f -%f translate\n",
x, y);
"[ 1 0 0 1 %f %f ]\n",
inverse.x0, inverse.y0);
_cairo_output_stream_printf (surface->stream,
"makepattern setpattern\n");
}
static void
@ -1732,8 +1765,7 @@ emit_radial_pattern (cairo_ps_surface_t *surface,
}
static void
emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern,
double x, double y)
emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
{
/* FIXME: We should keep track of what pattern is currently set in
* the postscript file and only emit code if we're setting a
@ -1745,7 +1777,7 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern,
break;
case CAIRO_PATTERN_TYPE_SURFACE:
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, x, y);
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
break;
case CAIRO_PATTERN_TYPE_LINEAR:
@ -1840,7 +1872,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_rectangle_int16_t extents;
cairo_rectangle_int16_t extents, pattern_extents;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _analyze_operation (surface, op, source);
@ -1858,9 +1890,11 @@ _cairo_ps_surface_paint (void *abstract_surface,
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_paint\n");
_cairo_pattern_get_extents (source, &extents);
_cairo_surface_get_extents (&surface->base, &extents);
_cairo_pattern_get_extents (source, &pattern_extents);
_cairo_rectangle_intersect (&extents, &pattern_extents);
emit_pattern (surface, source, extents.x, extents.y);
emit_pattern (surface, source);
_cairo_output_stream_printf (stream, "%d %d M\n",
extents.x, extents.y);
@ -1999,7 +2033,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
}
}
emit_pattern (surface, source, 0, 0);
emit_pattern (surface, source);
_cairo_output_stream_printf (stream,
"gsave\n");
@ -2066,7 +2100,7 @@ _cairo_ps_surface_fill (void *abstract_surface,
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_fill\n");
emit_pattern (surface, source, 0, 0);
emit_pattern (surface, source);
/* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
status = _cairo_ps_surface_emit_path (surface, stream, path,
@ -2089,20 +2123,32 @@ _cairo_ps_surface_fill (void *abstract_surface,
return status;
}
/* This size keeps the length of the hex encoded string of glyphs
* within 80 columns. */
#define MAX_GLYPHS_PER_SHOW 36
typedef struct _cairo_ps_glyph_id {
unsigned int subset_id;
unsigned int glyph_id;
} cairo_ps_glyph_id_t;
static cairo_int_status_t
_cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
unsigned int current_subset_id = -1;
unsigned int font_id, subset_id, subset_glyph_index;
unsigned int font_id;
cairo_ps_glyph_id_t *glyph_ids;
cairo_status_t status;
int i;
unsigned int num_glyphs_unsigned, i, j, last, end;
cairo_bool_t vertical, horizontal;
cairo_output_stream_t *word_wrap;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _analyze_operation (surface, op, source);
@ -2112,37 +2158,117 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_show_glyphs\n");
if (num_glyphs)
emit_pattern (surface, source, 0, 0);
if (num_glyphs <= 0)
return CAIRO_STATUS_SUCCESS;
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
&font_id, &subset_id, &subset_glyph_index);
if (status)
return status;
num_glyphs_unsigned = num_glyphs;
if (subset_id != current_subset_id) {
_cairo_output_stream_printf (surface->stream,
"/CairoFont-%d-%d findfont\n"
"[ %f %f %f %f 0 0 ] makefont\n"
"setfont\n",
font_id,
subset_id,
scaled_font->scale.xx,
scaled_font->scale.yx,
-scaled_font->scale.xy,
-scaled_font->scale.yy);
current_subset_id = subset_id;
}
emit_pattern (surface, source);
glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
if (glyph_ids == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_output_stream_printf (surface->stream,
"%f %f M <%02x> S\n",
glyphs[i].x, glyphs[i].y,
subset_glyph_index);
for (i = 0; i < num_glyphs_unsigned; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
&font_id,
&(glyph_ids[i].subset_id),
&(glyph_ids[i].glyph_id));
if (status)
goto fail;
}
return _cairo_output_stream_get_status (surface->stream);
i = 0;
while (i < num_glyphs_unsigned) {
if (glyph_ids[i].subset_id != current_subset_id) {
_cairo_output_stream_printf (surface->stream,
"/CairoFont-%d-%d findfont\n"
"[ %f %f %f %f 0 0 ] makefont\n"
"setfont\n",
font_id,
glyph_ids[i].subset_id,
scaled_font->scale.xx,
scaled_font->scale.yx,
-scaled_font->scale.xy,
-scaled_font->scale.yy);
current_subset_id = glyph_ids[i].subset_id;
}
if (i == 0)
_cairo_output_stream_printf (stream,
"%f %f M\n",
glyphs[i].x,
glyphs[i].y);
horizontal = TRUE;
vertical = TRUE;
end = num_glyphs_unsigned;
if (end - i > MAX_GLYPHS_PER_SHOW)
end = i + MAX_GLYPHS_PER_SHOW;
last = end - 1;
for (j = i; j < end - 1; j++) {
if ((glyphs[j].y != glyphs[j + 1].y))
horizontal = FALSE;
if ((glyphs[j].x != glyphs[j + 1].x))
vertical = FALSE;
if (glyph_ids[j].subset_id != glyph_ids[j + 1].subset_id) {
last = j;
break;
}
}
if (i == last) {
_cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id);
} else {
word_wrap = _word_wrap_stream_create (surface->stream, 79);
_cairo_output_stream_printf (word_wrap, "<");
for (j = i; j < last+1; j++)
_cairo_output_stream_printf (word_wrap, "%02x", glyph_ids[j].glyph_id);
_cairo_output_stream_printf (word_wrap, ">\n[");
if (horizontal) {
for (j = i; j < last+1; j++) {
if (j == num_glyphs_unsigned - 1)
_cairo_output_stream_printf (word_wrap, "0 ");
else
_cairo_output_stream_printf (word_wrap,
"%f ", glyphs[j + 1].x - glyphs[j].x);
}
_cairo_output_stream_printf (word_wrap, "] xS\n");
} else if (vertical) {
for (j = i; j < last+1; j++) {
if (j == num_glyphs_unsigned - 1)
_cairo_output_stream_printf (word_wrap, "0 ");
else
_cairo_output_stream_printf (word_wrap,
"%f ", glyphs[j + 1].y - glyphs[j].y);
}
_cairo_output_stream_printf (word_wrap, "] yS\n");
} else {
for (j = i; j < last+1; j++) {
if (j == num_glyphs_unsigned - 1)
_cairo_output_stream_printf (word_wrap, "0 ");
else
_cairo_output_stream_printf (word_wrap,
"%f %f ",
glyphs[j + 1].x - glyphs[j].x,
glyphs[j + 1].y - glyphs[j].y);
}
_cairo_output_stream_printf (word_wrap, "] xyS\n");
}
status = _cairo_output_stream_destroy (word_wrap);
if (status)
goto fail;
}
i = last + 1;
}
status = _cairo_output_stream_get_status (surface->stream);
fail:
free (glyph_ids);
return status;
}
static void

Просмотреть файл

@ -55,11 +55,9 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
{
cairo_quartz_surface_t *surface = abstract_surface;
#if 0
if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
/* XXX: We can create an image out of the bitmap here */
}
#endif
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -249,19 +247,11 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
surface->clip_region = NULL;
surface->y_grows_down = y_grows_down;
#if 0
/* 10.3 or later */
clip_box = CGContextGetClipBoundingBox (context);
surface->extents.x = clip_box.origin.x;
surface->extents.y = clip_box.origin.y;
surface->extents.width = clip_box.size.width;
surface->extents.height = clip_box.size.height;
#else
surface->extents.x = 0;
surface->extents.y = 0;
surface->extents.width = width;
surface->extents.height = height;
#endif
return (cairo_surface_t *) surface;
}

Просмотреть файл

@ -105,6 +105,7 @@
#define cairo_matrix_multiply _moz_cairo_matrix_multiply
#define cairo_matrix_rotate _moz_cairo_matrix_rotate
#define cairo_matrix_scale _moz_cairo_matrix_scale
#define cairo_matrix_transform_bounding_box _moz_cairo_matrix_transform_bounding_box
#define cairo_matrix_transform_distance _moz_cairo_matrix_transform_distance
#define cairo_matrix_transform_point _moz_cairo_matrix_transform_point
#define cairo_matrix_translate _moz_cairo_matrix_translate
@ -154,8 +155,6 @@
#define cairo_pdf_surface_set_size _moz_cairo_pdf_surface_set_size
#define cairo_pop_group _moz_cairo_pop_group
#define cairo_pop_group_to_source _moz_cairo_pop_group_to_source
#define cairo_profile_surface_create _moz_cairo_profile_surface_create
#define cairo_profile_surface_get_profile_data _moz_cairo_profile_surface_get_profile_data
#define cairo_ps_surface_create _moz_cairo_ps_surface_create
#define cairo_ps_surface_create_for_stream _moz_cairo_ps_surface_create_for_stream
#define cairo_ps_surface_dsc_begin_page_setup _moz_cairo_ps_surface_dsc_begin_page_setup
@ -227,7 +226,6 @@
#define cairo_surface_get_type _moz_cairo_surface_get_type
#define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
#define cairo_surface_is_nquartz _moz_cairo_surface_is_nquartz
#define cairo_surface_is_profile _moz_cairo_surface_is_profile
#define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
#define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle
#define cairo_surface_reference _moz_cairo_surface_reference

Просмотреть файл

@ -179,6 +179,46 @@ _cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure);
typedef struct _cairo_cff_subset {
char *base_font;
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
char *data;
unsigned long data_length;
} cairo_cff_subset_t;
/**
* _cairo_cff_subset_init:
* @cff_subset: a #cairo_cff_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a
* cff file corresponding to @font_subset and initialize
* @cff_subset with information about the subset and the cff
* data.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
* cff file, or an non-zero value indicating an error. Possible
* errors include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_cff_subset_fini:
* @cff_subset: a #cairo_cff_subset_t
*
* Free all resources associated with @cff_subset. After this
* call, @cff_subset should not be used again without a
* subsequent call to _cairo_cff_subset_init() again first.
**/
cairo_private void
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
typedef struct _cairo_truetype_subset {
char *base_font;
@ -269,14 +309,15 @@ cairo_private void
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
/**
* _cairo_type1_fallback_init:
* _cairo_type1_fallback_init_binary:
* @type1_subset: a #cairo_type1_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a type1
* file corresponding to @font_subset and initialize @type1_subset
* with information about the subset and the type1 data.
* with information about the subset and the type1 data. The encrypted
* part of the font is binary encoded.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
@ -284,9 +325,30 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset);
* include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_type1_fallback_init (cairo_type1_subset_t *type_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_type1_fallback_init_hexencode:
* @type1_subset: a #cairo_type1_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a type1
* file corresponding to @font_subset and initialize @type1_subset
* with information about the subset and the type1 data. The encrypted
* part of the font is hex encoded.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
* file, or an non-zero value indicating an error. Possible errors
* include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_type1_fallback_fini:

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: cairo-scaled-font.c,v 1.11 2006/09/26 22:21:55 vladimir%pobox.com Exp $
/* $Id: cairo-scaled-font.c,v 1.12 2006/12/23 01:15:53 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
@ -698,7 +698,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
**/
void
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
@ -834,7 +834,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
cairo_status_t status = CAIRO_STATUS_SUCCESS;
int i;
int min_x = INT16_MAX, max_x = INT16_MIN;
int min_y = INT16_MAX, max_y = INT16_MAX;
int min_y = INT16_MAX, max_y = INT16_MIN;
if (scaled_font->status)
return scaled_font->status;
@ -855,8 +855,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
}
/* glyph images are snapped to pixel locations */
x = (int) floor (glyphs[i].x + 0.5);
y = (int) floor (glyphs[i].y + 0.5);
x = _cairo_lround (glyphs[i].x);
y = _cairo_lround (glyphs[i].y);
left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x);
top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
@ -891,7 +891,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
@ -964,12 +964,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
/* round glyph locations to the nearest pixel */
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
x = (int) floor (glyphs[i].x +
glyph_surface->base.device_transform.x0 +
0.5);
y = (int) floor (glyphs[i].y +
glyph_surface->base.device_transform.y0 +
0.5);
x = _cairo_lround (glyphs[i].x +
glyph_surface->base.device_transform.x0);
y = _cairo_lround (glyphs[i].y +
glyph_surface->base.device_transform.y0);
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
@ -1213,6 +1211,7 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
double hm, wm;
double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0;
double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0;
double device_x_advance, device_y_advance;
for (hm = 0.0; hm <= 1.0; hm += 1.0)
for (wm = 0.0; wm <= 1.0; wm += 1.0) {
@ -1261,10 +1260,19 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
&scaled_glyph->metrics.x_advance,
&scaled_glyph->metrics.y_advance);
device_x_advance = fs_metrics->x_advance;
device_y_advance = fs_metrics->y_advance;
cairo_matrix_transform_distance (&scaled_font->scale,
&device_x_advance,
&device_y_advance);
scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x);
scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y);
scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x);
scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y);
scaled_glyph->x_advance = _cairo_lround (device_x_advance);
scaled_glyph->y_advance = _cairo_lround (device_y_advance);
}
void

Просмотреть файл

@ -0,0 +1,99 @@
/*
* Copyright © 2006 Keith Packard
* Copyright © 2006 Carl Worth
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef SKIPLIST_H
#define SKIPLIST_H
#include "cairoint.h"
#define MAX_LEVEL 31
/*
* Skip list element. In order to use the skip list, the caller must
* generate a structure for list elements that has as its final member
* a skip_elt_t, (which will be allocated with variable size).
*
* The caller must also pass the size of the structure to
* skip_list_init.
*/
typedef struct _skip_elt {
int prev_index;
struct _skip_elt *prev;
struct _skip_elt *next[1];
} skip_elt_t;
#define SKIP_LIST_ELT_TO_DATA(type, elt) ((type *) ((char *) (elt) - (sizeof (type) - sizeof (skip_elt_t))))
typedef int
(*skip_list_compare_t) (void *list, void *a, void *b);
typedef struct _skip_list {
skip_list_compare_t compare;
size_t elt_size;
size_t data_size;
skip_elt_t *chains[MAX_LEVEL];
skip_elt_t *freelists[MAX_LEVEL];
int max_level;
} skip_list_t;
/* Initialize a new skip list. The compare function accepts a pointer
* to the list as well as pointers to two elements. The function must
* return a value greater than zero, zero, or less then 0 if the first
* element is considered respectively greater than, equal to, or less
* than the second element. The size of each object, (as computed by
* sizeof) is passed for elt_size. Note that the structure used for
* list elements must have as its final member a skip_elt_t
*/
cairo_private void
skip_list_init (skip_list_t *list,
skip_list_compare_t compare,
size_t elt_size);
/* Deallocate resources associated with a skip list and all elements
* in it. (XXX: currently this simply deletes all elements.)
*/
cairo_private void
skip_list_fini (skip_list_t *list);
/* Insert a new element into the list at the correct sort order as
* determined by compare. If unique is true, then duplicate elements
* are ignored and the already inserted element is returned.
* Otherwise data will be copied (elt_size bytes from <data> via
* memcpy) and the new element is returned. */
cairo_private void *
skip_list_insert (skip_list_t *list, void *data, int unique);
/* Find an element which compare considers equal to <data> */
cairo_private void *
skip_list_find (skip_list_t *list, void *data);
/* Delete an element which compare considers equal to <data> */
cairo_private void
skip_list_delete (skip_list_t *list, void *data);
/* Delete the given element from the list. */
cairo_private void
skip_list_delete_given (skip_list_t *list, skip_elt_t *given);
#endif

Просмотреть файл

@ -0,0 +1,469 @@
/*
* Copyright © 2006 Keith Packard
* Copyright © 2006 Carl Worth
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "cairo-skiplist-private.h"
#define ELT_DATA(elt) (void *) ((char*) (elt) - list->data_size)
#define NEXT_TO_ELT(next) (skip_elt_t *) ((char *) (next) - offsetof (skip_elt_t, next))
/* Four 256 element lookup tables back to back implementing a linear
* feedback shift register of degree 32. */
static unsigned const lfsr_lut[1024] = {
0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2,
0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853,
0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d,
0x87c3fb23, 0x1dbaae14, 0xee26afff, 0x745ffac8, 0x40ad50a6, 0xdad40591,
0x3dec0647, 0xa7955370, 0x9367f91e, 0x091eac29, 0xfa82adc2, 0x60fbf8f5,
0x5409529b, 0xce7007ac, 0x529008f4, 0xc8e95dc3, 0xfc1bf7ad, 0x6662a29a,
0x95fea371, 0x0f87f646, 0x3b755c28, 0xa10c091f, 0x46340ac9, 0xdc4d5ffe,
0xe8bff590, 0x72c6a0a7, 0x815aa14c, 0x1b23f47b, 0x2fd15e15, 0xb5a80b22,
0x7bd80c8e, 0xe1a159b9, 0xd553f3d7, 0x4f2aa6e0, 0xbcb6a70b, 0x26cff23c,
0x123d5852, 0x88440d65, 0x6f7c0eb3, 0xf5055b84, 0xc1f7f1ea, 0x5b8ea4dd,
0xa812a536, 0x326bf001, 0x06995a6f, 0x9ce00f58, 0xa52011e8, 0x3f5944df,
0x0babeeb1, 0x91d2bb86, 0x624eba6d, 0xf837ef5a, 0xccc54534, 0x56bc1003,
0xb18413d5, 0x2bfd46e2, 0x1f0fec8c, 0x8576b9bb, 0x76eab850, 0xec93ed67,
0xd8614709, 0x4218123e, 0x8c681592, 0x161140a5, 0x22e3eacb, 0xb89abffc,
0x4b06be17, 0xd17feb20, 0xe58d414e, 0x7ff41479, 0x98cc17af, 0x02b54298,
0x3647e8f6, 0xac3ebdc1, 0x5fa2bc2a, 0xc5dbe91d, 0xf1294373, 0x6b501644,
0xf7b0191c, 0x6dc94c2b, 0x593be645, 0xc342b372, 0x30deb299, 0xaaa7e7ae,
0x9e554dc0, 0x042c18f7, 0xe3141b21, 0x796d4e16, 0x4d9fe478, 0xd7e6b14f,
0x247ab0a4, 0xbe03e593, 0x8af14ffd, 0x10881aca, 0xdef81d66, 0x44814851,
0x7073e23f, 0xea0ab708, 0x1996b6e3, 0x83efe3d4, 0xb71d49ba, 0x2d641c8d,
0xca5c1f5b, 0x50254a6c, 0x64d7e002, 0xfeaeb535, 0x0d32b4de, 0x974be1e9,
0xa3b94b87, 0x39c01eb0, 0xd03976e7, 0x4a4023d0, 0x7eb289be, 0xe4cbdc89,
0x1757dd62, 0x8d2e8855, 0xb9dc223b, 0x23a5770c, 0xc49d74da, 0x5ee421ed,
0x6a168b83, 0xf06fdeb4, 0x03f3df5f, 0x998a8a68, 0xad782006, 0x37017531,
0xf971729d, 0x630827aa, 0x57fa8dc4, 0xcd83d8f3, 0x3e1fd918, 0xa4668c2f,
0x90942641, 0x0aed7376, 0xedd570a0, 0x77ac2597, 0x435e8ff9, 0xd927dace,
0x2abbdb25, 0xb0c28e12, 0x8430247c, 0x1e49714b, 0x82a97e13, 0x18d02b24,
0x2c22814a, 0xb65bd47d, 0x45c7d596, 0xdfbe80a1, 0xeb4c2acf, 0x71357ff8,
0x960d7c2e, 0x0c742919, 0x38868377, 0xa2ffd640, 0x5163d7ab, 0xcb1a829c,
0xffe828f2, 0x65917dc5, 0xabe17a69, 0x31982f5e, 0x056a8530, 0x9f13d007,
0x6c8fd1ec, 0xf6f684db, 0xc2042eb5, 0x587d7b82, 0xbf457854, 0x253c2d63,
0x11ce870d, 0x8bb7d23a, 0x782bd3d1, 0xe25286e6, 0xd6a02c88, 0x4cd979bf,
0x7519670f, 0xef603238, 0xdb929856, 0x41ebcd61, 0xb277cc8a, 0x280e99bd,
0x1cfc33d3, 0x868566e4, 0x61bd6532, 0xfbc43005, 0xcf369a6b, 0x554fcf5c,
0xa6d3ceb7, 0x3caa9b80, 0x085831ee, 0x922164d9, 0x5c516375, 0xc6283642,
0xf2da9c2c, 0x68a3c91b, 0x9b3fc8f0, 0x01469dc7, 0x35b437a9, 0xafcd629e,
0x48f56148, 0xd28c347f, 0xe67e9e11, 0x7c07cb26, 0x8f9bcacd, 0x15e29ffa,
0x21103594, 0xbb6960a3, 0x27896ffb, 0xbdf03acc, 0x890290a2, 0x137bc595,
0xe0e7c47e, 0x7a9e9149, 0x4e6c3b27, 0xd4156e10, 0x332d6dc6, 0xa95438f1,
0x9da6929f, 0x07dfc7a8, 0xf443c643, 0x6e3a9374, 0x5ac8391a, 0xc0b16c2d,
0x0ec16b81, 0x94b83eb6, 0xa04a94d8, 0x3a33c1ef, 0xc9afc004, 0x53d69533,
0x67243f5d, 0xfd5d6a6a, 0x1a6569bc, 0x801c3c8b, 0xb4ee96e5, 0x2e97c3d2,
0xdd0bc239, 0x4772970e, 0x73803d60, 0xe9f96857, 0x00000000, 0x3a0bb8f9,
0x741771f2, 0x4e1cc90b, 0xe82ee3e4, 0xd2255b1d, 0x9c399216, 0xa6322aef,
0x4a2492ff, 0x702f2a06, 0x3e33e30d, 0x04385bf4, 0xa20a711b, 0x9801c9e2,
0xd61d00e9, 0xec16b810, 0x944925fe, 0xae429d07, 0xe05e540c, 0xda55ecf5,
0x7c67c61a, 0x466c7ee3, 0x0870b7e8, 0x327b0f11, 0xde6db701, 0xe4660ff8,
0xaa7ac6f3, 0x90717e0a, 0x364354e5, 0x0c48ec1c, 0x42542517, 0x785f9dee,
0xb2eb1ecb, 0x88e0a632, 0xc6fc6f39, 0xfcf7d7c0, 0x5ac5fd2f, 0x60ce45d6,
0x2ed28cdd, 0x14d93424, 0xf8cf8c34, 0xc2c434cd, 0x8cd8fdc6, 0xb6d3453f,
0x10e16fd0, 0x2aead729, 0x64f61e22, 0x5efda6db, 0x26a23b35, 0x1ca983cc,
0x52b54ac7, 0x68bef23e, 0xce8cd8d1, 0xf4876028, 0xba9ba923, 0x809011da,
0x6c86a9ca, 0x568d1133, 0x1891d838, 0x229a60c1, 0x84a84a2e, 0xbea3f2d7,
0xf0bf3bdc, 0xcab48325, 0xffaf68a1, 0xc5a4d058, 0x8bb81953, 0xb1b3a1aa,
0x17818b45, 0x2d8a33bc, 0x6396fab7, 0x599d424e, 0xb58bfa5e, 0x8f8042a7,
0xc19c8bac, 0xfb973355, 0x5da519ba, 0x67aea143, 0x29b26848, 0x13b9d0b1,
0x6be64d5f, 0x51edf5a6, 0x1ff13cad, 0x25fa8454, 0x83c8aebb, 0xb9c31642,
0xf7dfdf49, 0xcdd467b0, 0x21c2dfa0, 0x1bc96759, 0x55d5ae52, 0x6fde16ab,
0xc9ec3c44, 0xf3e784bd, 0xbdfb4db6, 0x87f0f54f, 0x4d44766a, 0x774fce93,
0x39530798, 0x0358bf61, 0xa56a958e, 0x9f612d77, 0xd17de47c, 0xeb765c85,
0x0760e495, 0x3d6b5c6c, 0x73779567, 0x497c2d9e, 0xef4e0771, 0xd545bf88,
0x9b597683, 0xa152ce7a, 0xd90d5394, 0xe306eb6d, 0xad1a2266, 0x97119a9f,
0x3123b070, 0x0b280889, 0x4534c182, 0x7f3f797b, 0x9329c16b, 0xa9227992,
0xe73eb099, 0xdd350860, 0x7b07228f, 0x410c9a76, 0x0f10537d, 0x351beb84,
0x65278475, 0x5f2c3c8c, 0x1130f587, 0x2b3b4d7e, 0x8d096791, 0xb702df68,
0xf91e1663, 0xc315ae9a, 0x2f03168a, 0x1508ae73, 0x5b146778, 0x611fdf81,
0xc72df56e, 0xfd264d97, 0xb33a849c, 0x89313c65, 0xf16ea18b, 0xcb651972,
0x8579d079, 0xbf726880, 0x1940426f, 0x234bfa96, 0x6d57339d, 0x575c8b64,
0xbb4a3374, 0x81418b8d, 0xcf5d4286, 0xf556fa7f, 0x5364d090, 0x696f6869,
0x2773a162, 0x1d78199b, 0xd7cc9abe, 0xedc72247, 0xa3dbeb4c, 0x99d053b5,
0x3fe2795a, 0x05e9c1a3, 0x4bf508a8, 0x71feb051, 0x9de80841, 0xa7e3b0b8,
0xe9ff79b3, 0xd3f4c14a, 0x75c6eba5, 0x4fcd535c, 0x01d19a57, 0x3bda22ae,
0x4385bf40, 0x798e07b9, 0x3792ceb2, 0x0d99764b, 0xabab5ca4, 0x91a0e45d,
0xdfbc2d56, 0xe5b795af, 0x09a12dbf, 0x33aa9546, 0x7db65c4d, 0x47bde4b4,
0xe18fce5b, 0xdb8476a2, 0x9598bfa9, 0xaf930750, 0x9a88ecd4, 0xa083542d,
0xee9f9d26, 0xd49425df, 0x72a60f30, 0x48adb7c9, 0x06b17ec2, 0x3cbac63b,
0xd0ac7e2b, 0xeaa7c6d2, 0xa4bb0fd9, 0x9eb0b720, 0x38829dcf, 0x02892536,
0x4c95ec3d, 0x769e54c4, 0x0ec1c92a, 0x34ca71d3, 0x7ad6b8d8, 0x40dd0021,
0xe6ef2ace, 0xdce49237, 0x92f85b3c, 0xa8f3e3c5, 0x44e55bd5, 0x7eeee32c,
0x30f22a27, 0x0af992de, 0xaccbb831, 0x96c000c8, 0xd8dcc9c3, 0xe2d7713a,
0x2863f21f, 0x12684ae6, 0x5c7483ed, 0x667f3b14, 0xc04d11fb, 0xfa46a902,
0xb45a6009, 0x8e51d8f0, 0x624760e0, 0x584cd819, 0x16501112, 0x2c5ba9eb,
0x8a698304, 0xb0623bfd, 0xfe7ef2f6, 0xc4754a0f, 0xbc2ad7e1, 0x86216f18,
0xc83da613, 0xf2361eea, 0x54043405, 0x6e0f8cfc, 0x201345f7, 0x1a18fd0e,
0xf60e451e, 0xcc05fde7, 0x821934ec, 0xb8128c15, 0x1e20a6fa, 0x242b1e03,
0x6a37d708, 0x503c6ff1, 0x00000000, 0xca4f08ea, 0x0ee744e3, 0xc4a84c09,
0x1dce89c6, 0xd781812c, 0x1329cd25, 0xd966c5cf, 0x3b9d138c, 0xf1d21b66,
0x357a576f, 0xff355f85, 0x26539a4a, 0xec1c92a0, 0x28b4dea9, 0xe2fbd643,
0x773a2718, 0xbd752ff2, 0x79dd63fb, 0xb3926b11, 0x6af4aede, 0xa0bba634,
0x6413ea3d, 0xae5ce2d7, 0x4ca73494, 0x86e83c7e, 0x42407077, 0x880f789d,
0x5169bd52, 0x9b26b5b8, 0x5f8ef9b1, 0x95c1f15b, 0xee744e30, 0x243b46da,
0xe0930ad3, 0x2adc0239, 0xf3bac7f6, 0x39f5cf1c, 0xfd5d8315, 0x37128bff,
0xd5e95dbc, 0x1fa65556, 0xdb0e195f, 0x114111b5, 0xc827d47a, 0x0268dc90,
0xc6c09099, 0x0c8f9873, 0x994e6928, 0x530161c2, 0x97a92dcb, 0x5de62521,
0x8480e0ee, 0x4ecfe804, 0x8a67a40d, 0x4028ace7, 0xa2d37aa4, 0x689c724e,
0xac343e47, 0x667b36ad, 0xbf1df362, 0x7552fb88, 0xb1fab781, 0x7bb5bf6b,
0x4691c957, 0x8cdec1bd, 0x48768db4, 0x8239855e, 0x5b5f4091, 0x9110487b,
0x55b80472, 0x9ff70c98, 0x7d0cdadb, 0xb743d231, 0x73eb9e38, 0xb9a496d2,
0x60c2531d, 0xaa8d5bf7, 0x6e2517fe, 0xa46a1f14, 0x31abee4f, 0xfbe4e6a5,
0x3f4caaac, 0xf503a246, 0x2c656789, 0xe62a6f63, 0x2282236a, 0xe8cd2b80,
0x0a36fdc3, 0xc079f529, 0x04d1b920, 0xce9eb1ca, 0x17f87405, 0xddb77cef,
0x191f30e6, 0xd350380c, 0xa8e58767, 0x62aa8f8d, 0xa602c384, 0x6c4dcb6e,
0xb52b0ea1, 0x7f64064b, 0xbbcc4a42, 0x718342a8, 0x937894eb, 0x59379c01,
0x9d9fd008, 0x57d0d8e2, 0x8eb61d2d, 0x44f915c7, 0x805159ce, 0x4a1e5124,
0xdfdfa07f, 0x1590a895, 0xd138e49c, 0x1b77ec76, 0xc21129b9, 0x085e2153,
0xccf66d5a, 0x06b965b0, 0xe442b3f3, 0x2e0dbb19, 0xeaa5f710, 0x20eafffa,
0xf98c3a35, 0x33c332df, 0xf76b7ed6, 0x3d24763c, 0x8d2392ae, 0x476c9a44,
0x83c4d64d, 0x498bdea7, 0x90ed1b68, 0x5aa21382, 0x9e0a5f8b, 0x54455761,
0xb6be8122, 0x7cf189c8, 0xb859c5c1, 0x7216cd2b, 0xab7008e4, 0x613f000e,
0xa5974c07, 0x6fd844ed, 0xfa19b5b6, 0x3056bd5c, 0xf4fef155, 0x3eb1f9bf,
0xe7d73c70, 0x2d98349a, 0xe9307893, 0x237f7079, 0xc184a63a, 0x0bcbaed0,
0xcf63e2d9, 0x052cea33, 0xdc4a2ffc, 0x16052716, 0xd2ad6b1f, 0x18e263f5,
0x6357dc9e, 0xa918d474, 0x6db0987d, 0xa7ff9097, 0x7e995558, 0xb4d65db2,
0x707e11bb, 0xba311951, 0x58cacf12, 0x9285c7f8, 0x562d8bf1, 0x9c62831b,
0x450446d4, 0x8f4b4e3e, 0x4be30237, 0x81ac0add, 0x146dfb86, 0xde22f36c,
0x1a8abf65, 0xd0c5b78f, 0x09a37240, 0xc3ec7aaa, 0x074436a3, 0xcd0b3e49,
0x2ff0e80a, 0xe5bfe0e0, 0x2117ace9, 0xeb58a403, 0x323e61cc, 0xf8716926,
0x3cd9252f, 0xf6962dc5, 0xcbb25bf9, 0x01fd5313, 0xc5551f1a, 0x0f1a17f0,
0xd67cd23f, 0x1c33dad5, 0xd89b96dc, 0x12d49e36, 0xf02f4875, 0x3a60409f,
0xfec80c96, 0x3487047c, 0xede1c1b3, 0x27aec959, 0xe3068550, 0x29498dba,
0xbc887ce1, 0x76c7740b, 0xb26f3802, 0x782030e8, 0xa146f527, 0x6b09fdcd,
0xafa1b1c4, 0x65eeb92e, 0x87156f6d, 0x4d5a6787, 0x89f22b8e, 0x43bd2364,
0x9adbe6ab, 0x5094ee41, 0x943ca248, 0x5e73aaa2, 0x25c615c9, 0xef891d23,
0x2b21512a, 0xe16e59c0, 0x38089c0f, 0xf24794e5, 0x36efd8ec, 0xfca0d006,
0x1e5b0645, 0xd4140eaf, 0x10bc42a6, 0xdaf34a4c, 0x03958f83, 0xc9da8769,
0x0d72cb60, 0xc73dc38a, 0x52fc32d1, 0x98b33a3b, 0x5c1b7632, 0x96547ed8,
0x4f32bb17, 0x857db3fd, 0x41d5fff4, 0x8b9af71e, 0x6961215d, 0xa32e29b7,
0x678665be, 0xadc96d54, 0x74afa89b, 0xbee0a071, 0x7a48ec78, 0xb007e492,
0x00000000, 0x803e706b, 0x9a05b5e1, 0x1a3bc58a, 0xae723ef5, 0x2e4c4e9e,
0x34778b14, 0xb449fb7f, 0xc69d28dd, 0x46a358b6, 0x5c989d3c, 0xdca6ed57,
0x68ef1628, 0xe8d16643, 0xf2eaa3c9, 0x72d4d3a2, 0x1743048d, 0x977d74e6,
0x8d46b16c, 0x0d78c107, 0xb9313a78, 0x390f4a13, 0x23348f99, 0xa30afff2,
0xd1de2c50, 0x51e05c3b, 0x4bdb99b1, 0xcbe5e9da, 0x7fac12a5, 0xff9262ce,
0xe5a9a744, 0x6597d72f, 0x2e86091a, 0xaeb87971, 0xb483bcfb, 0x34bdcc90,
0x80f437ef, 0x00ca4784, 0x1af1820e, 0x9acff265, 0xe81b21c7, 0x682551ac,
0x721e9426, 0xf220e44d, 0x46691f32, 0xc6576f59, 0xdc6caad3, 0x5c52dab8,
0x39c50d97, 0xb9fb7dfc, 0xa3c0b876, 0x23fec81d, 0x97b73362, 0x17894309,
0x0db28683, 0x8d8cf6e8, 0xff58254a, 0x7f665521, 0x655d90ab, 0xe563e0c0,
0x512a1bbf, 0xd1146bd4, 0xcb2fae5e, 0x4b11de35, 0x5d0c1234, 0xdd32625f,
0xc709a7d5, 0x4737d7be, 0xf37e2cc1, 0x73405caa, 0x697b9920, 0xe945e94b,
0x9b913ae9, 0x1baf4a82, 0x01948f08, 0x81aaff63, 0x35e3041c, 0xb5dd7477,
0xafe6b1fd, 0x2fd8c196, 0x4a4f16b9, 0xca7166d2, 0xd04aa358, 0x5074d333,
0xe43d284c, 0x64035827, 0x7e389dad, 0xfe06edc6, 0x8cd23e64, 0x0cec4e0f,
0x16d78b85, 0x96e9fbee, 0x22a00091, 0xa29e70fa, 0xb8a5b570, 0x389bc51b,
0x738a1b2e, 0xf3b46b45, 0xe98faecf, 0x69b1dea4, 0xddf825db, 0x5dc655b0,
0x47fd903a, 0xc7c3e051, 0xb51733f3, 0x35294398, 0x2f128612, 0xaf2cf679,
0x1b650d06, 0x9b5b7d6d, 0x8160b8e7, 0x015ec88c, 0x64c91fa3, 0xe4f76fc8,
0xfeccaa42, 0x7ef2da29, 0xcabb2156, 0x4a85513d, 0x50be94b7, 0xd080e4dc,
0xa254377e, 0x226a4715, 0x3851829f, 0xb86ff2f4, 0x0c26098b, 0x8c1879e0,
0x9623bc6a, 0x161dcc01, 0xba182468, 0x3a265403, 0x201d9189, 0xa023e1e2,
0x146a1a9d, 0x94546af6, 0x8e6faf7c, 0x0e51df17, 0x7c850cb5, 0xfcbb7cde,
0xe680b954, 0x66bec93f, 0xd2f73240, 0x52c9422b, 0x48f287a1, 0xc8ccf7ca,
0xad5b20e5, 0x2d65508e, 0x375e9504, 0xb760e56f, 0x03291e10, 0x83176e7b,
0x992cabf1, 0x1912db9a, 0x6bc60838, 0xebf87853, 0xf1c3bdd9, 0x71fdcdb2,
0xc5b436cd, 0x458a46a6, 0x5fb1832c, 0xdf8ff347, 0x949e2d72, 0x14a05d19,
0x0e9b9893, 0x8ea5e8f8, 0x3aec1387, 0xbad263ec, 0xa0e9a666, 0x20d7d60d,
0x520305af, 0xd23d75c4, 0xc806b04e, 0x4838c025, 0xfc713b5a, 0x7c4f4b31,
0x66748ebb, 0xe64afed0, 0x83dd29ff, 0x03e35994, 0x19d89c1e, 0x99e6ec75,
0x2daf170a, 0xad916761, 0xb7aaa2eb, 0x3794d280, 0x45400122, 0xc57e7149,
0xdf45b4c3, 0x5f7bc4a8, 0xeb323fd7, 0x6b0c4fbc, 0x71378a36, 0xf109fa5d,
0xe714365c, 0x672a4637, 0x7d1183bd, 0xfd2ff3d6, 0x496608a9, 0xc95878c2,
0xd363bd48, 0x535dcd23, 0x21891e81, 0xa1b76eea, 0xbb8cab60, 0x3bb2db0b,
0x8ffb2074, 0x0fc5501f, 0x15fe9595, 0x95c0e5fe, 0xf05732d1, 0x706942ba,
0x6a528730, 0xea6cf75b, 0x5e250c24, 0xde1b7c4f, 0xc420b9c5, 0x441ec9ae,
0x36ca1a0c, 0xb6f46a67, 0xaccfafed, 0x2cf1df86, 0x98b824f9, 0x18865492,
0x02bd9118, 0x8283e173, 0xc9923f46, 0x49ac4f2d, 0x53978aa7, 0xd3a9facc,
0x67e001b3, 0xe7de71d8, 0xfde5b452, 0x7ddbc439, 0x0f0f179b, 0x8f3167f0,
0x950aa27a, 0x1534d211, 0xa17d296e, 0x21435905, 0x3b789c8f, 0xbb46ece4,
0xded13bcb, 0x5eef4ba0, 0x44d48e2a, 0xc4eafe41, 0x70a3053e, 0xf09d7555,
0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c,
0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869};
static unsigned
lfsr_random(void)
{
static unsigned state = 0x12345678;
unsigned next;
next = lfsr_lut[((state>> 0) & 0xFF) + 0*256];
next ^= lfsr_lut[((state>> 8) & 0xFF) + 1*256];
next ^= lfsr_lut[((state>>16) & 0xFF) + 2*256];
next ^= lfsr_lut[((state>>24) & 0xFF) + 3*256];
return state = next;
}
/*
* Initialize an empty skip list
*/
void
skip_list_init (skip_list_t *list,
skip_list_compare_t compare,
size_t elt_size)
{
int i;
list->compare = compare;
list->elt_size = elt_size;
list->data_size = elt_size - sizeof (skip_elt_t);
for (i = 0; i < MAX_LEVEL; i++) {
list->chains[i] = NULL;
list->freelists[i] = NULL;
}
list->max_level = 0;
}
void
skip_list_fini (skip_list_t *list)
{
skip_elt_t *elt;
int i;
while ((elt = list->chains[0])) {
skip_list_delete_given (list, elt);
}
for (i=0; i<MAX_LEVEL; i++) {
elt = list->freelists[i];
while (elt) {
skip_elt_t *nextfree = elt->prev;
free (ELT_DATA(elt));
elt = nextfree;
}
}
}
/*
* Generate a random level number, distributed
* so that each level is 1/4 as likely as the one before
*
* Note that level numbers run 1 <= level <= MAX_LEVEL
*/
static int
random_level (void)
{
/* tricky bit -- each bit is '1' 75% of the time */
long int bits = lfsr_random() | lfsr_random();
int level = 0;
while (++level < MAX_LEVEL)
{
if (bits & 1)
break;
bits >>= 1;
}
return level;
}
static void *
alloc_node_for_level (skip_list_t *list, unsigned level)
{
if (list->freelists[level-1]) {
skip_elt_t *elt = list->freelists[level-1];
list->freelists[level-1] = elt->prev;
return ELT_DATA(elt);
}
return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *));
}
static void
free_elt (skip_list_t *list, skip_elt_t *elt)
{
elt->prev = list->freelists[elt->prev_index];
list->freelists[elt->prev_index] = elt;
}
/*
* Insert 'data' into the list
*/
void *
skip_list_insert (skip_list_t *list, void *data, int unique)
{
skip_elt_t **update[MAX_LEVEL];
skip_elt_t *prev[MAX_LEVEL];
char *data_and_elt;
skip_elt_t *elt, **next;
int i, level, prev_index;
/*
* Find links along each chain
*/
next = list->chains;
for (i = list->max_level; --i >= 0; )
{
for (; (elt = next[i]); next = elt->next)
{
int cmp = list->compare (list, ELT_DATA(elt), data);
if (unique && 0 == cmp)
return ELT_DATA(elt);
if (cmp > 0)
break;
}
update[i] = next;
if (next != list->chains)
prev[i] = NEXT_TO_ELT (next);
else
prev[i] = NULL;
}
level = random_level ();
prev_index = level - 1;
/*
* Create new list element
*/
if (level > list->max_level)
{
level = list->max_level + 1;
prev_index = level - 1;
prev[prev_index] = NULL;
update[list->max_level] = list->chains;
list->max_level = level;
}
data_and_elt = alloc_node_for_level (list, level);
memcpy (data_and_elt, data, list->data_size);
elt = (skip_elt_t *) (data_and_elt + list->data_size);
elt->prev_index = prev_index;
elt->prev = prev[prev_index];
/*
* Insert into all chains
*/
for (i = 0; i < level; i++)
{
elt->next[i] = update[i][i];
if (elt->next[i] && elt->next[i]->prev_index == i)
elt->next[i]->prev = elt;
update[i][i] = elt;
}
return data_and_elt;
}
void *
skip_list_find (skip_list_t *list, void *data)
{
int i;
skip_elt_t **next = list->chains;
skip_elt_t *elt;
/*
* Walk chain pointers one level at a time
*/
for (i = list->max_level; --i >= 0;)
while (next[i] && list->compare (list, data, ELT_DATA(next[i])) > 0)
{
next = next[i]->next;
}
/*
* Here we are
*/
elt = next[0];
if (elt && list->compare (list, data, ELT_DATA (elt)) == 0)
return ELT_DATA (elt);
return NULL;
}
void
skip_list_delete (skip_list_t *list, void *data)
{
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
skip_elt_t *elt, **next;
int i;
/*
* Find links along each chain
*/
next = list->chains;
for (i = list->max_level; --i >= 0; )
{
for (; (elt = next[i]); next = elt->next)
{
if (list->compare (list, ELT_DATA (elt), data) >= 0)
break;
}
update[i] = &next[i];
if (next == list->chains)
prev[i] = NULL;
else
prev[i] = NEXT_TO_ELT (next);
}
elt = next[0];
assert (list->compare (list, ELT_DATA (elt), data) == 0);
for (i = 0; i < list->max_level && *update[i] == elt; i++) {
*update[i] = elt->next[i];
if (elt->next[i] && elt->next[i]->prev_index == i)
elt->next[i]->prev = prev[i];
}
while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL)
list->max_level--;
free_elt (list, elt);
}
void
skip_list_delete_given (skip_list_t *list, skip_elt_t *given)
{
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
skip_elt_t *elt, **next;
int i;
/*
* Find links along each chain
*/
if (given->prev)
next = given->prev->next;
else
next = list->chains;
for (i = given->prev_index + 1; --i >= 0; )
{
for (; (elt = next[i]); next = elt->next)
{
if (elt == given)
break;
}
update[i] = &next[i];
if (next == list->chains)
prev[i] = NULL;
else
prev[i] = NEXT_TO_ELT (next);
}
elt = next[0];
assert (elt == given);
for (i = 0; i < (given->prev_index + 1) && *update[i] == elt; i++) {
*update[i] = elt->next[i];
if (elt->next[i] && elt->next[i]->prev_index == i)
elt->next[i]->prev = prev[i];
}
while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL)
list->max_level--;
free_elt (list, elt);
}

Просмотреть файл

@ -74,7 +74,7 @@ cairo_private cairo_status_t
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);

Просмотреть файл

@ -548,10 +548,6 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
clear_region = _cairo_region_create_from_rectangle (&extents);
if (clear_region == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -843,7 +839,7 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
typedef struct {
cairo_scaled_font_t *font;
const cairo_glyph_t *glyphs;
cairo_glyph_t *glyphs;
int num_glyphs;
} cairo_show_glyphs_info_t;
@ -911,7 +907,7 @@ cairo_status_t
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -987,6 +987,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
* _cairo_surface_clone_similar:
* @surface: a #cairo_surface_t
* @src: the source image
* @src_x: extent for the rectangle in src we actually care about
* @src_y: extent for the rectangle in src we actually care about
* @width: extent for the rectangle in src we actually care about
* @height: extent for the rectangle in src we actually care about
* @clone_out: location to store a surface compatible with @surface
* and with contents identical to @src. The caller must call
* cairo_surface_destroy() on the result.
@ -1002,6 +1006,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_status_t status;
@ -1014,7 +1022,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
if (surface->backend->clone_similar == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = surface->backend->clone_similar (surface, src, clone_out);
status = surface->backend->clone_similar (surface, src, src_x, src_y,
width, height, clone_out);
if (status == CAIRO_STATUS_SUCCESS)
(*clone_out)->device_transform = src->device_transform;
@ -1025,7 +1034,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
if (status != CAIRO_STATUS_SUCCESS)
return status;
status = surface->backend->clone_similar (surface, &image->base, clone_out);
status = surface->backend->clone_similar (surface, &image->base, src_x,
src_y, width, height, clone_out);
if (status == CAIRO_STATUS_SUCCESS)
(*clone_out)->device_transform = src->device_transform;
@ -1785,7 +1795,7 @@ cairo_status_t
_cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
@ -1863,7 +1873,7 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;

Просмотреть файл

@ -49,6 +49,7 @@
typedef struct cairo_svg_document cairo_svg_document_t;
typedef struct cairo_svg_surface cairo_svg_surface_t;
typedef struct cairo_svg_page cairo_svg_page_t;
static const int invalid_pattern_id = -1;
@ -60,6 +61,12 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
static cairo_bool_t
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
{
return version > CAIRO_SVG_VERSION_1_1;
}
static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] =
{
"SVG 1.1",
@ -72,6 +79,13 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
"1.2"
};
struct cairo_svg_page {
unsigned int surface_id;
unsigned int clip_id;
unsigned int clip_level;
cairo_output_stream_t *xml_node;
};
struct cairo_svg_document {
cairo_output_stream_t *output_stream;
unsigned long refcount;
@ -114,6 +128,7 @@ struct cairo_svg_surface {
cairo_svg_document_t *document;
cairo_output_stream_t *xml_node;
cairo_array_t page_set;
unsigned int clip_level;
unsigned int base_clip;
@ -370,6 +385,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
width, height);
surface->xml_node = _cairo_memory_stream_create ();
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
if (content == CAIRO_CONTENT_COLOR) {
_cairo_output_stream_printf (surface->xml_node,
@ -412,6 +428,52 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
return surface;
}
static cairo_svg_page_t *
_cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
{
unsigned int i;
cairo_svg_page_t page;
page.surface_id = surface->id;
page.clip_id = surface->base_clip;
page.clip_level = surface->clip_level;
page.xml_node = surface->xml_node;
surface->xml_node = _cairo_memory_stream_create ();
surface->clip_level = 0;
for (i = 0; i < page.clip_level; i++)
_cairo_output_stream_printf (page.xml_node, "</g>\n");
_cairo_array_append (&surface->page_set, &page);
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
}
static cairo_int_status_t
_cairo_svg_surface_copy_page (void *abstract_surface)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_page_t *page;
page = _cairo_svg_surface_store_page (surface);
_cairo_memory_stream_copy (page->xml_node, surface->xml_node);
surface->clip_level = page->clip_level;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_svg_surface_show_page (void *abstract_surface)
{
cairo_svg_surface_t *surface = abstract_surface;
_cairo_svg_surface_store_page (surface);
return CAIRO_STATUS_SUCCESS;
}
static void
emit_transform (cairo_output_stream_t *output,
char const *attribute_str,
@ -716,6 +778,8 @@ _cairo_svg_surface_finish (void *abstract_surface)
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
cairo_svg_page_t *page;
unsigned int i;
if (_cairo_paginated_surface_get_target (document->owner) == &surface->base)
status = _cairo_svg_document_finish (document);
@ -724,6 +788,12 @@ _cairo_svg_surface_finish (void *abstract_surface)
_cairo_output_stream_destroy (surface->xml_node);
for (i = 0; i < surface->page_set.num_elements; i++) {
page = _cairo_array_index (&surface->page_set, i);
_cairo_output_stream_destroy (page->xml_node);
}
_cairo_array_fini (&surface->page_set);
_cairo_svg_document_destroy (document);
return status;
@ -902,80 +972,86 @@ static int
emit_meta_surface (cairo_svg_document_t *document,
cairo_meta_surface_t *surface)
{
cairo_surface_t *paginated_surface;
cairo_surface_t *svg_surface;
cairo_meta_snapshot_t new_snapshot;
cairo_array_t *page_set;
cairo_output_stream_t *contents;
cairo_meta_surface_t *meta;
cairo_meta_snapshot_t *snapshot;
unsigned int num_elements;
unsigned int i, id;
/* search in already emitted meta snapshots */
num_elements = document->meta_snapshots.num_elements;
for (i = 0; i < num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);
meta = snapshot->meta;
if (meta->commands.num_elements == surface->commands.num_elements &&
_cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) {
id = snapshot->id;
break;
return snapshot->id;
}
}
if (i >= num_elements) {
cairo_surface_t *paginated_surface;
cairo_surface_t *svg_surface;
cairo_meta_snapshot_t new_snapshot;
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
paginated_surface = _cairo_svg_surface_create_for_document (document,
meta->content,
meta->width_pixels,
meta->height_pixels);
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
cairo_surface_set_fallback_resolution (paginated_surface,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
_cairo_surface_show_page (paginated_surface);
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
paginated_surface = _cairo_svg_surface_create_for_document (document,
meta->content,
meta->width_pixels,
meta->height_pixels);
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
cairo_surface_set_fallback_resolution (paginated_surface,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
_cairo_surface_show_page (paginated_surface);
new_snapshot.meta = meta;
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
new_snapshot.meta = meta;
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
if (meta->content == CAIRO_CONTENT_ALPHA) {
emit_alpha_filter (document);
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\" "
"filter=\"url(#alpha)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
} else {
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
}
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
_cairo_memory_stream_copy (contents, document->xml_node_defs);
for (i = 0; i < ((cairo_svg_surface_t *) svg_surface)->clip_level; i++)
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
id = new_snapshot.id;
cairo_surface_destroy (paginated_surface);
/* FIXME: cairo_paginated_surface doesn't take a ref to the
* passed in target surface so we can't call destroy here.
* cairo_paginated_surface should be fixed, but for now just
* work around it. */
/* cairo_surface_destroy (svg_surface); */
if (meta->content == CAIRO_CONTENT_ALPHA) {
emit_alpha_filter (document);
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\" "
"filter=\"url(#alpha)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
} else {
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
}
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
if (_cairo_memory_stream_length (contents) > 0)
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
if (page_set->num_elements > 0) {
cairo_svg_page_t *page;
page = _cairo_array_index (page_set, page_set->num_elements - 1);
_cairo_memory_stream_copy (page->xml_node, document->xml_node_defs);
}
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
id = new_snapshot.id;
cairo_surface_destroy (paginated_surface);
/* FIXME: cairo_paginated_surface doesn't take a ref to the
* passed in target surface so we can't call destroy here.
* cairo_paginated_surface should be fixed, but for now just
* work around it. */
/* cairo_surface_destroy (svg_surface); */
return id;
}
@ -1532,7 +1608,7 @@ static cairo_int_status_t
_cairo_svg_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *pattern,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
@ -1664,8 +1740,8 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
NULL, /* _cairo_svg_surface_composite, */
NULL, /* _cairo_svg_surface_fill_rectangles, */
NULL, /* _cairo_svg_surface_composite_trapezoids,*/
NULL, /* copy_page */
NULL, /* show_page */
_cairo_svg_surface_copy_page,
_cairo_svg_surface_show_page,
NULL, /* set_clip_region */
_cairo_svg_surface_intersect_clip_path,
_cairo_svg_surface_get_extents,
@ -1759,6 +1835,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
cairo_output_stream_t *output = document->output_stream;
cairo_meta_snapshot_t *snapshot;
cairo_svg_surface_t *surface;
cairo_svg_page_t *page;
unsigned int i;
if (document->finished)
@ -1788,17 +1865,36 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
}
surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner);
_cairo_output_stream_printf (output,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
surface->id,
surface->base_clip);
_cairo_memory_stream_copy (surface->xml_node, output);
if (_cairo_memory_stream_length (surface->xml_node) > 0)
_cairo_svg_surface_store_page (surface);
for (i = 0; i < surface->clip_level; i++)
if (surface->page_set.num_elements > 1 &&
_cairo_svg_version_has_page_set_support (document->svg_version)) {
_cairo_output_stream_printf (output, "<pageSet>\n");
for (i = 0; i < surface->page_set.num_elements; i++) {
page = _cairo_array_index (&surface->page_set, i);
_cairo_output_stream_printf (output, "<page>\n");
_cairo_output_stream_printf (output,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n</page>\n");
}
_cairo_output_stream_printf (output, "</pageSet>\n");
} else if (surface->page_set.num_elements > 0) {
page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
_cairo_output_stream_printf (output,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n");
}
_cairo_output_stream_printf (output, "</g>\n</svg>\n");
_cairo_output_stream_printf (output, "</svg>\n");
_cairo_output_stream_destroy (document->xml_node_glyphs);
_cairo_output_stream_destroy (document->xml_node_defs);

Просмотреть файл

@ -46,7 +46,7 @@ CAIRO_BEGIN_DECLS
* #cairo_svg_version_t is used to describe the version number of the SVG
* specification that a generated SVG file will conform to.
*/
typedef enum {
typedef enum _cairo_svg_version {
CAIRO_SVG_VERSION_1_1,
CAIRO_SVG_VERSION_1_2
} cairo_svg_version_t;

Просмотреть файл

@ -46,11 +46,6 @@ static cairo_status_t
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
static cairo_status_t
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2);
static int
_compare_point_fixed_by_y (const void *av, const void *bv);
@ -69,6 +64,8 @@ _line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_
void
_cairo_traps_init (cairo_traps_t *traps)
{
traps->status = CAIRO_STATUS_SUCCESS;
traps->num_traps = 0;
traps->traps_size = 0;
@ -101,13 +98,11 @@ cairo_status_t
_cairo_traps_init_box (cairo_traps_t *traps,
cairo_box_t *box)
{
cairo_status_t status;
_cairo_traps_init (traps);
status = _cairo_traps_grow_by (traps, 1);
if (status)
return status;
traps->status = _cairo_traps_grow_by (traps, 1);
if (traps->status)
return traps->status;
traps->num_traps = 1;
@ -122,25 +117,27 @@ _cairo_traps_init_box (cairo_traps_t *traps,
traps->extents = *box;
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
static cairo_status_t
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right)
{
cairo_status_t status;
cairo_trapezoid_t *trap;
if (traps->status)
return traps->status;
if (top == bottom) {
return CAIRO_STATUS_SUCCESS;
}
if (traps->num_traps >= traps->traps_size) {
int inc = traps->traps_size ? traps->traps_size : 32;
status = _cairo_traps_grow_by (traps, inc);
if (status)
return status;
traps->status = _cairo_traps_grow_by (traps, inc);
if (traps->status)
return traps->status;
}
trap = &traps->traps[traps->num_traps];
@ -173,10 +170,10 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
traps->num_traps++;
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
static cairo_status_t
cairo_status_t
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2)
@ -184,6 +181,9 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
cairo_line_t left;
cairo_line_t right;
if (traps->status)
return traps->status;
left.p1 = left_p1;
left.p2 = left_p2;
@ -200,21 +200,24 @@ _cairo_traps_grow_by (cairo_traps_t *traps, int additional)
int old_size = traps->traps_size;
int new_size = traps->num_traps + additional;
if (new_size <= traps->traps_size) {
return CAIRO_STATUS_SUCCESS;
}
if (traps->status)
return traps->status;
if (new_size <= traps->traps_size)
return traps->status;
traps->traps_size = new_size;
new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t));
if (new_traps == NULL) {
traps->traps_size = old_size;
return CAIRO_STATUS_NO_MEMORY;
traps->status = CAIRO_STATUS_NO_MEMORY;
return traps->status;
}
traps->traps = new_traps;
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
static int
@ -309,7 +312,6 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
cairo_status_t status;
cairo_line_t line;
cairo_fixed_16_16_t intersect;
cairo_point_t tsort[3];
@ -320,16 +322,16 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
/* horizontal top edge requires special handling */
if (tsort[0].y == tsort[1].y) {
if (tsort[0].x < tsort[1].x)
status = _cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
_cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
else
status = _cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
return status;
_cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
return traps->status;
}
line.p1 = tsort[0];
@ -338,73 +340,146 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
intersect = _compute_x (&line, tsort[2].y);
if (intersect < tsort[2].x) {
status = _cairo_traps_add_trap_from_points (traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[1],
tsort[0], tsort[2]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
if (status)
return status;
_cairo_traps_add_trap_from_points (traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[1],
tsort[0], tsort[2]);
_cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
} else {
status = _cairo_traps_add_trap_from_points (traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[2],
tsort[0], tsort[1]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
if (status)
return status;
_cairo_traps_add_trap_from_points (traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[2],
tsort[0], tsort[1]);
_cairo_traps_add_trap_from_points (traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
}
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
/* Warning: This function reorders the elements of the array provided. */
cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4])
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
{
cairo_status_t status;
int a, b, c, d;
int i;
qsort (q, 4, sizeof (cairo_point_t), _compare_point_fixed_by_y);
/* Choose a as a point with minimal y */
a = 0;
for (i = 1; i < 4; i++)
if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
a = i;
if (q[1].x > q[2].x) {
status = _cairo_traps_add_trap_from_points (traps,
q[0].y, q[1].y, q[0], q[2], q[0], q[1]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
q[1].y, q[2].y, q[0], q[2], q[1], q[3]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
q[2].y, q[3].y, q[2], q[3], q[1], q[3]);
if (status)
return status;
} else {
status = _cairo_traps_add_trap_from_points (traps,
q[0].y, q[1].y, q[0], q[1], q[0], q[2]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
q[1].y, q[2].y, q[1], q[3], q[0], q[2]);
if (status)
return status;
status = _cairo_traps_add_trap_from_points (traps,
q[2].y, q[3].y, q[1], q[3], q[2], q[3]);
if (status)
return status;
/* b and d are adjacent to a, while c is opposite */
b = (a + 1) % 4;
c = (a + 2) % 4;
d = (a + 3) % 4;
/* Choose between b and d so that b.y is less than d.y */
if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
b = (a + 3) % 4;
d = (a + 1) % 4;
}
return CAIRO_STATUS_SUCCESS;
/* Without freedom left to choose anything else, we have four
* cases to tessellate which we can distinguish by comparing c.y
* to d.y and then by comparing b.x to d.x. And then for any of
* these cases there is a trivial way to emit three
* trapezoids. The 4 cases and their trapezoids are described and
* implemented below:
*/
if (q[c].y < q[d].y) {
if (q[b].x < q[d].x) {
/* c.y < d.y && b.x < d.x
*
* top bot left right
* a
* / | a.y b.y ab ad
* b |
* | | b.y c.y bc ad
* c |
* \ | c.y d.y cd ad
* d
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[b], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[c].y,
q[b], q[c], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[c].y, q[d].y,
q[c], q[d], q[a], q[d]);
} else {
/* c.y < d.y && b.x >= d.x
*
* a
* | \ a.y b.y ad ab
* | b
* | | b.y c.y ad bc
* | c
* | / c.y d.y ad cd
* d
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[d], q[a], q[b]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[c].y,
q[a], q[d], q[b], q[c]);
_cairo_traps_add_trap_from_points (traps,
q[c].y, q[d].y,
q[a], q[d], q[c], q[d]);
}
} else {
if (q[b].x < q[d].x) {
/* c.y >= d.y && b.x < d.x
*
* a
* / \ a.y b.y ab ad
* b \
* \ \ b.y d.y bc ad
* \ d
* \ / d.y c.y bc dc
* c
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[b], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[d].y,
q[b], q[c], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[d].y, q[c].y,
q[b], q[c], q[d], q[c]);
} else {
/* c.y >= d.y && b.x >= d.x
*
* a
* / \ a.y b.y ad ab
* / b
* / / b.y d.y ad bc
* d /
* \ / d.y c.y dc bc
* c
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[d], q[a], q[b]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[d].y,
q[a], q[d], q[b], q[c]);
_cairo_traps_add_trap_from_points (traps,
q[d].y, q[c].y,
q[d], q[c], q[b], q[c]);
}
}
return traps->status;
}
static int
@ -730,7 +805,6 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *poly,
cairo_fill_rule_t fill_rule)
{
cairo_status_t status;
int i, active, inactive;
cairo_fixed_t y, y_next, intersect;
int in_out, num_edges = poly->num_edges;
@ -786,9 +860,7 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
if ((in_out & 1) == 0)
continue;
}
status = _cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge);
if (status)
return status;
_cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge);
}
/* delete inactive edges */
@ -801,7 +873,7 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
y = y_next;
}
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
static cairo_bool_t

Просмотреть файл

@ -51,6 +51,7 @@
*/
#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d)
#define TT_TAG_CFF MAKE_TT_TAG('C','F','F',' ')
#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p')
#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ')
#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m')

Просмотреть файл

@ -194,12 +194,12 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
goto fail3;
font->base.num_glyphs = 0;
font->base.x_min = be16_to_cpu (head.x_min);
font->base.y_min = be16_to_cpu (head.y_min);
font->base.x_max = be16_to_cpu (head.x_max);
font->base.y_max = be16_to_cpu (head.y_max);
font->base.ascent = be16_to_cpu (hhea.ascender);
font->base.descent = be16_to_cpu (hhea.descender);
font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
font->base.y_min = (int16_t) be16_to_cpu (head.y_min);
font->base.x_max = (int16_t) be16_to_cpu (head.x_max);
font->base.y_max = (int16_t) be16_to_cpu (head.y_max);
font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender);
font->base.descent = (int16_t) be16_to_cpu (hhea.descender);
/* Extract the font name from the name table. At present this
* just looks for the Mac platform/Roman encoded font name. It
@ -591,10 +591,9 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
}
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
(num_hmetrics - 1) * long_entry_size +
(font->glyphs[i].parent_index - num_hmetrics)
* short_entry_size,
(unsigned char *) (p+1), &short_entry_size);
num_hmetrics * long_entry_size +
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
(unsigned char *) (p + 1), &short_entry_size);
}
font->base.widths[i] = be16_to_cpu (p[0]);
}

Просмотреть файл

@ -64,7 +64,8 @@ typedef struct _cairo_type1_font {
static cairo_status_t
cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_type1_font_t **subset_return)
cairo_type1_font_t **subset_return,
cairo_bool_t hex_encode)
{
cairo_type1_font_t *font;
cairo_font_face_t *font_face;
@ -84,6 +85,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
}
font->scaled_font_subset = scaled_font_subset;
font->hex_encode = hex_encode;
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
@ -98,12 +100,20 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
&font_matrix,
&ctm,
&font_options);
if (font->type1_scaled_font == NULL)
goto fail;
_cairo_array_init (&font->contents, sizeof (unsigned char));
*subset_return = font;
return CAIRO_STATUS_SUCCESS;
fail:
free (font->widths);
free (font);
return CAIRO_STATUS_NO_MEMORY;
}
/* Magic constants for the type1 eexec encryption */
@ -378,14 +388,19 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
path_info.data = data;
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
_cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
_charstring_line_to,
_charstring_curve_to,
_charstring_close_path,
&path_info);
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
_charstring_line_to,
_charstring_curve_to,
_charstring_close_path,
&path_info);
if (status)
return status;
status = _cairo_array_grow_by (data, 1);
if (status)
return status;
charstring_encode_command (path_info.data, CHARSTRING_endchar);
return CAIRO_STATUS_SUCCESS;
@ -395,7 +410,7 @@ static cairo_int_status_t
cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
cairo_output_stream_t *encrypted_output)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
unsigned char zeros[] = { 0, 0, 0, 0 };
cairo_array_t data;
unsigned int i;
@ -413,7 +428,9 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
_cairo_array_append_multiple (&data, zeros, 4);
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
&data);
@ -432,8 +449,12 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
_cairo_array_append_multiple (&data, zeros, 4);
create_notdef_charstring (&data);
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
status = create_notdef_charstring (&data);
if (status)
goto fail;
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
_cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
@ -447,7 +468,7 @@ fail:
return status;
}
static cairo_status_t
static void
cairo_type1_font_write_header (cairo_type1_font_t *font,
const char *name)
{
@ -495,8 +516,6 @@ cairo_type1_font_write_header (cairo_type1_font_t *font,
"readonly def\n"
"currentdict end\n"
"currentfile eexec\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -546,14 +565,15 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
cairo_output_stream_t *encrypted_output;
font->eexec_key = private_dict_key;
font->hex_encode = TRUE;
font->hex_column = 0;
encrypted_output = _cairo_output_stream_create (
cairo_type1_write_stream_encrypted,
NULL,
font);
if (encrypted_output == NULL)
if (encrypted_output == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail;
}
/* Note: the first four spaces at the start of this private dict
* are the four "random" bytes of plaintext required by the
@ -589,7 +609,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
return status;
}
static cairo_status_t
static void
cairo_type1_font_write_trailer(cairo_type1_font_t *font)
{
int i;
@ -600,8 +620,6 @@ cairo_type1_font_write_trailer(cairo_type1_font_t *font)
_cairo_output_stream_write (font->output, zeros, sizeof zeros);
_cairo_output_stream_printf (font->output, "cleartomark\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -667,17 +685,18 @@ cairo_type1_font_destroy (cairo_type1_font_t *font)
free (font);
}
cairo_status_t
_cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset)
static cairo_status_t
_cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset,
cairo_bool_t hex_encode)
{
cairo_type1_font_t *font;
cairo_status_t status;
unsigned long length;
unsigned int i, len;
status = cairo_type1_font_create (scaled_font_subset, &font);
status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode);
if (status)
return status;
@ -686,12 +705,16 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
goto fail1;
type1_subset->base_font = strdup (name);
if (type1_subset->base_font == NULL)
if (type1_subset->base_font == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail1;
}
type1_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (type1_subset->widths == NULL)
if (type1_subset->widths == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail2;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
type1_subset->widths[i] = font->widths[i];
@ -705,9 +728,10 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
length = font->header_size + font->data_size +
font->trailer_size;
type1_subset->data = malloc (length);
if (type1_subset->data == NULL)
if (type1_subset->data == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail3;
}
memcpy (type1_subset->data,
_cairo_array_index (&font->contents, 0), length);
@ -737,6 +761,26 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
return status;
}
cairo_status_t
_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset)
{
return _cairo_type1_fallback_init_internal (type1_subset,
name,
scaled_font_subset, FALSE);
}
cairo_status_t
_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset)
{
return _cairo_type1_fallback_init_internal (type1_subset,
name,
scaled_font_subset, TRUE);
}
void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
{

Просмотреть файл

@ -280,7 +280,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
_cairo_output_stream_printf (font->output,
"/Encoding 256 array\n"
"0 1 255 {1 index exch /.notdef put} for\n");
for (i = 0; i < font->base.num_glyphs; i++) {
for (i = 1; i < font->base.num_glyphs; i++) {
if (font->glyphs[i].subset_index < 0)
continue;
_cairo_output_stream_printf (font->output,
@ -1008,6 +1008,9 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode);

Просмотреть файл

@ -218,7 +218,7 @@ cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
#define _cairo_uint128_to_int128_(i) (i)
#define _cairo_uint128_to_int128(i) (i)
#define _cairo_int128_to_uint128(i) (i)
cairo_int128_t I _cairo_int32_to_int128 (int32_t i);
@ -298,6 +298,14 @@ _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den);
cairo_quorem128_t I
_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den);
cairo_uquorem64_t I
_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num,
cairo_uint64_t den);
cairo_quorem64_t I
_cairo_int_96by64_32x64_divrem (cairo_int128_t num,
cairo_int64_t den);
#define _cairo_uint128_le(a,b) (!_cairo_uint128_gt(a,b))
#define _cairo_uint128_ne(a,b) (!_cairo_uint128_eq(a,b))
#define _cairo_uint128_ge(a,b) (!_cairo_uint128_lt(a,b))

Просмотреть файл

@ -71,7 +71,7 @@ _cairo_int32_to_int64 (int32_t i)
return q;
}
static const cairo_uint64_t
static cairo_uint64_t
_cairo_uint32s_to_uint64 (uint32_t h, uint32_t l)
{
cairo_uint64_t q;
@ -407,7 +407,7 @@ _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b)
#define uint64_lo32(i) ((i).lo)
#define uint64_hi32(i) ((i).hi)
static const cairo_uint64_t
static cairo_uint64_t
uint64_lo (cairo_uint64_t i)
{
cairo_uint64_t s;
@ -417,7 +417,7 @@ uint64_lo (cairo_uint64_t i)
return s;
}
static const cairo_uint64_t
static cairo_uint64_t
uint64_hi (cairo_uint64_t i)
{
cairo_uint64_t s;
@ -427,7 +427,7 @@ uint64_hi (cairo_uint64_t i)
return s;
}
static const cairo_uint64_t
static cairo_uint64_t
uint64_shift32 (cairo_uint64_t i)
{
cairo_uint64_t s;
@ -656,3 +656,155 @@ _cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den)
qr.quo = uqr.quo;
return qr;
}
/**
* _cairo_uint_96by64_32x64_divrem:
*
* Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned
* dividend and 64 bit divisor. If the quotient doesn't fit into 32
* bits then the returned remainder is equal to the divisor, and the
* qoutient is the largest representable 64 bit integer. It is an
* error to call this function with the high 32 bits of @num being
* non-zero. */
cairo_uquorem64_t
_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num,
cairo_uint64_t den)
{
cairo_uquorem64_t result;
cairo_uint64_t B = _cairo_uint32s_to_uint64 (1, 0);
/* These are the high 64 bits of the *96* bit numerator. We're
* going to represent the numerator as xB + y, where x is a 64,
* and y is a 32 bit number. */
cairo_uint64_t x = _cairo_uint128_to_uint64 (_cairo_uint128_rsl(num, 32));
/* Initialise the result to indicate overflow. */
result.quo = _cairo_uint32s_to_uint64 (-1U, -1U);
result.rem = den;
/* Don't bother if the quotient is going to overflow. */
if (_cairo_uint64_ge (x, den)) {
return /* overflow */ result;
}
if (_cairo_uint64_lt (x, B)) {
/* When the final quotient is known to fit in 32 bits, then
* num < 2^64 if and only if den < 2^32. */
return _cairo_uint64_divrem (_cairo_uint128_to_uint64 (num), den);
}
else {
/* Denominator is >= 2^32. the numerator is >= 2^64, and the
* division won't overflow: need two divrems. Write the
* numerator and denominator as
*
* num = xB + y x : 64 bits, y : 32 bits
* den = uB + v u, v : 32 bits
*/
uint32_t y = _cairo_uint128_to_uint32 (num);
uint32_t u = uint64_hi32 (den);
uint32_t v = _cairo_uint64_to_uint32 (den);
/* Compute a lower bound approximate quotient of num/den
* from x/(u+1). Then we have
*
* x = q(u+1) + r ; q : 32 bits, r <= u : 32 bits.
*
* xB + y = q(u+1)B + (rB+y)
* = q(uB + B + v - v) + (rB+y)
* = q(uB + v) + qB - qv + (rB+y)
* = q(uB + v) + q(B-v) + (rB+y)
*
* The true quotient of num/den then is q plus the
* contribution of q(B-v) + (rB+y). The main contribution
* comes from the term q(B-v), with the term (rB+y) only
* contributing at most one part.
*
* The term q(B-v) must fit into 64 bits, since q fits into 32
* bits on account of being a lower bound to the true
* quotient, and as B-v <= 2^32, we may safely use a single
* 64/64 bit division to find its contribution. */
cairo_uquorem64_t quorem;
cairo_uint64_t remainder; /* will contain final remainder */
uint32_t quotient; /* will contain final quotient. */
uint32_t q;
uint32_t r;
/* Approximate quotient by dividing the high 64 bits of num by
* u+1. Watch out for overflow of u+1. */
if (u+1) {
quorem = _cairo_uint64_divrem (x, _cairo_uint32_to_uint64 (u+1));
q = _cairo_uint64_to_uint32 (quorem.quo);
r = _cairo_uint64_to_uint32 (quorem.rem);
}
else {
q = uint64_hi32 (x);
r = _cairo_uint64_to_uint32 (x);
}
quotient = q;
/* Add the main term's contribution to quotient. Note B-v =
* -v as an uint32 (unless v = 0) */
if (v)
quorem = _cairo_uint64_divrem (_cairo_uint32x32_64_mul (q, -v), den);
else
quorem = _cairo_uint64_divrem (_cairo_uint32s_to_uint64 (q, 0), den);
quotient += _cairo_uint64_to_uint32 (quorem.quo);
/* Add the contribution of the subterm and start computing the
* true remainder. */
remainder = _cairo_uint32s_to_uint64 (r, y);
if (_cairo_uint64_ge (remainder, den)) {
remainder = _cairo_uint64_sub (remainder, den);
quotient++;
}
/* Add the contribution of the main term's remainder. The
* funky test here checks that remainder + main_rem >= den,
* taking into account overflow of the addition. */
remainder = _cairo_uint64_add (remainder, quorem.rem);
if (_cairo_uint64_ge (remainder, den) ||
_cairo_uint64_lt (remainder, quorem.rem))
{
remainder = _cairo_uint64_sub (remainder, den);
quotient++;
}
result.quo = _cairo_uint32_to_uint64 (quotient);
result.rem = remainder;
}
return result;
}
cairo_quorem64_t
_cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
{
int num_neg = _cairo_int128_negative (num);
int den_neg = _cairo_int64_negative (den);
cairo_int64_t nonneg_den = den;
cairo_uquorem64_t uqr;
cairo_quorem64_t qr;
if (num_neg)
num = _cairo_int128_negate (num);
if (den_neg)
nonneg_den = _cairo_int64_negate (den);
uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den);
if (_cairo_uint64_eq (uqr.rem, nonneg_den)) {
/* bail on overflow. */
qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);;
qr.rem = den;
return qr;
}
if (num_neg)
qr.rem = _cairo_int64_negate (uqr.rem);
else
qr.rem = uqr.rem;
if (num_neg != den_neg)
qr.quo = _cairo_int64_negate (uqr.quo);
else
qr.quo = uqr.quo;
return qr;
}

Просмотреть файл

@ -1,304 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Keith Packard
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Keith Packard
*
* Contributor(s):
* Keith R. Packard <keithp@keithp.com>
*
*/
#ifndef CAIRO_WIDEINT_H
#define CAIRO_WIDEINT_H
#if HAVE_STDINT_H
# include <stdint.h>
#elif HAVE_INTTYPES_H
# include <inttypes.h>
#elif HAVE_SYS_INT_TYPES_H
# include <sys/int_types.h>
#elif defined(_MSC_VER)
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# ifndef HAVE_UINT64_T
# define HAVE_UINT64_T 1
# endif
#else
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
#endif
/*
* 64-bit datatypes. Two separate implementations, one using
* built-in 64-bit signed/unsigned types another implemented
* as a pair of 32-bit ints
*/
#define I cairo_private
#if !HAVE_UINT64_T
typedef struct _cairo_uint64 {
uint32_t lo, hi;
} cairo_uint64_t, cairo_int64_t;
cairo_uint64_t I _cairo_uint32_to_uint64 (uint32_t i);
#define _cairo_uint64_to_uint32(a) ((a).lo)
cairo_uint64_t I _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint64_t I _cairo_uint64_sub (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint64_t I _cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint64_t I _cairo_uint32x32_64_mul (uint32_t a, uint32_t b);
cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift);
cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift);
cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift);
int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b);
int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a);
#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0)
cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a);
#define _cairo_uint64_to_int64(i) (i)
#define _cairo_int64_to_uint64(i) (i)
cairo_int64_t I _cairo_int32_to_int64(int32_t i);
#define _cairo_int64_to_int32(a) ((int32_t) _cairo_uint64_to_uint32(a))
#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b)
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b)
#define _cairo_int64_rsa(a,b) _cairo_uint64_rsa (a,b)
#define _cairo_int64_negate(a) _cairo_uint64_negate(a)
#define _cairo_int64_negative(a) (((int32_t) ((a).hi)) < 0)
#define _cairo_int64_not(a) _cairo_uint64_not(a)
#else
typedef uint64_t cairo_uint64_t;
typedef int64_t cairo_int64_t;
#define _cairo_uint32_to_uint64(i) ((uint64_t) (i))
#define _cairo_uint64_to_uint32(i) ((uint32_t) (i))
#define _cairo_uint64_add(a,b) ((a) + (b))
#define _cairo_uint64_sub(a,b) ((a) - (b))
#define _cairo_uint64_mul(a,b) ((a) * (b))
#define _cairo_uint32x32_64_mul(a,b) ((uint64_t) (a) * (b))
#define _cairo_uint64_lsl(a,b) ((a) << (b))
#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b))
#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b)))
#define _cairo_uint64_lt(a,b) ((a) < (b))
#define _cairo_uint64_eq(a,b) ((a) == (b))
#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a)))
#define _cairo_uint64_negative(a) ((int64_t) (a) < 0)
#define _cairo_uint64_not(a) (~(a))
#define _cairo_uint64_to_int64(i) ((int64_t) (i))
#define _cairo_int64_to_uint64(i) ((uint64_t) (i))
#define _cairo_int32_to_int64(i) ((int64_t) (i))
#define _cairo_int64_to_int32(i) ((int32_t) (i))
#define _cairo_int64_add(a,b) ((a) + (b))
#define _cairo_int64_sub(a,b) ((a) - (b))
#define _cairo_int64_mul(a,b) ((a) * (b))
#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b))
#define _cairo_int64_lt(a,b) ((a) < (b))
#define _cairo_int64_eq(a,b) ((a) == (b))
#define _cairo_int64_lsl(a,b) ((a) << (b))
#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b)))
#define _cairo_int64_rsa(a,b) ((int64_t) (a) >> (b))
#define _cairo_int64_negate(a) (-(a))
#define _cairo_int64_negative(a) ((a) < 0)
#define _cairo_int64_not(a) (~(a))
#endif
/*
* 64-bit comparisions derived from lt or eq
*/
#define _cairo_uint64_le(a,b) (!_cairo_uint64_gt(a,b))
#define _cairo_uint64_ne(a,b) (!_cairo_uint64_eq(a,b))
#define _cairo_uint64_ge(a,b) (!_cairo_uint64_lt(a,b))
#define _cairo_uint64_gt(a,b) _cairo_uint64_lt(b,a)
#define _cairo_int64_le(a,b) (!_cairo_int64_gt(a,b))
#define _cairo_int64_ne(a,b) (!_cairo_int64_eq(a,b))
#define _cairo_int64_ge(a,b) (!_cairo_int64_lt(a,b))
#define _cairo_int64_gt(a,b) _cairo_int64_lt(b,a)
/*
* As the C implementation always computes both, create
* a function which returns both for the 'native' type as well
*/
typedef struct _cairo_uquorem64 {
cairo_uint64_t quo;
cairo_uint64_t rem;
} cairo_uquorem64_t;
typedef struct _cairo_quorem64 {
cairo_int64_t quo;
cairo_int64_t rem;
} cairo_quorem64_t;
cairo_uquorem64_t I
_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den);
cairo_quorem64_t I
_cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den);
/*
* 128-bit datatypes. Again, provide two implementations in
* case the machine has a native 128-bit datatype. GCC supports int128_t
* on ia64
*/
#if !HAVE_UINT128_T
typedef struct cairo_uint128 {
cairo_uint64_t lo, hi;
} cairo_uint128_t, cairo_int128_t;
cairo_uint128_t I _cairo_uint32_to_uint128 (uint32_t i);
cairo_uint128_t I _cairo_uint64_to_uint128 (cairo_uint64_t i);
#define _cairo_uint128_to_uint64(a) ((a).lo)
#define _cairo_uint128_to_uint32(a) _cairo_uint64_to_uint32(_cairo_uint128_to_uint64(a))
cairo_uint128_t I _cairo_uint128_add (cairo_uint128_t a, cairo_uint128_t b);
cairo_uint128_t I _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b);
cairo_uint128_t I _cairo_uint128_mul (cairo_uint128_t a, cairo_uint128_t b);
cairo_uint128_t I _cairo_uint64x64_128_mul (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift);
cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift);
cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift);
int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b);
int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b);
cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
#define _cairo_uint128_to_int128_(i) (i)
#define _cairo_int128_to_uint128(i) (i)
cairo_int128_t I _cairo_int32_to_int128 (int32_t i);
cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
#define _cairo_int128_to_int64(a) ((cairo_int64_t) (a).lo)
#define _cairo_int128_to_int32(a) _cairo_int64_to_int32(_cairo_int128_to_int64(a))
#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b)
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b)
#define _cairo_int128_negate(a) _cairo_uint128_negate(a)
#define _cairo_int128_negative(a) (_cairo_uint128_negative(a))
#define _cairo_int128_not(a) _cairo_uint128_not(a)
#else /* !HAVE_UINT128_T */
typedef uint128_t cairo_uint128_t;
typedef int128_t cairo_int128_t;
#define _cairo_uint32_to_uint128(i) ((uint128_t) (i))
#define _cairo_uint64_to_uint128(i) ((uint128_t) (i))
#define _cairo_uint128_to_uint64(i) ((uint64_t) (i))
#define _cairo_uint128_to_uint32(i) ((uint32_t) (i))
#define _cairo_uint128_add(a,b) ((a) + (b))
#define _cairo_uint128_sub(a,b) ((a) - (b))
#define _cairo_uint128_mul(a,b) ((a) * (b))
#define _cairo_uint64x64_128_mul(a,b) ((uint128_t) (a) * (b))
#define _cairo_uint128_lsl(a,b) ((a) << (b))
#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b))
#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b)))
#define _cairo_uint128_lt(a,b) ((a) < (b))
#define _cairo_uint128_eq(a,b) ((a) == (b))
#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a)))
#define _cairo_uint128_negative(a) ((int128_t) (a) < 0)
#define _cairo_uint128_not(a) (~(a))
#define _cairo_uint128_to_int128(i) ((int128_t) (i))
#define _cairo_int128_to_uint128(i) ((uint128_t) (i))
#define _cairo_int32_to_int128(i) ((int128_t) (i))
#define _cairo_int64_to_int128(i) ((int128_t) (i))
#define _cairo_int128_to_int64(i) ((int64_t) (i))
#define _cairo_int128_to_int32(i) ((int32_t) (i))
#define _cairo_int128_add(a,b) ((a) + (b))
#define _cairo_int128_sub(a,b) ((a) - (b))
#define _cairo_int128_mul(a,b) ((a) * (b))
#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b))
#define _cairo_int128_lt(a,b) ((a) < (b))
#define _cairo_int128_eq(a,b) ((a) == (b))
#define _cairo_int128_lsl(a,b) ((a) << (b))
#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b)))
#define _cairo_int128_rsa(a,b) ((int128_t) (a) >> (b))
#define _cairo_int128_negate(a) (-(a))
#define _cairo_int128_negative(a) ((a) < 0)
#define _cairo_int128_not(a) (~(a))
#endif /* HAVE_UINT128_T */
typedef struct _cairo_uquorem128 {
cairo_uint128_t quo;
cairo_uint128_t rem;
} cairo_uquorem128_t;
typedef struct _cairo_quorem128 {
cairo_int128_t quo;
cairo_int128_t rem;
} cairo_quorem128_t;
cairo_uquorem128_t I
_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den);
cairo_quorem128_t I
_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den);
#define _cairo_uint128_le(a,b) (!_cairo_uint128_gt(a,b))
#define _cairo_uint128_ne(a,b) (!_cairo_uint128_eq(a,b))
#define _cairo_uint128_ge(a,b) (!_cairo_uint128_lt(a,b))
#define _cairo_uint128_gt(a,b) _cairo_uint128_lt(b,a)
#define _cairo_int128_le(a,b) (!_cairo_int128_gt(a,b))
#define _cairo_int128_ne(a,b) (!_cairo_int128_eq(a,b))
#define _cairo_int128_ge(a,b) (!_cairo_int128_lt(a,b))
#define _cairo_int128_gt(a,b) _cairo_int128_lt(b,a)
#undef I
#endif /* CAIRO_WIDEINT_H */

Просмотреть файл

@ -151,7 +151,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
scaled_font->y_scale = - scaled_font->y_scale;
scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * floor (scaled_font->y_scale + 0.5);
scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
_cairo_lround (scaled_font->y_scale);
}
/* The font matrix has x and y "scale" components which we extract and
@ -165,7 +166,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
&scaled_font->x_scale, &scaled_font->y_scale,
TRUE); /* XXX: Handle vertical text */
scaled_font->logical_size = floor (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale + 0.5);
scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
scaled_font->y_scale);
scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
}
@ -864,8 +866,8 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
glyph_index_option = 0;
for (i = 0; i < num_glyphs; i++) {
int x = floor (0.5 + glyphs[i].x);
int y = floor (0.5 + glyphs[i].y);
int x = _cairo_lround (glyphs[i].x);
int y = _cairo_lround (glyphs[i].y);
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
&metrics, 0, NULL, &matrix);
@ -966,8 +968,8 @@ _add_glyph (cairo_glyph_state_t *state,
cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
logical_x = floor (user_x + 0.5);
logical_y = floor (user_y + 0.5);
logical_x = _cairo_lround (user_x);
logical_y = _cairo_lround (user_y);
if (state->glyphs.num_elements > 0) {
int dx;
@ -1149,7 +1151,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;

Просмотреть файл

@ -106,6 +106,6 @@ cairo_bool_t
_cairo_surface_is_win32 (cairo_surface_t *surface);
void
_cairo_win32_initialize ();
_cairo_win32_initialize (void);
#endif /* CAIRO_WIN32_PRIVATE_H */

Просмотреть файл

@ -1473,7 +1473,7 @@ static cairo_int_status_t
_cairo_win32_surface_show_glyphs (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
@ -1481,19 +1481,21 @@ _cairo_win32_surface_show_glyphs (void *surface,
WORD glyph_buf_stack[STACK_GLYPH_SIZE];
WORD *glyph_buf = glyph_buf_stack;
int dx_buf_stack[STACK_GLYPH_SIZE];
int *dx_buf = dx_buf_stack;
int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
int *dxy_buf = dxy_buf_stack;
BOOL win_result = 0;
int i;
double last_y = glyphs[0].y;
int i, j;
cairo_solid_pattern_t *solid_pattern;
COLORREF color;
int output_count = 0;
cairo_matrix_t device_to_logical;
int start_x, start_y;
double user_x, user_y;
int logical_x, logical_y;
/* We can only handle win32 fonts */
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1531,58 +1533,68 @@ _cairo_win32_surface_show_glyphs (void *surface,
if (num_glyphs > STACK_GLYPH_SIZE) {
glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
dx_buf = (int *)malloc(num_glyphs * sizeof(int));
dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
}
for (i = 0; i < num_glyphs; ++i) {
output_count++;
/* It is vital that dx values for dxy_buf are calculated from the delta of
* _logical_ x coordinates (not user x coordinates) or else the sum of all
* previous dx values may start to diverge from the current glyph's x
* coordinate due to accumulated rounding error. As a result strings could
* be painted shorter or longer than expected. */
glyph_buf[i] = (WORD) glyphs[i].index;
if (i == num_glyphs - 1)
dx_buf[i] = 0;
else
dx_buf[i] = (int) floor(((glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE) + 0.5);
user_x = glyphs[0].x;
user_y = glyphs[0].y;
if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {
const int offset = (i - output_count) + 1;
double user_x = glyphs[offset].x;
double user_y = last_y;
int logical_x, logical_y;
cairo_matrix_transform_point(&device_to_logical,
&user_x, &user_y);
cairo_matrix_transform_point(&device_to_logical,
&user_x, &user_y);
logical_x = _cairo_lround (user_x);
logical_y = _cairo_lround (user_y);
logical_x = (int) floor(user_x + 0.5);
logical_y = (int) floor(user_y + 0.5);
start_x = logical_x;
start_y = logical_y;
win_result = ExtTextOutW(dst->dc,
logical_x,
logical_y,
ETO_GLYPH_INDEX,
NULL,
glyph_buf + offset,
output_count,
dx_buf + offset);
if (!win_result) {
_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
goto FAIL;
}
for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
glyph_buf[i] = (WORD) glyphs[i].index;
if (i == num_glyphs - 1) {
dxy_buf[j] = 0;
dxy_buf[j+1] = 0;
} else {
double next_user_x = glyphs[i+1].x;
double next_user_y = glyphs[i+1].y;
int next_logical_x, next_logical_y;
output_count = 0;
cairo_matrix_transform_point(&device_to_logical,
&next_user_x, &next_user_y);
if (i < num_glyphs - 1)
last_y = glyphs[i+1].y;
} else {
last_y = glyphs[i].y;
}
next_logical_x = _cairo_lround (next_user_x);
next_logical_y = _cairo_lround (next_user_y);
dxy_buf[j] = _cairo_lround ((next_logical_x - logical_x) * WIN32_FONT_LOGICAL_SCALE);
dxy_buf[j+1] = _cairo_lround ((logical_y - start_y) * WIN32_FONT_LOGICAL_SCALE);
logical_x = next_logical_x;
logical_y = next_logical_y;
}
}
win_result = ExtTextOutW(dst->dc,
start_x,
start_y,
ETO_GLYPH_INDEX | ETO_PDY,
NULL,
glyph_buf,
num_glyphs,
dxy_buf);
if (!win_result) {
_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
}
FAIL:
RestoreDC(dst->dc, -1);
if (glyph_buf != glyph_buf_stack) {
free(glyph_buf);
free(dx_buf);
free(dxy_buf);
}
return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
}

Просмотреть файл

@ -40,6 +40,16 @@
#if CAIRO_HAS_WIN32_SURFACE
#define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features. Although we don't use them here, things
* should still work if this header file ends up being the one to include
* windows.h into a source file, so: */
#if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
CAIRO_BEGIN_DECLS

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -41,16 +41,16 @@
#if CAIRO_HAS_XCB_SURFACE
#include <X11/XCB/xcb.h>
#include <X11/XCB/render.h>
#include <xcb/xcb.h>
#include <xcb/render.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_xcb_surface_create_with_xrender_format (XCBConnection *c,
XCBDRAWABLE drawable,
XCBSCREEN *screen,
XCBRenderPICTFORMINFO *format,
cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *c,
xcb_drawable_t drawable,
xcb_screen_t *screen,
xcb_render_pictforminfo_t *format,
int width,
int height);

Просмотреть файл

@ -41,21 +41,21 @@
#if CAIRO_HAS_XCB_SURFACE
#include <X11/XCB/xcb.h>
#include <xcb/xcb.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_xcb_surface_create (XCBConnection *c,
XCBDRAWABLE drawable,
XCBVISUALTYPE *visual,
cairo_xcb_surface_create (xcb_connection_t *c,
xcb_drawable_t drawable,
xcb_visualtype_t *visual,
int width,
int height);
cairo_public cairo_surface_t *
cairo_xcb_surface_create_for_bitmap (XCBConnection *c,
XCBPIXMAP bitmap,
XCBSCREEN *screen,
cairo_xcb_surface_create_for_bitmap (xcb_connection_t *c,
xcb_pixmap_t bitmap,
xcb_screen_t *screen,
int width,
int height);

Просмотреть файл

@ -54,6 +54,7 @@ _cairo_xlib_screen_info_get (Display *display, Screen *screen);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
#include "cairo-xlib-xrender.h"
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
#endif

Просмотреть файл

@ -33,6 +33,7 @@
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Behdad Esfahbod <behdad@behdad.org>
*/
#include "cairoint.h"
@ -69,7 +70,7 @@ static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
cairo_pattern_t *src_pattern,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
@ -744,6 +745,10 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
static cairo_status_t
_draw_image_surface (cairo_xlib_surface_t *surface,
cairo_image_surface_t *image,
int src_x,
int src_y,
int width,
int height,
int dst_x,
int dst_y)
{
@ -774,8 +779,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
_cairo_xlib_surface_ensure_gc (surface);
XPutImage(surface->dpy, surface->drawable, surface->gc,
&ximage, 0, 0, dst_x, dst_y,
image->width, image->height);
&ximage, src_x, src_y, dst_x, dst_y,
width, height);
return CAIRO_STATUS_SUCCESS;
@ -839,7 +844,8 @@ _cairo_xlib_surface_release_dest_image (void *abstract_surfac
cairo_xlib_surface_t *surface = abstract_surface;
/* ignore errors */
_draw_image_surface (surface, image, image_rect->x, image_rect->y);
_draw_image_surface (surface, image, 0, 0, image->width, image->height,
image_rect->x, image_rect->y);
cairo_surface_destroy (&image->base);
}
@ -859,6 +865,10 @@ _cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst,
static cairo_status_t
_cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_xlib_surface_t *surface = abstract_surface;
@ -884,7 +894,8 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
_draw_image_surface (clone, image_src, 0, 0);
_draw_image_surface (clone, image_src, src_x, src_y,
width, height, src_x, src_y);
*clone_out = &clone->base;
@ -2008,6 +2019,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
NULL, format, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
/**
* cairo_xlib_surface_set_size:
@ -2397,12 +2409,12 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
*/
/* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
glyph_info.x = - (int) floor(glyph_surface->base.device_transform.x0 + 0.5);
glyph_info.y = - (int) floor(glyph_surface->base.device_transform.y0 + 0.5);
glyph_info.x = - _cairo_lround (glyph_surface->base.device_transform.x0);
glyph_info.y = - _cairo_lround (glyph_surface->base.device_transform.y0);
glyph_info.width = glyph_surface->width;
glyph_info.height = glyph_surface->height;
glyph_info.xOff = 0;
glyph_info.yOff = 0;
glyph_info.xOff = scaled_glyph->x_advance;
glyph_info.yOff = scaled_glyph->y_advance;
data = glyph_surface->data;
@ -2485,200 +2497,301 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
return status;
}
#define N_STACK_BUF 1024
typedef void (*cairo_xrender_composite_text_func_t)
(Display *dpy,
int op,
Picture src,
Picture dst,
_Xconst XRenderPictFormat *maskFormat,
int xSrc,
int ySrc,
int xDst,
int yDst,
_Xconst XGlyphElt8 *elts,
int nelt);
/* Build a struct of the same size of cairo_glyph_t that can be used both as
* an input glyph with double coordinates, and as "working" glyph with
* integer from-current-point offsets. */
typedef struct {
unsigned long index;
union {
struct {
double x;
double y;
} d;
struct {
int x;
int y;
} i;
} p;
} cairo_xlib_glyph_t;
#define GLYPH_INDEX_SKIP ((unsigned long) -1)
#define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8)))
static cairo_status_t
_cairo_xlib_surface_show_glyphs8 (cairo_xlib_surface_t *dst,
cairo_operator_t op,
cairo_xlib_surface_t *src,
int src_x_offset, int src_y_offset,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
cairo_xlib_glyph_t *glyphs,
int num_glyphs,
int width,
int num_elts,
cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_surface_attributes_t *attributes)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt8 *elts = NULL;
XGlyphElt8 stack_elts [N_STACK_BUF];
/* Which XRenderCompositeText function to use */
cairo_xrender_composite_text_func_t composite_text_func;
int size;
char *chars = NULL;
char stack_chars [N_STACK_BUF];
/* Element buffer stuff */
XGlyphElt8 *elts;
XGlyphElt8 stack_elts[STACK_ELTS_LEN];
/* Reuse the input glyph array for output char generation */
char *char8 = (char *) glyphs;
unsigned short *char16 = (unsigned short *) glyphs;
unsigned int *char32 = (unsigned int *) glyphs;
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
int nelt; /* Element index */
int n; /* Num output glyphs in current element */
int j; /* Num output glyphs so far */
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
chars = stack_chars;
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
switch (width) {
case 1:
/* don't cast the 8-variant, to catch possible mismatches */
composite_text_func = XRenderCompositeText8;
size = sizeof (char);
break;
case 2:
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16;
size = sizeof (unsigned short);
break;
default:
case 4:
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32;
size = sizeof (unsigned int);
}
/* Allocate element array */
if (num_elts <= STACK_ELTS_LEN) {
elts = stack_elts;
} else {
elts = malloc (num_glyphs * sizeof (XGlyphElt8) +
num_glyphs * sizeof (unsigned char));
if (elts == NULL)
return CAIRO_STATUS_NO_MEMORY;
chars = (char *) (elts + num_glyphs);
elts = malloc (num_elts * sizeof (XGlyphElt8));
if (elts == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
for (i = 0; i < num_glyphs; ++i) {
chars[i] = glyphs[i].index;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = font_private->glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
/* Fill them in */
nelt = 0;
n = 0;
j = 0;
for (i = 0; i < num_glyphs; i++) {
/* Skip glyphs marked so */
if (glyphs[i].index == GLYPH_INDEX_SKIP)
continue;
/* Start a new element for first output glyph, and for glyphs with
* unexpected position */
if (!j || glyphs[i].p.i.x || glyphs[i].p.i.y) {
if (j) {
elts[nelt].nchars = n;
nelt++;
n = 0;
}
elts[nelt].chars = char8 + size * j;
elts[nelt].glyphset = font_private->glyphset;
elts[nelt].xOff = glyphs[i].p.i.x;
elts[nelt].yOff = glyphs[i].p.i.y;
}
switch (width) {
case 1: char8 [j] = (char) glyphs[i].index; break;
case 2: char16[j] = (unsigned short) glyphs[i].index; break;
default:
case 4: char32[j] = (unsigned int) glyphs[i].index; break;
}
n++;
j++;
}
XRenderCompositeText8 (dst->dpy,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
if (n) {
elts[nelt].nchars = n;
nelt++;
n = 0;
}
composite_text_func (dst->dpy,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->xrender_format,
attributes->x_offset + elts[0].xOff,
attributes->y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
(XGlyphElt8 *) elts, nelt);
if (elts != stack_elts)
free (elts);
free (elts);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs16 (cairo_xlib_surface_t *dst,
cairo_operator_t op,
cairo_xlib_surface_t *src,
int src_x_offset, int src_y_offset,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt16 *elts = NULL;
XGlyphElt16 stack_elts [N_STACK_BUF];
unsigned short *chars = NULL;
unsigned short stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
chars = stack_chars;
} else {
elts = malloc (num_glyphs * sizeof (XGlyphElt16) +
num_glyphs * sizeof (unsigned short));
if (elts == NULL)
return CAIRO_STATUS_NO_MEMORY;
chars = (unsigned short *) (elts + num_glyphs);
}
for (i = 0; i < num_glyphs; ++i) {
chars[i] = glyphs[i].index;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = font_private->glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText16 (dst->dpy,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
if (elts != stack_elts)
free (elts);
return CAIRO_STATUS_SUCCESS;
}
#undef STACK_ELTS_LEN
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_xlib_surface_t *dst,
cairo_operator_t op,
cairo_xlib_surface_t *src,
int src_x_offset, int src_y_offset,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
cairo_xlib_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_surface_attributes_t *attributes)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt32 *elts = NULL;
XGlyphElt32 stack_elts [N_STACK_BUF];
unsigned int *chars = NULL;
unsigned int stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
cairo_fixed_t x = 0, y = 0;
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
chars = stack_chars;
} else {
elts = malloc (num_glyphs * sizeof (XGlyphElt32) +
num_glyphs * sizeof (unsigned int));
if (elts == NULL)
return CAIRO_STATUS_NO_MEMORY;
unsigned long max_index = 0;
int width = 1;
int num_elts = 0;
int num_out_glyphs = 0;
chars = (unsigned int *) (elts + num_glyphs);
int max_request_size = XMaxRequestSize (dst->dpy)
- MAX (sz_xRenderCompositeGlyphs8Req,
MAX(sz_xRenderCompositeGlyphs16Req,
sz_xRenderCompositeGlyphs32Req));
int request_size = 0;
_cairo_xlib_surface_ensure_dst_picture (dst);
for (i = 0; i < num_glyphs; i++) {
int this_x, this_y;
int old_width;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE |
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status != CAIRO_STATUS_SUCCESS)
return status;
this_x = _cairo_lround (glyphs[i].p.d.x);
this_y = _cairo_lround (glyphs[i].p.d.y);
/* Glyph skipping:
*
* We skip any initial size-zero glyphs to avoid an X server bug (present
* in at least Xorg 7.1 without EXA) which stops rendering glyphs after
* the first zero-size glyph. However, we don't skip all size-zero
* glyphs, since that will force a new element at every space. We
* skip initial size-zero glyphs and hope that it's enough. Since
* Xft never exposed that bug, this assumptation should be correct.
*
* We also skip any glyph that hav troublesome coordinates. We want
* to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
* a signed 16bit integer, otherwise it will overflow in the render
* protocol.
* To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in
* a signed 15bit integer. The trivial option would be to allow
* coordinates -8192..8192, but that's kinda dull. It probably will
* take a decade or so to get monitors 8192x4096 or something. A
* negative value of -8192 on the other hand, is absolutely useless.
* Note that we do want to allow some negative positions. The glyph
* may start off the screen but part of it make it to the screen.
* Anyway, we will allow positions in the range -1024..15359. That
* will buy us a few more years before this stops working.
*/
if ((!num_out_glyphs && !(scaled_glyph->surface->width && scaled_glyph->surface->height)) ||
(((this_x+1024)|(this_y+1024))&~0x3fffu)) {
glyphs[i].index = GLYPH_INDEX_SKIP;
continue;
}
old_width = width;
/* Update max glyph index */
if (glyphs[i].index > max_index) {
max_index = glyphs[i].index;
if (max_index >= 65536)
width = 4;
else if (max_index >= 256)
width = 2;
if (width != old_width)
request_size += (width - old_width) * num_out_glyphs;
}
/* If we will pass the max request size by adding this glyph,
* flush current glyphs. Note that we account for a
* possible element being added below. */
if (request_size + width > max_request_size - sz_xGlyphElt) {
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
old_width, num_elts,
scaled_font, op, src, attributes);
if (status != CAIRO_STATUS_SUCCESS)
return status;
glyphs += i;
num_glyphs -= i;
i = 0;
max_index = glyphs[i].index;
width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
request_size = 0;
num_elts = 0;
num_out_glyphs = 0;
x = y = 0;
}
/* Convert absolute glyph position to relative-to-current-point
* position */
glyphs[i].p.i.x = this_x - x;
glyphs[i].p.i.y = this_y - y;
/* Start a new element for the first glyph, or for any glyph that
* has unexpected position */
if (!num_out_glyphs || glyphs[i].p.i.x || glyphs[i].p.i.y) {
num_elts++;
request_size += sz_xGlyphElt;
}
/* Send unsent glyphs to the server */
if (scaled_glyph->surface_private == NULL) {
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
}
/* adjust current-position */
x = this_x + scaled_glyph->x_advance;
y = this_y + scaled_glyph->y_advance;
num_out_glyphs++;
request_size += width;
}
for (i = 0; i < num_glyphs; ++i) {
chars[i] = glyphs[i].index;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = font_private->glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
if (num_elts)
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
width, num_elts,
scaled_font, op, src, attributes);
XRenderCompositeText32 (dst->dpy,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
if (elts != stack_elts)
free (elts);
return CAIRO_STATUS_SUCCESS;
return status;
}
typedef cairo_status_t (*cairo_xlib_surface_show_glyphs_func_t)
(cairo_xlib_surface_t *, cairo_operator_t, cairo_xlib_surface_t *, int, int,
const cairo_glyph_t *, int, cairo_scaled_font_t *);
#undef GLYPH_INDEX_SKIP
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
cairo_pattern_t *src_pattern,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
@ -2689,17 +2802,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xlib_surface_t *src = NULL;
cairo_glyph_t *output_glyphs;
const cairo_glyph_t *glyphs_chunk;
int glyphs_remaining, chunk_size, max_chunk_size;
cairo_scaled_glyph_t *scaled_glyph;
cairo_xlib_surface_font_private_t *font_private;
int i, o;
unsigned long max_index = 0;
cairo_xlib_surface_show_glyphs_func_t show_glyphs_func;
cairo_pattern_union_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
@ -2739,13 +2843,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
(font_private != NULL && font_private->dpy != dst->dpy))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* We make a copy of the glyphs so that we can elide any size-zero
* glyphs to workaround an X server bug, (present in at least Xorg
* 7.1 without EXA). */
output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
@ -2803,60 +2900,11 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (status)
goto BAIL;
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
for (i = 0, o = 0; i < num_glyphs; i++) {
if (glyphs[i].index > max_index)
max_index = glyphs[i].index;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status != CAIRO_STATUS_SUCCESS)
goto BAIL;
/* Don't put any size-zero glyphs into output_glyphs to avoid
* an X server bug which stops rendering glyphs after the
* first size-zero glyph. */
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
output_glyphs[o++] = glyphs[i];
if (scaled_glyph->surface_private == NULL) {
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
}
}
}
num_glyphs = o;
_cairo_xlib_surface_ensure_dst_picture (dst);
max_chunk_size = XMaxRequestSize (dst->dpy);
if (max_index < 256) {
max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
show_glyphs_func = _cairo_xlib_surface_show_glyphs8;
} else if (max_index < 65536) {
max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
show_glyphs_func = _cairo_xlib_surface_show_glyphs16;
} else {
max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
show_glyphs_func = _cairo_xlib_surface_show_glyphs32;
}
max_chunk_size /= sz_xGlyphElt;
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
glyphs_remaining;
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
{
chunk_size = MIN (glyphs_remaining, max_chunk_size);
status = show_glyphs_func (dst, op, src,
attributes.x_offset, attributes.y_offset,
glyphs_chunk, chunk_size, scaled_font);
if (status != CAIRO_STATUS_SUCCESS)
break;
}
_cairo_xlib_surface_emit_glyphs (dst, (cairo_xlib_glyph_t *) glyphs, num_glyphs,
scaled_font, op, src, &attributes);
BAIL:
_cairo_scaled_font_thaw_cache (scaled_font);
free (output_glyphs);
if (src)
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);

Просмотреть файл

@ -40,7 +40,7 @@
#include "cairo-private.h"
#include "cairo-arc-private.h"
#include "cairo-path-data-private.h"
#include "cairo-path-private.h"
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
@ -156,6 +156,7 @@ cairo_version_string (void)
{
return CAIRO_VERSION_STRING;
}
slim_hidden_def (cairo_version_string);
/**
* cairo_create:
@ -2007,18 +2008,21 @@ cairo_show_page (cairo_t *cr)
* @x: X coordinate of the point to test
* @y: Y coordinate of the point to test
*
* Tests whether the given point is on the area stroked by doing a
* cairo_stroke() operation on @cr given the current path and stroking
* parameters.
* Tests whether the given point is inside the area that would be
* affected by a cairo_stroke() operation given the current path and
* stroking parameters.
*
* See cairo_stroke, cairo_set_line_width(), cairo_set_line_join(),
* See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
* cairo_set_line_cap(), cairo_set_dash(), and
* cairo_stroke_preserve().
*
* Return value: A non-zero value if the point is inside, or zero if
* outside.
**/
cairo_bool_t
cairo_in_stroke (cairo_t *cr, double x, double y)
{
int inside;
cairo_bool_t inside;
if (cr->status)
return 0;
@ -2038,16 +2042,19 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
* @x: X coordinate of the point to test
* @y: Y coordinate of the point to test
*
* Tests whether the given point is on the area filled by doing a
* cairo_stroke() operation on @cr given the current path and filling
* parameters.
* Tests whether the given point is inside the area that would be
* affected by a cairo_fill() operation given the current path and
* filling parameters.
*
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
*
* Return value: A non-zero value if the point is inside, or zero if
* outside.
**/
cairo_bool_t
cairo_in_fill (cairo_t *cr, double x, double y)
{
int inside;
cairo_bool_t inside;
if (cr->status)
return 0;
@ -2071,10 +2078,15 @@ cairo_in_fill (cairo_t *cr, double x, double y)
* @x2: right of the resulting extents
* @y2: bottom of the resulting extents
*
* Computes a bounding box in user coordinates covering all area that will
* be stroked by the current path with the current stroking parameters. If
* the current path is empty, returns an empty rectangle. Surface dimensions
* and clipping are not taken into account.
* Computes a bounding box in user coordinates covering the area that
* would be affected by a cairo_stroke() operation operation given the
* current path and stroke parameters. If the current path is empty,
* returns an empty rectangle (0,0, 0,0). Surface dimensions and
* clipping are not taken into account.
*
* See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
* cairo_set_line_cap(), cairo_set_dash(), and
* cairo_stroke_preserve().
**/
void
cairo_stroke_extents (cairo_t *cr,
@ -2098,10 +2110,13 @@ cairo_stroke_extents (cairo_t *cr,
* @x2: right of the resulting extents
* @y2: bottom of the resulting extents
*
* Computes a bounding box in user coordinates covering all area that will
* be filled by the current path. If the current path is empty, returns an
* empty rectangle. Surface dimensions and clipping are not taken into
* account.
* Computes a bounding box in user coordinates covering the area that
* would be affected by a cairo_fill() operation given the current path
* and fill parameters. If the current path is empty, returns an empty
* rectangle (0,0, 0,0). Surface dimensions and clipping are not taken
* into account.
*
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
**/
void
cairo_fill_extents (cairo_t *cr,
@ -2218,6 +2233,8 @@ cairo_reset_clip (cairo_t *cr)
*
* Computes a bounding box in user coordinates covering the area inside the
* current clip.
*
* Since: 1.4
**/
void
cairo_clip_extents (cairo_t *cr,
@ -2233,7 +2250,7 @@ cairo_clip_extents (cairo_t *cr,
}
static cairo_rectangle_list_t *
_cairo_rectangle_list_create_for_status (cairo_status_t status)
_cairo_rectangle_list_create_in_error (cairo_status_t status)
{
cairo_rectangle_list_t *list;
@ -2259,12 +2276,14 @@ _cairo_rectangle_list_create_for_status (cairo_status_t status)
*
* The caller must always call cairo_rectangle_list_destroy on the result of
* this function.
*
* Since: 1.4
**/
cairo_rectangle_list_t *
cairo_copy_clip_rectangles (cairo_t *cr)
{
if (cr->status)
return _cairo_rectangle_list_create_for_status (cr->status);
return _cairo_rectangle_list_create_in_error (cr->status);
return _cairo_gstate_copy_clip_rectangles (cr->gstate);
}
@ -2594,7 +2613,7 @@ cairo_text_extents (cairo_t *cr,
**/
void
cairo_glyph_extents (cairo_t *cr,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
@ -2730,7 +2749,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
}
void
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
{
if (cr->status)
return;
@ -2981,8 +3000,12 @@ cairo_get_group_target (cairo_t *cr)
* conditions hold:
*
* <orderedlist>
* <listitem>If there is insufficient memory to copy the path.</listitem>
* <listitem>If @cr is already in an error state.</listitem>
* <listitem>If there is insufficient memory to copy the path. In this
* case <literal>path->status</literal> will be set to
* %CAIRO_STATUS_NO_MEMORY.</listitem>
* <listitem>If @cr is already in an error state. In this case
* <literal>path->status</literal> will contain the same status that
* would be returned by cairo_status().</listitem>
* </orderedlist>
*
* In either case, <literal>path->status</literal> will be set to
@ -2997,9 +3020,9 @@ cairo_path_t *
cairo_copy_path (cairo_t *cr)
{
if (cr->status)
return (cairo_path_t*) &_cairo_path_nil;
return _cairo_path_create_in_error (cr->status);
return _cairo_path_data_create (&cr->path, cr->gstate);
return _cairo_path_create (&cr->path, cr->gstate);
}
/**
@ -3039,9 +3062,9 @@ cairo_path_t *
cairo_copy_path_flat (cairo_t *cr)
{
if (cr->status)
return (cairo_path_t*) &_cairo_path_nil;
else
return _cairo_path_data_create_flat (&cr->path, cr->gstate);
return _cairo_path_create_in_error (cr->status);
return _cairo_path_create_flat (&cr->path, cr->gstate);
}
/**
@ -3057,8 +3080,8 @@ cairo_copy_path_flat (cairo_t *cr)
* initialized to %CAIRO_STATUS_SUCCESS.
**/
void
cairo_append_path (cairo_t *cr,
cairo_path_t *path)
cairo_append_path (cairo_t *cr,
const cairo_path_t *path)
{
if (cr->status)
return;
@ -3082,7 +3105,7 @@ cairo_append_path (cairo_t *cr,
return;
}
cr->status = _cairo_path_data_append_to_context (path, cr);
cr->status = _cairo_path_append_to_context (path, cr);
if (cr->status)
_cairo_set_error (cr, cr->status);
}
@ -3173,3 +3196,214 @@ _cairo_restrict_value (double *value, double min, double max)
else if (*value > max)
*value = max;
}
/* This function is identical to the C99 function lround(), except that it
* performs arithmetic rounding (instead of away-from-zero rounding) and
* has a valid input range of (INT_MIN, INT_MAX] instead of
* [INT_MIN, INT_MAX]. It is much faster on both x86 and FPU-less systems
* than other commonly used methods for rounding (lround, round, rint, lrint
* or float (d + 0.5)).
*
* The reason why this function is much faster on x86 than other
* methods is due to the fact that it avoids the fldcw instruction.
* This instruction incurs a large performance penalty on modern Intel
* processors due to how it prevents efficient instruction pipelining.
*
* The reason why this function is much faster on FPU-less systems is for
* an entirely different reason. All common rounding methods involve multiple
* floating-point operations. Each one of these operations has to be
* emulated in software, which adds up to be a large performance penalty.
* This function doesn't perform any floating-point calculations, and thus
* avoids this penalty.
*/
int
_cairo_lround (double d)
{
uint32_t top, shift_amount, output;
union {
double d;
uint64_t ui64;
uint32_t ui32[2];
} u;
u.d = d;
/* If the integer word order doesn't match the float word order, we swap
* the words of the input double. This is needed because we will be
* treating the whole double as a 64-bit unsigned integer. Notice that we
* use WORDS_BIGENDIAN to detect the integer word order, which isn't
* exactly correct because WORDS_BIGENDIAN refers to byte order, not word
* order. Thus, we are making the assumption that the byte order is the
* same as the integer word order which, on the modern machines that we
* care about, is OK.
*/
#if ( defined(FLOAT_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)) || \
(!defined(FLOAT_WORDS_BIGENDIAN) && defined(WORDS_BIGENDIAN))
{
uint32_t temp = u.ui32[0];
u.ui32[0] = u.ui32[1];
u.ui32[1] = temp;
}
#endif
#ifdef WORDS_BIGENDIAN
#define MSW (0) /* Most Significant Word */
#define LSW (1) /* Least Significant Word */
#else
#define MSW (1)
#define LSW (0)
#endif
/* By shifting the most significant word of the input double to the
* right 20 places, we get the very "top" of the double where the exponent
* and sign bit lie.
*/
top = u.ui32[MSW] >> 20;
/* Here, we calculate how much we have to shift the mantissa to normalize
* it to an integer value. We extract the exponent "top" by masking out the
* sign bit, then we calculate the shift amount by subtracting the exponent
* from the bias. Notice that the correct bias for 64-bit doubles is
* actually 1075, but we use 1053 instead for two reasons:
*
* 1) To perform rounding later on, we will first need the target
* value in a 31.1 fixed-point format. Thus, the bias needs to be one
* less: (1075 - 1: 1074).
*
* 2) To avoid shifting the mantissa as a full 64-bit integer (which is
* costly on certain architectures), we break the shift into two parts.
* First, the upper and lower parts of the mantissa are shifted
* individually by a constant amount that all valid inputs will require
* at the very least. This amount is chosen to be 21, because this will
* allow the two parts of the mantissa to later be combined into a
* single 32-bit representation, on which the remainder of the shift
* will be performed. Thus, we decrease the bias by an additional 21:
* (1074 - 21: 1053).
*/
shift_amount = 1053 - (top & 0x7FF);
/* We are done with the exponent portion in "top", so here we shift it off
* the end.
*/
top >>= 11;
/* Before we perform any operations on the mantissa, we need to OR in
* the implicit 1 at the top (see the IEEE-754 spec). We needn't mask
* off the sign bit nor the exponent bits because these higher bits won't
* make a bit of difference in the rest of our calculations.
*/
u.ui32[MSW] |= 0x100000;
/* If the input double is negative, we have to decrease the mantissa
* by a hair. This is an important part of performing arithmetic rounding,
* as negative numbers must round towards positive infinity in the
* halfwase case of -x.5. Since "top" contains only the sign bit at this
* point, we can just decrease the mantissa by the value of "top".
*/
u.ui64 -= top;
/* By decrementing "top", we create a bitmask with a value of either
* 0x0 (if the input was negative) or 0xFFFFFFFF (if the input was positive
* and thus the unsigned subtraction underflowed) that we'll use later.
*/
top--;
/* Here, we shift the mantissa by the constant value as described above.
* We can emulate a 64-bit shift right by 21 through shifting the top 32
* bits left 11 places and ORing in the bottom 32 bits shifted 21 places
* to the right. Both parts of the mantissa are now packed into a single
* 32-bit integer. Although we severely truncate the lower part in the
* process, we still have enough significant bits to perform the conversion
* without error (for all valid inputs).
*/
output = (u.ui32[MSW] << 11) | (u.ui32[LSW] >> 21);
/* Next, we perform the shift that converts the X.Y fixed-point number
* currently found in "output" to the desired 31.1 fixed-point format
* needed for the following rounding step. It is important to consider
* all possible values for "shift_amount" at this point:
*
* - {shift_amount < 0} Since shift_amount is an unsigned integer, it
* really can't have a value less than zero. But, if the shift_amount
* calculation above caused underflow (which would happen with
* input > INT_MAX or input <= INT_MIN) then shift_amount will now be
* a very large number, and so this shift will result in complete
* garbage. But that's OK, as the input was out of our range, so our
* output is undefined.
*
* - {shift_amount > 31} If the magnitude of the input was very small
* (i.e. |input| << 1.0), shift_amount will have a value greater than
* 31. Thus, this shift will also result in garbage. After performing
* the shift, we will zero-out "output" if this is the case.
*
* - {0 <= shift_amount < 32} In this case, the shift will properly convert
* the mantissa into a 31.1 fixed-point number.
*/
output >>= shift_amount;
/* This is where we perform rounding with the 31.1 fixed-point number.
* Since what we're after is arithmetic rounding, we simply add the single
* fractional bit into the integer part of "output", and just keep the
* integer part.
*/
output = (output >> 1) + (output & 1);
/* Here, we zero-out the result if the magnitude if the input was very small
* (as explained in the section above). Notice that all input out of the
* valid range is also caught by this condition, which means we produce 0
* for all invalid input, which is a nice side effect.
*
* The most straightforward way to do this would be:
*
* if (shift_amount > 31)
* output = 0;
*
* But we can use a little trick to avoid the potential branch. The
* expression (shift_amount > 31) will be either 1 or 0, which when
* decremented will be either 0x0 or 0xFFFFFFFF (unsigned underflow),
* which can be used to conditionally mask away all the bits in "output"
* (in the 0x0 case), effectively zeroing it out. Certain, compilers would
* have done this for us automatically.
*/
output &= ((shift_amount > 31) - 1);
/* If the input double was a negative number, then we have to negate our
* output. The most straightforward way to do this would be:
*
* if (!top)
* output = -output;
*
* as "top" at this point is either 0x0 (if the input was negative) or
* 0xFFFFFFFF (if the input was positive). But, we can use a trick to
* avoid the branch. Observe that the following snippet of code has the
* same effect as the reference snippet above:
*
* if (!top)
* output = 0 - output;
* else
* output = output - 0;
*
* Armed with the bitmask found in "top", we can condense the two statements
* into the following:
*
* output = (output & top) - (output & ~top);
*
* where, in the case that the input double was negative, "top" will be 0,
* and the statement will be equivalent to:
*
* output = (0) - (output);
*
* and if the input double was positive, "top" will be 0xFFFFFFFF, and the
* statement will be equivalent to:
*
* output = (output) - (0);
*
* Which, as pointed out earlier, is equivalent to the original reference
* snippet.
*/
output = (output & top) - (output & ~top);
return output;
#undef MSW
#undef LSW
}

Просмотреть файл

@ -169,7 +169,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
* @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
*
* #cairo_status_t is used to indicate errors that can occur when
@ -600,6 +600,8 @@ cairo_clip_extents (cairo_t *cr,
* cairo_rectangle_t:
*
* A data structure for holding a rectangle.
*
* Since: 1.4
*/
typedef struct _cairo_rectangle {
double x, y, width, height;
@ -610,6 +612,8 @@ typedef struct _cairo_rectangle {
*
* A data structure for holding a dynamically allocated
* array of rectangles.
*
* Since: 1.4
*/
typedef struct _cairo_rectangle_list {
cairo_status_t status;
@ -950,7 +954,7 @@ cairo_text_extents (cairo_t *cr,
cairo_public void
cairo_glyph_extents (cairo_t *cr,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
@ -958,7 +962,7 @@ cairo_public void
cairo_text_path (cairo_t *cr, const char *utf8);
cairo_public void
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
/* Generic identifier for a font style */
@ -1058,7 +1062,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
cairo_public void
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
@ -1233,8 +1237,8 @@ cairo_public cairo_path_t *
cairo_copy_path_flat (cairo_t *cr);
cairo_public void
cairo_append_path (cairo_t *cr,
cairo_path_t *path);
cairo_append_path (cairo_t *cr,
const cairo_path_t *path);
cairo_public void
cairo_path_destroy (cairo_path_t *path);
@ -1672,9 +1676,9 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
cairo_public void
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height,
cairo_bool_t *is_tight);
double *x1, double *y1,
double *x2, double *y2,
cairo_bool_t *is_tight);
/* Functions to be used while debugging (not intended for use in production code) */
cairo_public void

Просмотреть файл

@ -67,6 +67,7 @@
#ifdef _MSC_VER
#define snprintf _snprintf
#undef inline
#define inline __inline
#endif
@ -89,8 +90,8 @@ CAIRO_BEGIN_DECLS
# define slim_hidden_asmname(name) slim_hidden_asmname1(name)
# define slim_hidden_asmname1(name) slim_hidden_ulp #name
#else
# define slim_hidden_proto(name)
# define slim_hidden_def(name)
# define slim_hidden_proto(name) int _cairo_dummy_prototype(void)
# define slim_hidden_def(name) int _cairo_dummy_prototype(void)
#endif
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
@ -133,12 +134,6 @@ CAIRO_BEGIN_DECLS
#define __attribute__(x)
#endif
#if defined(__GNUC__)
#define INLINE __inline__
#else
#define INLINE
#endif
#if 0
#if HAVE_PTHREAD_H
# include <pthread.h>
@ -149,11 +144,15 @@ CAIRO_BEGIN_DECLS
#endif
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features. Although we don't use them here, things
* should still work if this header file ends up being the one to include
* windows.h into a source file, so: */
# if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
# endif
# ifndef WINVER
# define WINVER 0xFFFFF /* use newest and greatest */
# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
# endif
# include <windows.h>
/* the real initialization must take place in DllMain */
@ -210,6 +209,13 @@ cairo_private void _cairo_beos_unlock(void*);
#define M_PI 3.14159265358979323846
#endif
/* Size in bytes of buffer to use off the stack per functions.
* Mostly used by text functions. For larger allocations, they'll
* malloc(). */
#ifndef CAIRO_STACK_BUFFER_SIZE
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
#endif
#define ASSERT_NOT_REACHED \
do { \
static const int NOT_REACHED = 0; \
@ -506,6 +512,8 @@ typedef struct _cairo_scaled_glyph {
cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
cairo_text_extents_t metrics; /* user-space metrics */
cairo_box_t bbox; /* device-space bounds */
int16_t x_advance; /* device-space rounded X advance */
int16_t y_advance; /* device-space rounded Y advance */
cairo_image_surface_t *surface; /* device-space image */
cairo_path_fixed_t *path; /* device-space outline */
void *surface_private; /* for the surface backend */
@ -634,7 +642,7 @@ struct _cairo_scaled_font_backend {
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs);
cairo_int_status_t
@ -727,9 +735,23 @@ struct _cairo_surface_backend {
cairo_rectangle_int16_t *image_rect,
void *image_extra);
/* Create a new surface (@clone_out) with the following
* characteristics:
*
* 1. It is as compatible as possible with @surface (in terms of
* efficiency)
*
* 2. It has the same size as @src
*
* 3. It has the same contents as @src within the given rectangle.
*/
cairo_status_t
(*clone_similar) (void *surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out);
/* XXX: dst should be the first argument for consistency */
@ -843,7 +865,7 @@ struct _cairo_surface_backend {
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs);
void
@ -905,7 +927,7 @@ struct _cairo_surface_backend {
(*show_glyphs) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
@ -1086,6 +1108,8 @@ typedef struct _cairo_surface_attributes {
} cairo_surface_attributes_t;
typedef struct _cairo_traps {
cairo_status_t status;
cairo_trapezoid_t *traps;
int num_traps;
int traps_size;
@ -1141,6 +1165,9 @@ typedef struct _cairo_stroke_face {
cairo_private void
_cairo_restrict_value (double *value, double min, double max);
cairo_private int
_cairo_lround (double d);
/* cairo_fixed.c */
cairo_private cairo_fixed_t
_cairo_fixed_from_int (int i);
@ -1411,7 +1438,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *font,
cairo_private cairo_status_t
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
@ -1421,10 +1448,10 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
int num_glyphs);
cairo_private cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path);
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path);
cairo_private cairo_bool_t
_cairo_operator_bounded_by_mask (cairo_operator_t op);
@ -1667,12 +1694,6 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_glyph_t **glyphs,
int *num_glyphs);
cairo_private cairo_status_t
_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_private cairo_status_t
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
@ -1690,7 +1711,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
@ -1841,7 +1862,7 @@ cairo_private cairo_status_t
_cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
@ -1892,6 +1913,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out);
cairo_private cairo_surface_t *
@ -1936,7 +1961,7 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
@ -2160,12 +2185,6 @@ _cairo_matrix_get_affine (const cairo_matrix_t *matrix,
double *xy, double *yy,
double *x0, double *y0);
cairo_private void
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height,
cairo_bool_t *is_tight);
cairo_private void
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
@ -2176,6 +2195,9 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
cairo_private cairo_bool_t
_cairo_matrix_is_identity (const cairo_matrix_t *matrix);
cairo_private cairo_bool_t
_cairo_matrix_is_translation (const cairo_matrix_t *matrix);
cairo_private cairo_bool_t
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
int *itx, int *ity);
@ -2205,13 +2227,23 @@ cairo_private cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
cairo_private cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4]);
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
cairo_private cairo_status_t
_cairo_traps_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *poly,
cairo_fill_rule_t fill_rule);
cairo_private cairo_status_t
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2);
cairo_private cairo_status_t
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule);
cairo_private int
_cairo_traps_contain (cairo_traps_t *traps, double x, double y);
@ -2401,6 +2433,7 @@ slim_hidden_proto (cairo_pattern_get_extend);
slim_hidden_proto (cairo_pattern_get_type);
slim_hidden_proto (cairo_pattern_reference);
slim_hidden_proto (cairo_pattern_set_matrix);
slim_hidden_proto (cairo_pattern_status);
slim_hidden_proto (cairo_pop_group);
slim_hidden_proto (cairo_pop_group_to_source);
slim_hidden_proto (cairo_push_group);
@ -2435,6 +2468,7 @@ slim_hidden_proto (cairo_surface_set_device_offset);
slim_hidden_proto (cairo_surface_set_fallback_resolution);
slim_hidden_proto (cairo_surface_status);
slim_hidden_proto (cairo_surface_write_to_png_stream);
slim_hidden_proto (cairo_version_string);
CAIRO_END_DECLS

Просмотреть файл

@ -247,7 +247,7 @@ static cairo_int_status_t
_test_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -228,7 +228,7 @@ static cairo_int_status_t
_test_paginated_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{

Просмотреть файл

@ -2732,78 +2732,231 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CA
#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
static CARD32
xRenderColorMultToCard32 (pixman_color_t *c)
typedef struct
{
return
((((uint32_t) c->red * c->alpha) >> 24) << 16) |
((((uint32_t) c->green * c->alpha) >> 24) << 8) |
((((uint32_t) c->blue * c->alpha) >> 24) << 0) |
((((uint32_t) c->alpha ) >> 8) << 24);
CARD32 left_ag;
CARD32 left_rb;
CARD32 right_ag;
CARD32 right_rb;
int32_t left_x;
int32_t right_x;
int32_t width_x;
int32_t stepper;
pixman_gradient_stop_t *stops;
int num_stops;
unsigned int spread;
} GradientWalker;
static void
_gradient_walker_init (GradientWalker *walker,
SourcePictPtr pGradient,
unsigned int spread)
{
walker->num_stops = pGradient->gradient.nstops;
walker->stops = pGradient->gradient.stops;
walker->left_x = 0;
walker->right_x = 0x10000;
walker->width_x = 0; /* will force a reset */
walker->stepper = 0;
walker->left_ag = 0;
walker->left_rb = 0;
walker->right_ag = 0;
walker->right_rb = 0;
walker->spread = spread;
}
static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
static void
_gradient_walker_reset (GradientWalker *walker,
xFixed_32_32 pos)
{
int ipos = (pos * pGradient->gradient.stopRange - 1) >> 16;
int32_t x, left_x, right_x;
pixman_color_t *left_c, *right_c;
int n, count = walker->num_stops;
pixman_gradient_stop_t *stops = walker->stops;
/* calculate the actual offset. */
if (ipos < 0 || ipos >= pGradient->gradient.stopRange)
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
switch (walker->spread)
{
if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal)
{
ipos = ipos % pGradient->gradient.stopRange;
ipos = ipos < 0 ? pGradient->gradient.stopRange + ipos : ipos;
case RepeatNormal:
x = (int32_t)pos & 0xFFFF;
for (n = 0; n < count; n++)
if (x < stops[n].x)
break;
if (n == 0) {
left_x = stops[count-1].x - 0x10000;
left_c = &stops[count-1].color;
} else {
left_x = stops[n-1].x;
left_c = &stops[n-1].color;
}
else if (spread == RepeatReflect)
{
const int limit = pGradient->gradient.stopRange * 2 - 1;
ipos = ipos % limit;
ipos = ipos < 0 ? limit + ipos : ipos;
ipos = ipos >= pGradient->gradient.stopRange ? limit - ipos : ipos;
if (n == count) {
right_x = stops[0].x + 0x10000;
right_c = &stops[0].color;
} else {
right_x = stops[n].x;
right_c = &stops[n].color;
}
left_x += (pos - x);
right_x += (pos - x);
break;
case RepeatPad:
for (n = 0; n < count; n++)
if (pos < stops[n].x)
break;
if (n == 0) {
left_x = INT_MIN;
left_c = &stops[0].color;
} else {
left_x = stops[n-1].x;
left_c = &stops[n-1].color;
}
else if (spread == RepeatPad)
{
if (ipos < 0)
ipos = 0;
else
ipos = pGradient->gradient.stopRange - 1;
if (n == count) {
right_x = INT_MAX;
right_c = &stops[n-1].color;
} else {
right_x = stops[n].x;
right_c = &stops[n].color;
}
else /* RepeatNone */
break;
case RepeatReflect:
x = (int32_t)pos & 0xFFFF;
if ((int32_t)pos & 0x10000)
x = 0x10000 - x;
for (n = 0; n < count; n++)
if (x < stops[n].x)
break;
if (n == 0) {
left_x = -stops[0].x;
left_c = &stops[0].color;
} else {
left_x = stops[n-1].x;
left_c = &stops[n-1].color;
}
if (n == count) {
right_x = 0x20000 - stops[n-1].x;
right_c = &stops[n-1].color;
} else {
right_x = stops[n].x;
right_c = &stops[n].color;
}
if ((int32_t)pos & 0x10000) {
pixman_color_t *tmp_c;
int32_t tmp_x;
tmp_x = 0x20000 - right_x;
right_x = 0x20000 - left_x;
left_x = tmp_x;
tmp_c = right_c;
right_c = left_c;
left_c = tmp_c;
}
left_x += (pos - x);
right_x += (pos - x);
break;
default: /* RepeatNone */
for (n = 0; n < count; n++)
if (pos < stops[n].x)
break;
if (n == 0)
{
return 0;
left_x = INT_MIN;
right_x = stops[0].x;
left_c = right_c = (pixman_color_t*) &transparent_black;
}
else if (n == count)
{
left_x = stops[n-1].x;
right_x = INT_MAX;
left_c = right_c = (pixman_color_t*) &transparent_black;
}
else
{
left_x = stops[n-1].x;
right_x = stops[n].x;
left_c = &stops[n-1].color;
right_c = &stops[n].color;
}
}
if (pGradient->gradient.colorTableSize)
walker->left_x = left_x;
walker->right_x = right_x;
walker->width_x = right_x - left_x;
walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8);
walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8);
walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8);
walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
if ( walker->width_x == 0 ||
( walker->left_ag == walker->right_ag &&
walker->left_rb == walker->right_rb ) )
{
return pGradient->gradient.colorTable[ipos];
walker->width_x = 1;
walker->stepper = 0;
}
else
{
int i;
if (ipos <= pGradient->gradient.stops->x)
return xRenderColorMultToCard32 (&pGradient->gradient.stops->color);
for (i = 1; i < pGradient->gradient.nstops; i++)
{
if (pGradient->gradient.stops[i].x >= ipos)
return PictureGradientColor (&pGradient->gradient.stops[i - 1],
&pGradient->gradient.stops[i],
ipos);
}
return xRenderColorMultToCard32 (&pGradient->gradient.stops[--i].color);
walker->stepper = ((1 << 24) + walker->width_x/2)/walker->width_x;
}
}
#define GRADIENT_WALKER_NEED_RESET(w,x) \
( (x) < (w)->left_x || (x) - (w)->left_x >= (w)->width_x )
/* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
static CARD32
_gradient_walker_pixel (GradientWalker *walker,
xFixed_32_32 x)
{
int dist, idist;
uint32_t t1, t2, a, color;
if (GRADIENT_WALKER_NEED_RESET (walker, x))
_gradient_walker_reset (walker, x);
dist = ((int)(x - walker->left_x)*walker->stepper) >> 16;
idist = 256 - dist;
/* combined INTERPOLATE and premultiply */
t1 = walker->left_rb*idist + walker->right_rb*dist;
t1 = (t1 >> 8) & 0xff00ff;
t2 = walker->left_ag*idist + walker->right_ag*dist;
t2 &= 0xff00ff00;
color = t2 & 0xff000000;
a = t2 >> 24;
t1 = t1*a + 0x800080;
t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
t2 = (t2 >> 8)*a + 0x800080;
t2 = (t2 + ((t2 >> 8) & 0xff00ff));
return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
}
static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
SourcePictPtr pGradient = pict->pSourcePict;
CARD32 *end = buffer + width;
SourcePictPtr pGradient = pict->pSourcePict;
GradientWalker walker;
CARD32 *end = buffer + width;
_gradient_walker_init (&walker, pGradient, pict->repeat);
if (pGradient->type == SourcePictTypeSolidFill) {
register CARD32 color = pGradient->solidFill.color;
@ -2854,20 +3007,29 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
{
register CARD32 color;
color = gradientPixel (pGradient, t, pict->repeat);
color = _gradient_walker_pixel( &walker, t );
while (buffer < end)
*buffer++ = color;
}
else
{
while (buffer < end) {
if (!mask || *mask++ & maskBits)
{
*buffer = gradientPixel (pGradient, t, pict->repeat);
}
++buffer;
t += inc;
}
if (!mask) {
while (buffer < end)
{
*buffer = _gradient_walker_pixel (&walker, t);
buffer += 1;
t += inc;
}
} else {
while (buffer < end) {
if (*mask++ & maskBits)
{
*buffer = _gradient_walker_pixel (&walker, t);
}
buffer += 1;
t += inc;
}
}
}
}
else /* projective transformation */
@ -2891,31 +3053,31 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
t = ((a * x + b * y) >> 16) + off;
}
color = gradientPixel (pGradient, t, pict->repeat);
color = _gradient_walker_pixel( &walker, t );
while (buffer < end)
*buffer++ = color;
}
else
{
while (buffer < end)
{
if (!mask || *mask++ & maskBits)
{
if (v.vector[2] == 0) {
t = 0;
} else {
xFixed_48_16 x, y;
x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
t = ((a*x + b*y) >> 16) + off;
}
*buffer = gradientPixel(pGradient, t, pict->repeat);
}
++buffer;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
while (buffer < end)
{
if (!mask || *mask++ & maskBits)
{
if (v.vector[2] == 0) {
t = 0;
} else {
xFixed_48_16 x, y;
x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
t = ((a*x + b*y) >> 16) + off;
}
*buffer = _gradient_walker_pixel (&walker, t);
}
++buffer;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
}
}
} else {
@ -2952,19 +3114,22 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
ry -= pGradient->radial.fy;
while (buffer < end) {
double b, c, det, s;
double b, c, det, s;
if (!mask || *mask++ & maskBits)
{
b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
c = -(rx*rx + ry*ry);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
*buffer = gradientPixel(pGradient,
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
pict->repeat);
}
++buffer;
if (!mask || *mask++ & maskBits)
{
xFixed_48_16 t;
b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
c = -(rx*rx + ry*ry);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536);
*buffer = _gradient_walker_pixel (&walker, t);
}
++buffer;
rx += cx;
ry += cy;
}
@ -2973,25 +3138,27 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
double x, y;
double b, c, det, s;
if (!mask || *mask++ & maskBits)
{
if (rz != 0) {
x = rx/rz;
y = ry/rz;
} else {
x = y = 0.;
}
x -= pGradient->radial.fx;
y -= pGradient->radial.fy;
b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy);
c = -(x*x + y*y);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
*buffer = gradientPixel(pGradient,
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
pict->repeat);
}
++buffer;
if (!mask || *mask++ & maskBits)
{
xFixed_48_16 t;
if (rz != 0) {
x = rx/rz;
y = ry/rz;
} else {
x = y = 0.;
}
x -= pGradient->radial.fx;
y -= pGradient->radial.fy;
b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy);
c = -(x*x + y*y);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536);
*buffer = _gradient_walker_pixel (&walker, t);
}
++buffer;
rx += cx;
ry += cy;
rz += cz;
@ -3006,37 +3173,41 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
while (buffer < end) {
double angle;
if (!mask || *mask++ & maskBits)
{
angle = atan2(ry, rx) + a;
if (!mask || *mask++ & maskBits)
{
xFixed_48_16 t;
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeat);
}
angle = atan2(ry, rx) + a;
t = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
*buffer = _gradient_walker_pixel (&walker, t);
}
++buffer;
rx += cx;
ry += cy;
}
} else {
while (buffer < end) {
double x, y;
double angle;
double angle;
if (!mask || *mask++ & maskBits)
{
if (rz != 0) {
x = rx/rz;
y = ry/rz;
} else {
x = y = 0.;
}
x -= pGradient->conical.center.x/65536.;
y -= pGradient->conical.center.y/65536.;
angle = atan2(y, x) + a;
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeat);
}
if (!mask || *mask++ & maskBits)
{
xFixed_48_16 t;
if (rz != 0) {
x = rx/rz;
y = ry/rz;
} else {
x = y = 0.;
}
x -= pGradient->conical.center.x/65536.;
y -= pGradient->conical.center.y/65536.;
angle = atan2(y, x) + a;
t = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
*buffer = _gradient_walker_pixel (&walker, t);
}
++buffer;
rx += cx;
ry += cy;

Просмотреть файл

@ -602,18 +602,18 @@ nsThebesRenderingContext::DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoo
}
/* Clamp r to (0,0) (32766,32766);
/* Clamp r to (0,0) (16384,16384);
* these are to be device coordinates.
*
* Returns PR_FALSE if the rectangle is completely out of bounds, PR_TRUE otherwise.
*/
#define CAIRO_COORD_MAX (16384.0)
static PRBool
ConditionRect(gfxRect& r) {
const double COORD_MAX = 32766.0;
// if either x or y is way out of bounds;
// note that we don't handle negative w/h here
if (r.pos.x > COORD_MAX || r.pos.y > COORD_MAX)
if (r.pos.x > CAIRO_COORD_MAX || r.pos.y > CAIRO_COORD_MAX)
return PR_FALSE;
if (r.pos.x < 0.0) {
@ -621,8 +621,8 @@ ConditionRect(gfxRect& r) {
r.pos.x = 0.0;
}
if (r.pos.x + r.size.width > COORD_MAX) {
r.size.width = COORD_MAX - r.pos.x;
if (r.pos.x + r.size.width > CAIRO_COORD_MAX) {
r.size.width = CAIRO_COORD_MAX - r.pos.x;
}
if (r.pos.y < 0.0) {
@ -630,8 +630,8 @@ ConditionRect(gfxRect& r) {
r.pos.y = 0.0;
}
if (r.pos.y + r.size.height > COORD_MAX) {
r.size.height = COORD_MAX - r.pos.y;
if (r.pos.y + r.size.height > CAIRO_COORD_MAX) {
r.size.height = CAIRO_COORD_MAX - r.pos.y;
}
return PR_TRUE;
}
@ -644,7 +644,7 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
gfxRect r(GFX_RECT_FROM_TWIPS_RECT(aRect));
/* Clamp coordinates to work around a design bug in cairo */
nscoord bigval = (nscoord)(32766*mP2T);
nscoord bigval = (nscoord)(CAIRO_COORD_MAX*mP2T);
if (aRect.width > bigval ||
aRect.height > bigval ||
aRect.x < -bigval ||
@ -661,6 +661,9 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
mThebes->IdentityMatrix();
mThebes->NewPath();
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::FillRect conditioned to [%f,%f,%f,%f]\n", this, r.pos.x, r.pos.y, r.size.width, r.size.height));
mThebes->Rectangle(r, PR_TRUE);
mThebes->Fill();
mThebes->SetMatrix(mat);
@ -668,6 +671,8 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
return NS_OK;
}
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::FillRect raw [%f,%f,%f,%f]\n", this, r.pos.x, r.pos.y, r.size.width, r.size.height));
mThebes->NewPath();
mThebes->Rectangle(r, PR_TRUE);
mThebes->Fill();

Просмотреть файл

@ -245,14 +245,14 @@ public:
}
gfxRect TransformBounds(const gfxRect& rect) const {
double x = rect.pos.x;
double y = rect.pos.y;
double width = rect.size.width;
double height = rect.size.height;
double x0 = rect.pos.x;
double y0 = rect.pos.y;
double x1 = rect.pos.x + rect.size.width;
double y1 = rect.pos.y + rect.size.height;
cairo_matrix_transform_bounding_box (&mat, &x, &y, &width, &height, NULL);
cairo_matrix_transform_bounding_box (&mat, &x0, &y0, &x1, &y1, NULL);
return gfxRect(x, y, width, height);
return gfxRect(x0, y0, x1 - x0, y1 - y0);
}
/**