From d0e02a948e83e3b1b330c9cb0aa4930b42bf485c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 09:18:17 -0800 Subject: [PATCH 001/155] autogen.sh: Pass --foreign option to automake so that it doesn't complain that ChangeLog does not exist. --- autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index 88ad4f74b..57bf60111 100755 --- a/autogen.sh +++ b/autogen.sh @@ -7,7 +7,7 @@ PACKAGE=cairo LIBTOOLIZE=${LIBTOOLIZE-libtoolize} LIBTOOLIZE_FLAGS="--copy --force" AUTOHEADER=${AUTOHEADER-autoheader} -AUTOMAKE_FLAGS="--add-missing" +AUTOMAKE_FLAGS="--add-missing --foreign" AUTOCONF=${AUTOCONF-autoconf} # automake 1.8 requires autoconf 2.58 From 9287d60d60f55ae3838a7cecfa9fa04a5f95e8de Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 11:24:03 -0800 Subject: [PATCH 002/155] Add get_type functions: cairo_surface_get_type, cairo_pattern_get_type, cairo_font_face_get_type, and cairo_scaled_font_get_type. --- src/cairo-surface.c | 3 +- src/cairo.h | 134 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 29820173e..52aeafe46 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -186,7 +186,8 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, * * Create a new surface that is as compatible as possible with an * existing surface. The new surface will use the same backend as - * @other unless that is not possible for some reason. + * @other unless that is not possible for some reason. The type of the + * returned surface may be examined with cairo_surface_get_type(). * * Return value: a pointer to the newly allocated surface. The caller * owns the surface and should call cairo_surface_destroy when done diff --git a/src/cairo.h b/src/cairo.h index fbb362088..76f9257e3 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -896,6 +896,46 @@ cairo_font_face_destroy (cairo_font_face_t *font_face); cairo_public cairo_status_t cairo_font_face_status (cairo_font_face_t *font_face); +/** + * cairo_font_type_t + * @CAIRO_SCALED_FONT_TYPE_FT: The font is of type ft + * @CAIRO_SCALED_FONT_TYPE_WIN32: The font is of type win32 + * @CAIRO_SCALED_FONT_TYPE_ATSUI: The font is of type atsui + * + * @cairo_font_type_t is used to describe the type of a given font + * face or scaled font. The font types are also known as "font + * backends" within cairo. + * + * The type of a font face is determined by the function used to + * create it, which will generally be of the form + * cairo__font_face_create. The font face type can be queried + * with cairo_font_face_get_type() + * + * The various cairo_font_face functions can be used with a font face + * of any type. + * + * The type of a scaled font is determined by the type of the font + * face passed to cairo_scaled_font_create. The scaled font type can + * be queried with cairo_scaled_font_get_type() + * + * The various cairo_scaled_font functions can be used with scaled + * fonts of any type, but some font backends also provide + * type-specific functions that must only be called with a scaled font + * of the appropriate type. These functions have names that begin with + * cairo__scaled_font such as cairo_ft_scaled_font_lock_face. + * + * The behavior of calling a type-specific function with a scaled font + * of the wrong type is undefined. + */ +typedef enum _cairo_font_type { + CAIRO_FONT_TYPE_FT, + CAIRO_FONT_TYPE_WIN32, + CAIRO_FONT_TYPE_ATSUI +} cairo_font_type_t; + +cairo_public cairo_font_type_t +cairo_font_face_get_type (cairo_scaled_font_t *font_face); + cairo_public void * cairo_font_face_get_user_data (cairo_font_face_t *font_face, const cairo_user_data_key_t *key); @@ -923,6 +963,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font); cairo_public cairo_status_t cairo_scaled_font_status (cairo_scaled_font_t *scaled_font); +cairo_public cairo_font_type_t +cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font); + cairo_public void cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *extents); @@ -1147,14 +1190,64 @@ cairo_surface_create_similar (cairo_surface_t *other, cairo_public cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface); +cairo_public void +cairo_surface_finish (cairo_surface_t *surface); + cairo_public void cairo_surface_destroy (cairo_surface_t *surface); cairo_public cairo_status_t cairo_surface_status (cairo_surface_t *surface); -cairo_public void -cairo_surface_finish (cairo_surface_t *surface); +/** + * cairo_surface_type_t + * @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image + * @CAIRO_SURFACE_TYPE_PDF: The surface is of type pdf + * @CAIRO_SURFACE_TYPE_PS: The surface is of type ps + * @CAIRO_SURFACE_TYPE_XLIB: The surface is of typs xlib + * @CAIRO_SURFACE_TYPE_XCB: The surface is of type xcb + * @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz + * @CAIRO_SURFACE_TYPE_QUARTZ: The surface is of type quartz + * @CAIRO_SURFACE_TYPE_WIN32: The surface is of type win32 + * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos + * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb + * @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg + * + * @cairo_surface_type_t is used to describe the type of a given + * surface. The surface types are also known as "backends" or "surface + * backends" within cairo. + * + * The type of a surface is determined by the function used to create + * it, which will generally be of the form cairo__surface_create, + * (though see cairo_surface_create_similar as well). + * + * The surface type can be queried with cairo_surface_get_type() + * + * The various cairo_surface functions can be used with surfaces of + * any type, but some backends also provide type-specific functions + * that must only be called with a surface of the appropriate + * type. These functions have names that begin with + * cairo__surface such as cairo_image_surface_get_width(). + * + * The behavior of calling a type-specific function with a surface of + * the wrong type is undefined. + */ +typedef enum _cairo_surface_type { + CAIRO_SURFACE_TYPE_IMAGE, + CAIRO_SURFACE_TYPE_PDF, + CAIRO_SURFACE_TYPE_PS, + CAIRO_SURFACE_TYPE_XLIB, + CAIRO_SURFACE_TYPE_XCB, + CAIRO_SURFACE_TYPE_GLITZ, + CAIRO_SURFACE_TYPE_QUARTZ, + CAIRO_SURFACE_TYPE_WIN32, + CAIRO_SURFACE_TYPE_BEOS, + CAIRO_SURFACE_TYPE_DIRECTFB, + CAIRO_SURFACE_TYPE_SVG +} cairo_surface_type_t; + +cairo_public cairo_surface_type_t +cairo_surface_get_type (cairo_surface_t *surface); #if CAIRO_HAS_PNG_FUNCTIONS @@ -1290,6 +1383,43 @@ cairo_pattern_destroy (cairo_pattern_t *pattern); cairo_public cairo_status_t cairo_pattern_status (cairo_pattern_t *pattern); +/** + * cairo_pattern_type_t + + * @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform) + * color. It may be opaque or translucent. + * @CAIRO_PATTERN_TYPE_SURFACE: The pattern is a based on a surface (an image). + * @CAIRO_PATTERN_TYPE_LINEAR_GRADIENT: The pattern is a linear gradient. + * @CAIRO_PATTERN_TYPE_RADIAL_GRADIENT: The pattern is a radial gradient. + * + * @cairo_pattern_type_t us used to describe the type of a given pattern. + * + * The type of a pattern is determined by the function used to create + * it. The cairo_pattern_create_rgb() and cairo_pattern_create_rgba() + * functions create SOLID patterns. The reamaining + * cairo_pattern_create functions map to pattern types in obvious + * ways. + * + * The pattern type can be queried with cairo_pattern_get_type() + * + * Most cairo_pattern functions can be called with a pattern of any + * type, (though trying to change the extend or filter for a solid + * pattern will have no effect). A notable exception is + * cairo_pattern_add_color_stop_rgb() and + * cairo_pattern_add_color_stop_rgba() which must only be called with + * gradient patterns. Otherwise the pattern will be shutdown and put + * into an error state. + */ +typedef enum _cairo_pattern_type { + CAIRO_PATTERN_TYPE_SOLID, + CAIRO_PATTERN_TYPE_SURFACE, + CAIRO_PATTERN_TYPE_LINEAR_GRADIENT, + CAIRO_PATTERN_TYPE_RADIAL_GRADIENT +} cairo_pattern_type_t; + +cairo_public cairo_pattern_type_t +cairo_pattern_get_type (cairo_pattern_t *pattern); + cairo_public void cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, double offset, From 2fc9fd79e794129b26cc8f9b62a5aa4604cb99d9 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 11:37:50 -0800 Subject: [PATCH 003/155] cairo.h: Fix two typos in the documentation. --- src/cairo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cairo.h b/src/cairo.h index 76f9257e3..0dd361643 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1204,7 +1204,7 @@ cairo_surface_status (cairo_surface_t *surface); * @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image * @CAIRO_SURFACE_TYPE_PDF: The surface is of type pdf * @CAIRO_SURFACE_TYPE_PS: The surface is of type ps - * @CAIRO_SURFACE_TYPE_XLIB: The surface is of typs xlib + * @CAIRO_SURFACE_TYPE_XLIB: The surface is of type xlib * @CAIRO_SURFACE_TYPE_XCB: The surface is of type xcb * @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz * @CAIRO_SURFACE_TYPE_QUARTZ: The surface is of type quartz @@ -1396,7 +1396,7 @@ cairo_pattern_status (cairo_pattern_t *pattern); * * The type of a pattern is determined by the function used to create * it. The cairo_pattern_create_rgb() and cairo_pattern_create_rgba() - * functions create SOLID patterns. The reamaining + * functions create SOLID patterns. The remaining * cairo_pattern_create functions map to pattern types in obvious * ways. * From f58f39d7afee8d8a663569f149651c789aa95da8 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 15:06:50 -0800 Subject: [PATCH 004/155] cairo.h: Fix typo (thanks to Torsten Schoenfeld) --- src/cairo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo.h b/src/cairo.h index 0dd361643..cc87b7e2b 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -934,7 +934,7 @@ typedef enum _cairo_font_type { } cairo_font_type_t; cairo_public cairo_font_type_t -cairo_font_face_get_type (cairo_scaled_font_t *font_face); +cairo_font_face_get_type (cairo_font_face_t *font_face); cairo_public void * cairo_font_face_get_user_data (cairo_font_face_t *font_face, From 5928d03b496420b2d0a89cf8e2d294081a60cc67 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 15:25:19 -0800 Subject: [PATCH 005/155] Remove private cairo_pattern_type in favor of new public one. Rename all values to now include TYPE. Drop _GRADIENT from LINEAR and RADIAL. --- src/cairo-meta-surface.c | 2 +- src/cairo-pattern.c | 68 ++++++++++++++++++------------------ src/cairo-pdf-surface.c | 10 +++--- src/cairo-ps-surface.c | 26 +++++++------- src/cairo-surface-fallback.c | 2 +- src/cairo-xlib-surface.c | 2 +- src/cairo.h | 12 +++---- src/cairoint.h | 7 ---- 8 files changed, 61 insertions(+), 68 deletions(-) diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index a314150bc..6f824634c 100644 --- a/src/cairo-meta-surface.c +++ b/src/cairo-meta-surface.c @@ -201,7 +201,7 @@ _init_pattern_with_snapshot (cairo_pattern_t *pattern, { _cairo_pattern_init_copy (pattern, other); - if (pattern->type == CAIRO_PATTERN_SURFACE) { + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; cairo_surface_t *surface = surface_pattern->surface; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index d7b73693b..27ede9a64 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -30,7 +30,7 @@ #include "cairoint.h" const cairo_solid_pattern_t cairo_pattern_nil = { - { CAIRO_PATTERN_SOLID, /* type */ + { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ @@ -39,7 +39,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = { }; static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { - { CAIRO_PATTERN_SOLID, /* type */ + { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_NULL_POINTER,/* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ @@ -48,7 +48,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { }; static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { - { CAIRO_PATTERN_SOLID, /* type */ + { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_FILE_NOT_FOUND, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ @@ -57,7 +57,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { }; static const cairo_solid_pattern_t cairo_pattern_nil_read_error = { - { CAIRO_PATTERN_SOLID, /* type */ + { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_READ_ERROR, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ @@ -117,7 +117,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) pattern->ref_count = 1; pattern->status = CAIRO_STATUS_SUCCESS; - if (type == CAIRO_PATTERN_SURFACE) + if (type == CAIRO_PATTERN_TYPE_SURFACE) pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT; else pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT; @@ -131,7 +131,7 @@ static void _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, const cairo_gradient_pattern_t *other) { - if (other->base.type == CAIRO_PATTERN_LINEAR) + if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern; cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other; @@ -170,21 +170,21 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, } switch (other->type) { - case CAIRO_PATTERN_SOLID: { + case CAIRO_PATTERN_TYPE_SOLID: { cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern; cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other; *dst = *src; } break; - case CAIRO_PATTERN_SURFACE: { + case CAIRO_PATTERN_TYPE_SURFACE: { cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern; cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other; *dst = *src; cairo_surface_reference (dst->surface); } break; - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: { + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern; cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other; @@ -199,16 +199,16 @@ void _cairo_pattern_fini (cairo_pattern_t *pattern) { switch (pattern->type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: break; - case CAIRO_PATTERN_SURFACE: { + case CAIRO_PATTERN_TYPE_SURFACE: { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; cairo_surface_destroy (surface_pattern->surface); } break; - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: { + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; @@ -222,7 +222,7 @@ void _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, const cairo_color_t *color) { - _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SOLID); + _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID); pattern->color = *color; } @@ -232,12 +232,12 @@ _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, { if (surface->status) { /* Force to solid to simplify the pattern_fini process. */ - pattern->base.type = CAIRO_PATTERN_SOLID; + pattern->base.type = CAIRO_PATTERN_TYPE_SOLID; _cairo_pattern_set_error (&pattern->base, surface->status); return; } - _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE); + _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE); pattern->surface = cairo_surface_reference (surface); } @@ -256,7 +256,7 @@ void _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern, double x0, double y0, double x1, double y1) { - _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_LINEAR); + _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR); pattern->gradient.p1.x = _cairo_fixed_from_double (x0); pattern->gradient.p1.y = _cairo_fixed_from_double (y0); @@ -269,7 +269,7 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, double cx0, double cy0, double radius0, double cx1, double cy1, double radius1) { - _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_RADIAL); + _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL); pattern->gradient.inner.x = _cairo_fixed_from_double (cx0); pattern->gradient.inner.y = _cairo_fixed_from_double (cy0); @@ -641,8 +641,8 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, if (pattern->status) return; - if (pattern->type != CAIRO_PATTERN_LINEAR && - pattern->type != CAIRO_PATTERN_RADIAL) + if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && + pattern->type != CAIRO_PATTERN_TYPE_RADIAL) { _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH); return; @@ -689,8 +689,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, if (pattern->status) return; - if (pattern->type != CAIRO_PATTERN_LINEAR && - pattern->type != CAIRO_PATTERN_RADIAL) + if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && + pattern->type != CAIRO_PATTERN_TYPE_RADIAL) { _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH); return; @@ -894,7 +894,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, cairo_status_t status; cairo_bool_t repeat = FALSE; - if (pattern->base.type == CAIRO_PATTERN_LINEAR) + if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; @@ -936,7 +936,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } - if (pattern->base.type == CAIRO_PATTERN_LINEAR) { + if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_bool_t is_horizontal; cairo_bool_t is_vertical; @@ -1055,7 +1055,7 @@ _cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern) { cairo_solid_pattern_t *solid; - if (pattern->type != CAIRO_PATTERN_SOLID) + if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) return FALSE; solid = (cairo_solid_pattern_t *) pattern; @@ -1151,7 +1151,7 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, } switch (pattern->type) { - case CAIRO_PATTERN_SOLID: { + case CAIRO_PATTERN_TYPE_SOLID: { cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern; status = _cairo_pattern_acquire_surface_for_solid (src, dst, @@ -1159,8 +1159,8 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, surface_out, attributes); } break; - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: { + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern; /* fast path for gradients with less than 2 color stops */ @@ -1203,7 +1203,7 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, attributes); } } break; - case CAIRO_PATTERN_SURFACE: { + case CAIRO_PATTERN_TYPE_SURFACE: { cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern; status = _cairo_pattern_acquire_surface_for_surface (src, dst, @@ -1235,7 +1235,7 @@ _cairo_pattern_release_surface (cairo_pattern_t *pattern, { cairo_surface_pattern_t *surface_pattern; - assert (pattern->type == CAIRO_PATTERN_SURFACE); + assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); surface_pattern = (cairo_surface_pattern_t *) pattern; _cairo_surface_release_source_image (surface_pattern->surface, @@ -1277,8 +1277,8 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src, /* XXX: This optimization assumes that there is no color * information in mask, so this will need to change when we * support RENDER-style 4-channel masks. */ - if (src->type == CAIRO_PATTERN_SOLID && - mask && mask->type == CAIRO_PATTERN_SOLID) + if (src->type == CAIRO_PATTERN_TYPE_SOLID && + mask && mask->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_color_t combined; cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; @@ -1346,7 +1346,7 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern, cairo_rectangle_t *extents) { if (pattern->extend == CAIRO_EXTEND_NONE && - pattern->type == CAIRO_PATTERN_SURFACE) + pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_status_t status; cairo_rectangle_t surface_extents; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index ee5c482cf..289eeb961 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -841,7 +841,7 @@ _cairo_pdf_surface_composite (cairo_operator_t op, if (mask_pattern) return CAIRO_STATUS_SUCCESS; - if (src_pattern->type != CAIRO_PATTERN_SURFACE) + if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE) return CAIRO_STATUS_SUCCESS; if (src->surface->backend == &cairo_pdf_surface_backend) @@ -1237,16 +1237,16 @@ static cairo_status_t emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern) { switch (pattern->type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); - case CAIRO_PATTERN_SURFACE: + case CAIRO_PATTERN_TYPE_SURFACE: return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); - case CAIRO_PATTERN_LINEAR: + case CAIRO_PATTERN_TYPE_LINEAR: return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); - case CAIRO_PATTERN_RADIAL: + case CAIRO_PATTERN_TYPE_RADIAL: return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 6cf862170..371290cc2 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -546,12 +546,12 @@ pattern_is_translucent (const cairo_pattern_t *abstract_pattern) pattern = (cairo_pattern_union_t *) abstract_pattern; switch (pattern->base.type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: return color_is_translucent (&pattern->solid.color); - case CAIRO_PATTERN_SURFACE: + case CAIRO_PATTERN_TYPE_SURFACE: return surface_is_translucent (pattern->surface.surface); - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: return gradient_is_translucent (&pattern->gradient.base); } @@ -637,7 +637,7 @@ color_operation_needs_fallback (cairo_operator_t op, static cairo_bool_t pattern_type_supported (const cairo_pattern_t *pattern) { - if (pattern->type == CAIRO_PATTERN_SOLID) + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) return TRUE; return FALSE; } @@ -837,19 +837,19 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) * different pattern. */ switch (pattern->type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); break; - case CAIRO_PATTERN_SURFACE: + case CAIRO_PATTERN_TYPE_SURFACE: emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); break; - case CAIRO_PATTERN_LINEAR: + case CAIRO_PATTERN_TYPE_LINEAR: emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); break; - case CAIRO_PATTERN_RADIAL: + case CAIRO_PATTERN_TYPE_RADIAL: emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); break; } @@ -890,12 +890,12 @@ _cairo_ps_surface_composite (cairo_operator_t op, status = CAIRO_STATUS_SUCCESS; switch (src_pattern->type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_composite: solid\n"); goto bail; - case CAIRO_PATTERN_SURFACE: + case CAIRO_PATTERN_TYPE_SURFACE: surface_pattern = (cairo_surface_pattern_t *) src_pattern; if (src_pattern->extend != CAIRO_EXTEND_NONE) { @@ -920,8 +920,8 @@ _cairo_ps_surface_composite (cairo_operator_t op, image, image_extra); break; - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_composite: gradient\n"); goto bail; diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 8f18ca33b..9dde31f23 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -576,7 +576,7 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src, { cairo_surface_t *clip_surface = clip ? clip->surface : NULL; - if ((src->type == CAIRO_PATTERN_SOLID || op == CAIRO_OPERATOR_CLEAR) && + if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) && !clip_surface) { const cairo_color_t *color; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 38c7c76b6..1ce7e890b 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1047,7 +1047,7 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst, if (!dst->buggy_repeat) return DO_RENDER; - if (src_pattern->type == CAIRO_PATTERN_SURFACE) + if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern; diff --git a/src/cairo.h b/src/cairo.h index cc87b7e2b..f6187210b 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1389,8 +1389,8 @@ cairo_pattern_status (cairo_pattern_t *pattern); * @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform) * color. It may be opaque or translucent. * @CAIRO_PATTERN_TYPE_SURFACE: The pattern is a based on a surface (an image). - * @CAIRO_PATTERN_TYPE_LINEAR_GRADIENT: The pattern is a linear gradient. - * @CAIRO_PATTERN_TYPE_RADIAL_GRADIENT: The pattern is a radial gradient. + * @CAIRO_PATTERN_TYPE_LINEAR: The pattern is a linear gradient. + * @CAIRO_PATTERN_TYPE_RADIAL: The pattern is a radial gradient. * * @cairo_pattern_type_t us used to describe the type of a given pattern. * @@ -1407,14 +1407,14 @@ cairo_pattern_status (cairo_pattern_t *pattern); * pattern will have no effect). A notable exception is * cairo_pattern_add_color_stop_rgb() and * cairo_pattern_add_color_stop_rgba() which must only be called with - * gradient patterns. Otherwise the pattern will be shutdown and put - * into an error state. + * gradient patterns (either LINEAR or RADIAL). Otherwise the pattern + * will be shutdown and put into an error state. */ typedef enum _cairo_pattern_type { CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE, - CAIRO_PATTERN_TYPE_LINEAR_GRADIENT, - CAIRO_PATTERN_TYPE_RADIAL_GRADIENT + CAIRO_PATTERN_TYPE_LINEAR, + CAIRO_PATTERN_TYPE_RADIAL } cairo_pattern_type_t; cairo_public cairo_pattern_type_t diff --git a/src/cairoint.h b/src/cairoint.h index 88fccae11..ebf2b31d0 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -909,13 +909,6 @@ typedef enum { #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST -typedef enum { - CAIRO_PATTERN_SOLID, - CAIRO_PATTERN_SURFACE, - CAIRO_PATTERN_LINEAR, - CAIRO_PATTERN_RADIAL -} cairo_pattern_type_t; - struct _cairo_pattern { cairo_pattern_type_t type; unsigned int ref_count; From 5a3c30eafe0b77f69434e139a2e247c8eb4230d7 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Feb 2006 15:32:26 -0800 Subject: [PATCH 006/155] Implement cairo_font_face_get_type. Add font type to font_face_backend. Also export new CAIRO_FONT_TYPE_TOY. --- src/cairo-atsui-font.c | 1 + src/cairo-font.c | 7 +++++++ src/cairo-ft-font.c | 1 + src/cairo-win32-font.c | 1 + src/cairo.h | 1 + src/cairoint.h | 3 +++ 6 files changed, 14 insertions(+) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 9f3b54da1..572359f8d 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -94,6 +94,7 @@ _cairo_atsui_font_face_scaled_font_create (void *abstract_face, } static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = { + CAIRO_FONT_TYPE_ATSUI, _cairo_atsui_font_face_destroy, _cairo_atsui_font_face_scaled_font_create }; diff --git a/src/cairo-font.c b/src/cairo-font.c index b0fab1b4a..bb184c48d 100644 --- a/src/cairo-font.c +++ b/src/cairo-font.c @@ -130,6 +130,12 @@ cairo_font_face_destroy (cairo_font_face_t *font_face) free (font_face); } +cairo_font_type_t +cairo_font_face_get_type (cairo_font_face_t *font_face) +{ + return font_face->backend->type; +} + /** * cairo_font_face_status: * @font_face: a #cairo_font_face_t @@ -409,6 +415,7 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face } static const cairo_font_face_backend_t _cairo_toy_font_face_backend = { + CAIRO_FONT_TYPE_TOY, _cairo_toy_font_face_destroy, _cairo_toy_font_face_scaled_font_create }; diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 45997444d..e159826a0 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2004,6 +2004,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face, } static const cairo_font_face_backend_t _cairo_ft_font_face_backend = { + CAIRO_FONT_TYPE_FT, _cairo_ft_font_face_destroy, _cairo_ft_font_face_scaled_font_create }; diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 3343abfd4..ca8e4a610 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1398,6 +1398,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face, } static const cairo_font_face_backend_t _cairo_win32_font_face_backend = { + CAIRO_FONT_TYPE_WIN32, _cairo_win32_font_face_destroy, _cairo_win32_font_face_scaled_font_create }; diff --git a/src/cairo.h b/src/cairo.h index f6187210b..5b38d18e4 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -928,6 +928,7 @@ cairo_font_face_status (cairo_font_face_t *font_face); * of the wrong type is undefined. */ typedef enum _cairo_font_type { + CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32, CAIRO_FONT_TYPE_ATSUI diff --git a/src/cairoint.h b/src/cairoint.h index ebf2b31d0..401114cb7 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -464,6 +464,7 @@ struct _cairo_scaled_font { }; struct _cairo_font_face { + /* hash_entry must be first */ cairo_hash_entry_t hash_entry; cairo_status_t status; int ref_count; @@ -555,6 +556,8 @@ struct _cairo_scaled_font_backend { }; struct _cairo_font_face_backend { + cairo_font_type_t type; + /* The destroy() function is allowed to resurrect the font face * by re-referencing. This is needed for the FreeType backend. */ From dba214b944a16dd7ee781f495cd5fbe83f678451 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Sun, 26 Feb 2006 10:46:04 +0100 Subject: [PATCH 007/155] Use C-style comments rather than C++-style --- pixman/src/fbcompose.c | 4 ++-- pixman/src/pixman-xserver-compat.h | 2 +- src/cairo-atsui-font.c | 23 ++++++++++++----------- src/cairo-directfb-surface.c | 2 +- src/cairo-quartz-surface.c | 11 ++++++----- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c index 2289cee09..c14986c4c 100644 --- a/pixman/src/fbcompose.c +++ b/pixman/src/fbcompose.c @@ -35,8 +35,8 @@ #include -// #define PIXMAN_CONVOLUTION -// #define PIXMAN_INDEXED_FORMATS +/* #define PIXMAN_CONVOLUTION */ +/* #define PIXMAN_INDEXED_FORMATS */ static Bool PictureTransformPoint3d (pixman_transform_t *transform, diff --git a/pixman/src/pixman-xserver-compat.h b/pixman/src/pixman-xserver-compat.h index 46e2825f9..5113abd54 100644 --- a/pixman/src/pixman-xserver-compat.h +++ b/pixman/src/pixman-xserver-compat.h @@ -72,8 +72,8 @@ typedef pixman_triangle_t xTriangle; #define FB_SHIFT IC_SHIFT #define FB_MASK IC_MASK #define FB_ALLONES IC_ALLONES +#define FbMaskBits IcMaskBits */ -//#define FbMaskBits IcMaskBits /* XXX: We changed some function and field names which makes for some * ugly hacks... */ diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 9f3b54da1..12cd329f7 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -132,7 +132,7 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale) ATSUStyle style; OSStatus err; - // Set the style's size + /* Set the style's size */ CGAffineTransform theTransform = CGAffineTransformMakeWithCairoFontScale(scale); Fixed theSize = @@ -174,7 +174,7 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font) extents.height = metrics.capHeight; extents.max_x_advance = metrics.maxAdvanceWidth; - // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. + /* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */ extents.max_y_advance = 0.0; _cairo_scaled_font_set_metrics (&font->base, &extents); @@ -275,7 +275,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, kFontNoLanguageCode, &fontID); if (err != noErr) { - // couldn't get the font - remap css names and try again + /* couldn't get the font - remap css names and try again */ if (!strcmp(family, "serif")) family = "Times"; @@ -287,7 +287,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, family = "Gadget"; else if (!strcmp(family, "monospace")) family = "Courier"; - else // anything else - return error instead? + else /* anything else - return error instead? */ family = "Courier"; err = ATSUFindFontFromName(family, strlen(family), @@ -504,7 +504,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font, err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16); - // Set the style for all of the text + /* Set the style for all of the text */ err = ATSUSetRunStyle(textLayout, font->style, kATSUFromTextBeginning, kATSUToTextEnd); @@ -565,7 +565,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, &rect, &extra); - // Create a CGBitmapContext for the dest surface for drawing into + /* Create a CGBitmapContext for the dest surface for drawing into */ colorSpace = CGColorSpaceCreateDeviceRGB(); myBitmapContext = CGBitmapContextCreate(destImageSurface->data, @@ -633,11 +633,12 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, /* XXX: Need to get the text clipped */ } - // TODO - bold and italic text - // - // We could draw the text using ATSUI and get bold, italics - // etc. for free, but ATSUI does a lot of text layout work - // that we don't really need... + /* TODO - bold and italic text + * + * We could draw the text using ATSUI and get bold, italics + * etc. for free, but ATSUI does a lot of text layout work + * that we don't really need... + */ for (i = 0; i < num_glyphs; i++) { diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c index be1791584..45db4dd54 100644 --- a/src/cairo-directfb-surface.c +++ b/src/cairo-directfb-surface.c @@ -150,7 +150,7 @@ static inline int cairo_to_directfb_format(cairo_format_t format ) { return DSPF_A1; default: { - //assert(0); + /*assert(0);*/ return DSPF_UNKNOWN; } } diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index d7defc98e..c65ca46d7 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -73,10 +73,11 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface, UInt32 imageDataSize, rowBytes; CGDataProviderRef dataProvider; - // We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t - // struct. If the window is ever drawn to without going through Cairo, then - // we would need to refetch the pixel data from the window into the cached - // image surface. + /* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t + * struct. If the window is ever drawn to without going through Cairo, then + * we would need to refetch the pixel data from the window into the cached + * image surface. + */ if (surface->image) { cairo_surface_reference(&surface->image->base); @@ -257,7 +258,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, surface->clip_region = NULL; surface->flipped = flipped; - // Set up the image surface which Cairo draws into and we blit to & from. + /* Set up the image surface which Cairo draws into and we blit to & from. */ void *foo; _cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo); From f6b4fabaf59227d6cafcdd7e27cf0d8e26b4eeb8 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 14 Feb 2006 11:55:00 -0800 Subject: [PATCH 008/155] Misc compilation fixes (C++-style comments, M_PI decls, etc.) (cherry picked from d0cc56b9a24fa59febc15ac5de073da0e785e1cc commit) (cherry picked from a6a054abe45287eb950c294e20366594313138f5 commit) --- pixman/src/fbcompose.c | 8 ++++++++ pixman/src/pixregion.c | 6 +++--- src/cairo-atsui-font.c | 10 ++++++++++ src/cairoint.h | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c index c14986c4c..e316c6db6 100644 --- a/pixman/src/fbcompose.c +++ b/pixman/src/fbcompose.c @@ -33,8 +33,16 @@ #include "pixregionint.h" +#ifdef _MSC_VER +#define _USE_MATH_DEFINES +#endif + #include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + /* #define PIXMAN_CONVOLUTION */ /* #define PIXMAN_INDEXED_FORMATS */ diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c index 9c122f534..e5660969e 100644 --- a/pixman/src/pixregion.c +++ b/pixman/src/pixregion.c @@ -60,7 +60,7 @@ SOFTWARE. #endif #undef assert -#ifdef DEBUG +#ifdef DEBUG_PIXREGION #define assert(expr) {if (!(expr)) \ FatalError("Assertion failed file %s, line %d: expr\n", \ __FILE__, __LINE__); } @@ -208,7 +208,7 @@ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ } -#ifdef DEBUG +#ifdef DEBUG_PIXREGION int pixman_region16_print(rgn) pixman_region16_t * rgn; @@ -302,7 +302,7 @@ pixman_region16_valid(reg) } } -#endif /* DEBUG */ +#endif /* DEBUG_PIXREGION */ /* Create a new empty region */ diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 12cd329f7..74a4fca07 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -40,6 +40,16 @@ #include "cairo.h" #include "cairo-quartz-private.h" +/* + * FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions + * here so we can use older SDKs. + */ +#ifndef FixedToFloat +#define fixed1 ((Fixed) 0x00010000L) +#define FixedToFloat(a) ((float)(a) / fixed1) +#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1)) +#endif + typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t; typedef struct _cairo_atsui_font cairo_atsui_font_t; diff --git a/src/cairoint.h b/src/cairoint.h index 88fccae11..2581bc6d8 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -184,6 +184,10 @@ cairo_private void _cairo_beos_unlock(void*); #define TRUE 1 #endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + #define ASSERT_NOT_REACHED \ do { \ static const int NOT_REACHED = 0; \ From e0f4eecb91c8f7f09ef4977703d4ca21b06797a9 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 15 Feb 2006 12:43:01 -0800 Subject: [PATCH 009/155] Win32: Rework clip and extents handling - Save extents at surface creation and always return these - Simplify clipping paths (cherry picked from a67722b3d7280e6c2375778c2d46556cca261bfc commit) (cherry picked from 7ce09732a978749a4da814feb77f50161dc42c91 commit) --- src/cairo-win32-private.h | 2 +- src/cairo-win32-surface.c | 92 +++++++++++++++------------------------ 2 files changed, 36 insertions(+), 58 deletions(-) diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h index a229147c7..b3143c96f 100644 --- a/src/cairo-win32-private.h +++ b/src/cairo-win32-private.h @@ -62,9 +62,9 @@ typedef struct _cairo_win32_surface { cairo_rectangle_t clip_rect; - int set_clip; HRGN saved_clip; + cairo_rectangle_t extents; } cairo_win32_surface_t; cairo_status_t diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index b1811a134..9c46efea9 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -274,9 +274,14 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, surface->clip_rect.width = width; surface->clip_rect.height = height; - surface->set_clip = 0; - surface->saved_clip = NULL; - + surface->saved_clip = CreateRectRgn (0, 0, 0, 0); + if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { + DeleteObject(surface->saved_clip); + surface->saved_clip = NULL; + } + + surface->extents = surface->clip_rect; + _cairo_surface_init (&surface->base, &cairo_win32_surface_backend); return (cairo_surface_t *)surface; @@ -340,9 +345,8 @@ _cairo_win32_surface_finish (void *abstract_surface) if (surface->image) cairo_surface_destroy (surface->image); - if (surface->saved_clip) { + if (surface->saved_clip) DeleteObject (surface->saved_clip); - } /* If we created the Bitmap and DC, destroy them */ if (surface->bitmap) { @@ -403,7 +407,7 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur cairo_win32_surface_t *surface = abstract_surface; cairo_win32_surface_t *local = NULL; cairo_status_t status; - + if (surface->image) { *image_out = (cairo_image_surface_t *)surface->image; *image_extra = NULL; @@ -446,7 +450,7 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa cairo_status_t status; RECT clip_box; int x1, y1, x2, y2; - + if (surface->image) { image_rect->x = 0; image_rect->y = 0; @@ -461,12 +465,12 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa if (GetClipBox (surface->dc, &clip_box) == ERROR) return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image"); - + x1 = clip_box.left; x2 = clip_box.right; y1 = clip_box.top; y2 = clip_box.bottom; - + if (interest_rect->x > x1) x1 = interest_rect->x; if (interest_rect->y > y1) @@ -855,19 +859,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, if (region == NULL) { /* Clear any clip set by cairo, return to the original */ - - if (surface->set_clip) { - if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region"); + if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR) + return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)"); - if (surface->saved_clip) { - DeleteObject (surface->saved_clip); - surface->saved_clip = NULL; - } - - surface->set_clip = 0; - } - return CAIRO_STATUS_SUCCESS; } else { @@ -910,36 +904,16 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, if (!gdi_region) return CAIRO_STATUS_NO_MEMORY; - if (surface->set_clip) { - /* Combine the new region with the original clip */ + /* Combine the new region with the original clip */ - if (surface->saved_clip) { - if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR) - goto FAIL; - } - - if (SelectClipRgn (surface->dc, gdi_region) == ERROR) + if (surface->saved_clip) { + if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR) goto FAIL; - - } else { - /* Save the the current region */ - - surface->saved_clip = CreateRectRgn (0, 0, 0, 0); - if (!surface->saved_clip) { - goto FAIL; } - - /* This function has no error return! */ - if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { /* No clip */ - DeleteObject (surface->saved_clip); - surface->saved_clip = NULL; - } - - if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR) - goto FAIL; - - surface->set_clip = 1; } + if (SelectClipRgn (surface->dc, gdi_region) == ERROR) + goto FAIL; + DeleteObject (gdi_region); return CAIRO_STATUS_SUCCESS; @@ -955,15 +929,8 @@ _cairo_win32_surface_get_extents (void *abstract_surface, cairo_rectangle_t *rectangle) { cairo_win32_surface_t *surface = abstract_surface; - RECT clip_box; - if (GetClipBox (surface->dc, &clip_box) == ERROR) - return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image"); - - rectangle->x = clip_box.left; - rectangle->y = clip_box.top; - rectangle->width = clip_box.right - clip_box.left; - rectangle->height = clip_box.bottom - clip_box.top; + *rectangle = surface->extents; return CAIRO_STATUS_SUCCESS; } @@ -1007,8 +974,19 @@ cairo_win32_surface_create (HDC hdc) surface->clip_rect.width = rect.right - rect.left; surface->clip_rect.height = rect.bottom - rect.top; - surface->set_clip = 0; - surface->saved_clip = NULL; + if (surface->clip_rect.width == 0 || + surface->clip_rect.height == 0) + { + surface->saved_clip = NULL; + } else { + surface->saved_clip = CreateRectRgn (0, 0, 0, 0); + if (GetClipRgn (hdc, surface->saved_clip) == 0) { + DeleteObject(surface->saved_clip); + surface->saved_clip = NULL; + } + } + + surface->extents = surface->clip_rect; _cairo_surface_init (&surface->base, &cairo_win32_surface_backend); From f4b34df6b6c07024a1b552236d8e0db959771b15 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 15 Feb 2006 13:14:52 -0800 Subject: [PATCH 010/155] Have mark_dirty always invalidate the last clip set on the surface mark_dirty will force cairo to set its own clip the next time the cairo clip is applied after mark_dirty; otherwise we run the risk of cairo's cached clip and the device clip getting out of sync if any clip-related functions are used on the native device back-end. (cherry picked from 1935a28949da8569f924e37714ec19571fa95987 commit) (cherry picked from ef8b472f0ffab7b8b828d7297c7e454bb22bd5ec commit) --- src/cairo-surface.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 29820173e..93095fcbf 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -502,6 +502,10 @@ cairo_surface_mark_dirty (cairo_surface_t *surface) * Like cairo_surface_mark_dirty(), but drawing has been done only to * the specified rectangle, so that cairo can retain cached contents * for other parts of the surface. + * + * Any cached clip set on the surface will be reset by this function, + * to make sure that future cairo calls have the clip set that they + * expect. */ void cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, @@ -520,6 +524,13 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, return; } + /* Always reset the clip here, to avoid having external calls to + * clip manipulation functions of the underlying device clip result + * in a desync between the cairo clip and the backend clip, due to + * the clip caching. + */ + surface->current_clip_serial = -1; + if (surface->backend->mark_dirty_rectangle) { cairo_status_t status; @@ -1329,6 +1340,12 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip) if (!surface) return CAIRO_STATUS_NULL_POINTER; + if (surface->status) + return surface->status; + + if (surface->finished) + return CAIRO_STATUS_SURFACE_FINISHED; + if (clip) { serial = clip->serial; if (serial == 0) @@ -1336,7 +1353,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip) } surface->clip = clip; - + if (serial == _cairo_surface_get_current_clip_serial (surface)) return CAIRO_STATUS_SUCCESS; From 0fe8a93d95ab0b2235133fa089be8ec99d1a5248 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 17 Feb 2006 23:17:23 -0800 Subject: [PATCH 011/155] Win32: expose win32 DIB (image) surface creation function, and DC getter Adds cairo_win32_surface_create_dib() for creating a win32 DIB-backed surface with a particular format. Also exposes cairo_win32_surface_get_dc() to obtain the DC of a win32 surface. (cherry picked from 0813a1b9b6f35d786fe8cb0d4748771023956cde commit) --- src/cairo-win32-font.c | 2 +- src/cairo-win32-private.h | 5 ----- src/cairo-win32-surface.c | 31 ++++++++++++++++++++++++++++--- src/cairo-win32.h | 8 ++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 3343abfd4..1c9d3bf6d 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, cairo_surface_pattern_t mask; RECT r; - tmp_surface = (cairo_win32_surface_t *)_cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height); + tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height); if (tmp_surface->base.status) return CAIRO_STATUS_NO_MEMORY; diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h index b3143c96f..fd6642413 100644 --- a/src/cairo-win32-private.h +++ b/src/cairo-win32-private.h @@ -70,11 +70,6 @@ typedef struct _cairo_win32_surface { cairo_status_t _cairo_win32_print_gdi_error (const char *context); -cairo_surface_t * -_cairo_win32_surface_create_dib (cairo_format_t format, - int width, - int height); - cairo_bool_t _cairo_surface_is_win32 (cairo_surface_t *surface); diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 9c46efea9..888dadd83 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -330,9 +330,9 @@ _cairo_win32_surface_create_similar (void *abstract_src, * be created (probably because of lack of memory) **/ cairo_surface_t * -_cairo_win32_surface_create_dib (cairo_format_t format, - int width, - int height) +cairo_win32_surface_create_dib (cairo_format_t format, + int width, + int height) { return _cairo_win32_surface_create_for_dc (NULL, format, width, height); } @@ -1007,6 +1007,31 @@ _cairo_surface_is_win32 (cairo_surface_t *surface) return surface->backend == &cairo_win32_surface_backend; } +/** + * cairo_win32_surface_get_dc + * @surface: a #cairo_surface_t + * + * Returns the HDC associated with this surface, or NULL if none. + * Also returns NULL if the surface is not a win32 surface. + * + * Return value: HDC or NULL if no HDC available. + **/ +HDC +cairo_win32_surface_get_dc (cairo_surface_t *surface) +{ + cairo_win32_surface_t *winsurf; + + if (surface == NULL) + return NULL; + + if (!_cairo_surface_is_win32(surface)) + return NULL; + + winsurf = (cairo_win32_surface_t *) surface; + + return winsurf->dc; +} + static const cairo_surface_backend_t cairo_win32_surface_backend = { _cairo_win32_surface_create_similar, _cairo_win32_surface_finish, diff --git a/src/cairo-win32.h b/src/cairo-win32.h index 8d43bb74f..a631820a4 100644 --- a/src/cairo-win32.h +++ b/src/cairo-win32.h @@ -47,6 +47,14 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * cairo_win32_surface_create (HDC hdc); +cairo_public cairo_surface_t * +cairo_win32_surface_create_dib (cairo_format_t format, + int width, + int height); + +cairo_public HDC +cairo_win32_surface_get_dc (cairo_surface_t *surface); + cairo_public cairo_font_face_t * cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont); From 0852cd449259eb9a52bfa63f19428c47c78baf91 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 27 Feb 2006 12:49:27 +0100 Subject: [PATCH 012/155] Win32: rename cairo_surface_create_dib to cairo_surface_create_with_dib Also adds some documentation for the win32 creation functions. (cherry picked from 3a148bd620d709237d98a72f65118759bfc5a76d commit) --- src/cairo-win32-font.c | 2 +- src/cairo-win32-surface.c | 55 ++++++++++++++++++++++++--------------- src/cairo-win32.h | 6 ++--- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 1c9d3bf6d..841459f20 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, cairo_surface_pattern_t mask; RECT r; - tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height); + tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height); if (tmp_surface->base.status) return CAIRO_STATUS_NO_MEMORY; diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 888dadd83..eb0456d2a 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -316,27 +316,6 @@ _cairo_win32_surface_create_similar (void *abstract_src, return _cairo_win32_surface_create_for_dc (src->dc, format, width, height); } -/** - * _cairo_win32_surface_create_dib: - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a device-independent-bitmap surface not associated with - * any particular existing surface or device context. The created - * bitmap will be unititialized. - * - * Return value: the newly created surface, or %NULL if it couldn't - * be created (probably because of lack of memory) - **/ -cairo_surface_t * -cairo_win32_surface_create_dib (cairo_format_t format, - int width, - int height) -{ - return _cairo_win32_surface_create_for_dc (NULL, format, width, height); -} - static cairo_status_t _cairo_win32_surface_finish (void *abstract_surface) { @@ -941,6 +920,18 @@ _cairo_win32_surface_flush (void *abstract_surface) return _cairo_surface_reset_clip (abstract_surface); } +/** + * cairo_win32_surface_create: + * @hdc: the DC to create a surface for + * + * Creates a cairo surface that targets the given DC. The DC will be + * queried for its initial clip extents, and this will be used as the + * size of the cairo surface. Also, if the DC is a raster DC, it will + * be queried for its pixel format and the cairo surface format will + * be set appropriately. + * + * Return value: the newly created surface + **/ cairo_surface_t * cairo_win32_surface_create (HDC hdc) { @@ -993,6 +984,28 @@ cairo_win32_surface_create (HDC hdc) return (cairo_surface_t *)surface; } +/** + * cairo_win32_surface_create_with_dib: + * @format: format of pixels in the surface to create + * @width: width of the surface, in pixels + * @height: height of the surface, in pixels + * + * Creates a device-independent-bitmap surface not associated with + * any particular existing surface or device context. The created + * bitmap will be unititialized. + * + * Return value: the newly created surface + * + **/ +cairo_surface_t * +cairo_win32_surface_create_with_dib (cairo_format_t format, + int width, + int height) +{ + return _cairo_win32_surface_create_for_dc (NULL, format, width, height); +} + + /** * _cairo_surface_is_win32: * @surface: a #cairo_surface_t diff --git a/src/cairo-win32.h b/src/cairo-win32.h index a631820a4..6ba37dec1 100644 --- a/src/cairo-win32.h +++ b/src/cairo-win32.h @@ -48,9 +48,9 @@ cairo_public cairo_surface_t * cairo_win32_surface_create (HDC hdc); cairo_public cairo_surface_t * -cairo_win32_surface_create_dib (cairo_format_t format, - int width, - int height); +cairo_win32_surface_create_with_dib (cairo_format_t format, + int width, + int height); cairo_public HDC cairo_win32_surface_get_dc (cairo_surface_t *surface); From 68ed40b6da242816a43cd68cc2c7feb779cf0acf Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 17 Feb 2006 23:24:06 -0800 Subject: [PATCH 013/155] Win32: Fix up src coords before calling AlphaBlend/BitBlt to avoid invalid calls Fixes up src coords and width/height before calling AlphaBlend/BitBlt; it's an error to try to use a region that extents outside of the source surface as a source DC. Doesn't repair the extra region relative to the operator -- e.g. regions outside of an ARGB source surface with SOURCE operator should be cleared to fully transparent black in the destination. (cherry picked from bc19c5b64b0e38e9d20045907d7b47d79f6afc60 commit) --- src/cairo-win32-surface.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index eb0456d2a..57f5aa508 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -643,6 +643,33 @@ _cairo_win32_surface_composite (cairo_operator_t op, if (!integer_transform) return CAIRO_INT_STATUS_UNSUPPORTED; + /* Fix up src coordinates; the src coords and size must be within the + * bounds of the source surface. + * XXX the region not covered should be appropriately rendered! + * - for OVER/SOURCE with RGB24 source -> opaque black + * - for SOURCE with ARGB32 source -> 100% transparent black + */ + src_x += itx; + src_y += ity; + + if (src_x < 0) { + width += src_x; + dst_x -= src_x; + src_x = 0; + } + + if (src_y < 0) { + height += src_y; + dst_y -= src_y; + src_y = 0; + } + + if (src_x + width > src->extents.width) + width = src->extents.width - src_x; + + if (src_y + height > src->extents.height) + height = src->extents.height - src_y; + if (alpha == 255 && src->format == dst->format && (op == CAIRO_OPERATOR_SOURCE || @@ -652,7 +679,7 @@ _cairo_win32_surface_composite (cairo_operator_t op, dst_x, dst_y, width, height, src->dc, - src_x + itx, src_y + ity, + src_x, src_y, SRCCOPY)) return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite"); @@ -664,7 +691,7 @@ _cairo_win32_surface_composite (cairo_operator_t op, op == CAIRO_OPERATOR_OVER) { return _composite_alpha_blend (dst, src, alpha, - src_x + itx, src_y + ity, + src_x, src_y, dst_x, dst_y, width, height); } From 2d784815ffac1ca8c10dac12525f2e8d0b412c1a Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 17 Feb 2006 23:34:51 -0800 Subject: [PATCH 014/155] Win32: Set surface format based on device caps If the DC is a display DC, inspect its depth and set out local format appropriately. If it's not a display DC, assume RGB24. (cherry picked from 6dd0a70d271f93df95f4bcaff5073b9bf90cecb6 commit) --- src/cairo-win32-surface.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 57f5aa508..d27185d19 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -31,6 +31,8 @@ * * Contributor(s): * Owen Taylor + * Stuart Parmenter + * Vladimir Vukicevic */ #include @@ -964,6 +966,8 @@ cairo_win32_surface_create (HDC hdc) { cairo_win32_surface_t *surface; RECT rect; + int depth; + cairo_format_t format; /* Try to figure out the drawing bounds for the Device context */ @@ -973,7 +977,26 @@ cairo_win32_surface_create (HDC hdc) _cairo_error (CAIRO_STATUS_NO_MEMORY); return &_cairo_surface_nil; } - + + if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) { + depth = GetDeviceCaps(hdc, BITSPIXEL); + if (depth == 32) + format = CAIRO_FORMAT_ARGB32; + else if (depth == 24) + format = CAIRO_FORMAT_RGB24; + else if (depth == 8) + format = CAIRO_FORMAT_A8; + else if (depth == 1) + format = CAIRO_FORMAT_A1; + else { + _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)"); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return &_cairo_surface_nil; + } + } else { + format = CAIRO_FORMAT_RGB24; + } + surface = malloc (sizeof (cairo_win32_surface_t)); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -981,7 +1004,7 @@ cairo_win32_surface_create (HDC hdc) } surface->image = NULL; - surface->format = CAIRO_FORMAT_RGB24; + surface->format = format; surface->dc = hdc; surface->bitmap = NULL; From 1a1441912604c89e2912ec764fe26b7a9db995a3 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 17 Feb 2006 23:37:54 -0800 Subject: [PATCH 015/155] Win32: Handle BitBlt in get_image failure and AlphaBlend not being supported If the BitBlt in get_image fails, we pretty much can't do anything -- so fill the destination with white and hope for the best. This enables somewhat accurate printing of complex operations. Also, check the destination device caps before calling AlphaBlend; return UNSUPPORTED if the destination DC can't do AlphaBlend. (cherry picked from 9831de538e347a624af5b0ca38242b198b64bd45 commit) --- src/cairo-win32-surface.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index d27185d19..c7f45556e 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -364,8 +364,18 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, width, height, surface->dc, x, y, - SRCCOPY)) - goto FAIL; + SRCCOPY)) { + /* If we fail to BitBlt here, most likely the source is a printer. + * You can't reliably get bits from a printer DC, so just fill in + * the surface as white (common case for printing). + */ + + RECT r; + r.left = r.top = 0; + r.right = width; + r.bottom = height; + FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH)); + } *local_out = local; @@ -580,6 +590,8 @@ _composite_alpha_blend (cairo_win32_surface_t *dst, if (alpha_blend == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; + if (GetDeviceCaps(dst->dc, SHADEBLENDCAPS) == SB_NONE) + return CAIRO_INT_STATUS_UNSUPPORTED; blend_function.BlendOp = AC_SRC_OVER; blend_function.BlendFlags = 0; @@ -913,7 +925,7 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, return CAIRO_STATUS_NO_MEMORY; /* Combine the new region with the original clip */ - + if (surface->saved_clip) { if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR) goto FAIL; From cb3a445150e3771d23854849c2a1c991eaee712c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 19:47:14 +0100 Subject: [PATCH 016/155] Primitive "real" postscript output for stroke/fill/paint --- src/cairo-paginated-surface-private.h | 15 +- src/cairo-paginated-surface.c | 241 ++++++++++++- src/cairo-pdf-surface.c | 3 +- src/cairo-ps-surface.c | 470 ++++++++++++-------------- 4 files changed, 467 insertions(+), 262 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index 79438e4ab..c4c656b48 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -38,11 +38,24 @@ #include "cairoint.h" +typedef enum { + CAIRO_PAGINATED_MODE_EVALUATE, /* evaluate page regions */ + CAIRO_PAGINATED_MODE_RENDER /* render page contents */ +} cairo_paginated_mode_t; + +typedef void (*cairo_paginated_set_mode_t) (cairo_surface_t *target, + cairo_paginated_mode_t mode); + +typedef struct { + cairo_paginated_set_mode_t set_mode; +} cairo_paginated_funcs_t; + cairo_private cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, int width, - int height); + int height, + const cairo_paginated_funcs_t *funcs); cairo_private cairo_surface_t * _cairo_paginated_surface_get_target (cairo_surface_t *surface); diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 6317d7083..6d4c02e14 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -31,6 +31,7 @@ * * Contributor(s): * Carl Worth + * Keith Packard */ /* The paginated surface layer exists to provide as much code sharing @@ -85,6 +86,9 @@ typedef struct _cairo_paginated_surface { /* The target surface to hold the final result. */ cairo_surface_t *target; + /* Paginated-surface specific functions for the target */ + const cairo_paginated_funcs_t *funcs; + /* A cairo_meta_surface to record all operations. To be replayed * against target, and also against image surface as necessary for * fallbacks. */ @@ -97,11 +101,27 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend; static cairo_int_status_t _cairo_paginated_surface_show_page (void *abstract_surface); +typedef struct { + cairo_surface_t base; + int width; + int height; + + cairo_surface_t *target; + + cairo_bool_t fallback; +} cairo_evaluate_surface_t; + +static cairo_evaluate_surface_t * +_cairo_evaluate_surface_create (cairo_surface_t *target, + int width, + int height); + cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, int width, - int height) + int height, + const cairo_paginated_funcs_t *funcs) { cairo_paginated_surface_t *surface; @@ -116,6 +136,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, surface->height = height; surface->target = target; + surface->funcs = funcs; surface->meta = _cairo_meta_surface_create (content, width, height); if (cairo_surface_status (surface->meta)) @@ -191,25 +212,49 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface, cairo_surface_destroy (&image->base); } -static void +static cairo_int_status_t _paint_page (cairo_paginated_surface_t *surface) { + cairo_evaluate_surface_t *evaluate; cairo_surface_t *image; cairo_pattern_t *pattern; + cairo_status_t status; - image = _cairo_image_surface_create_with_content (surface->content, - surface->width, - surface->height); + evaluate = _cairo_evaluate_surface_create (surface->target, + surface->width, surface->height); - _cairo_meta_surface_replay (surface->meta, image); + surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_EVALUATE); + _cairo_meta_surface_replay (surface->meta, &evaluate->base); + surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); - pattern = cairo_pattern_create_for_surface (image); + if (evaluate->base.status) { + status = evaluate->base.status; + cairo_surface_destroy (&evaluate->base); + return status; + } + + if (evaluate->fallback) + { + image = _cairo_image_surface_create_with_content (surface->content, + surface->width, + surface->height); - _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern); + _cairo_meta_surface_replay (surface->meta, image); - cairo_pattern_destroy (pattern); + pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); + _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern); + + cairo_pattern_destroy (pattern); + + cairo_surface_destroy (image); + } + else + { + _cairo_meta_surface_replay (surface->meta, surface->target); + } + + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -409,3 +454,179 @@ const cairo_surface_backend_t cairo_paginated_surface_backend = { _cairo_paginated_surface_show_glyphs, _cairo_paginated_surface_snapshot }; + +static cairo_int_status_t +_cairo_evaluate_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + cairo_evaluate_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->paint) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->paint) (surface->target, op, + source); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_evaluate_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) +{ + cairo_evaluate_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->mask) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->mask) (surface->target, op, + source, mask); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_evaluate_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_evaluate_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->stroke) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->stroke) (surface->target, op, + source, path, style, + ctm, ctm_inverse, + tolerance, antialias); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_evaluate_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_evaluate_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->fill) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->fill) (surface->target, op, + source, path, fill_rule, + tolerance, antialias); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_evaluate_surface_show_glyphs (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + cairo_evaluate_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->show_glyphs) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->show_glyphs) (surface->target, op, + source, + glyphs, num_glyphs, + scaled_font); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static const cairo_surface_backend_t cairo_evaluate_surface_backend = { + NULL, /* create_similar */ + NULL, /* finish_surface */ + NULL, /* acquire_source_image */ + NULL, /* release_source_image */ + NULL, /* acquire_dest_image */ + NULL, /* release_dest_image */ + NULL, /* clone_similar */ + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ + NULL, /* copy_page */ + NULL, /* show_page */ + NULL, /* set_clip_region */ + NULL, /* clip_path */ + NULL, /* get_extents */ + NULL, /* old_show_glyphs */ + NULL, /* get_font_options */ + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + _cairo_evaluate_surface_paint, + _cairo_evaluate_surface_mask, + _cairo_evaluate_surface_stroke, + _cairo_evaluate_surface_fill, + _cairo_evaluate_surface_show_glyphs, + NULL, /* snapshot */ +}; + +static cairo_evaluate_surface_t * +_cairo_evaluate_surface_create (cairo_surface_t *target, + int width, + int height) +{ + cairo_evaluate_surface_t *surface; + + surface = malloc (sizeof (cairo_evaluate_surface_t)); + if (surface == NULL) + goto FAIL; + + _cairo_surface_init (&surface->base, &cairo_evaluate_surface_backend); + + surface->width = width; + surface->height = height; + + surface->target = target; + surface->fallback = FALSE; + + return surface; +FAIL: + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return NULL; +} + + diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 289eeb961..dd2fa9096 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -306,7 +306,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (target, CAIRO_CONTENT_COLOR_ALPHA, - width, height); + width, height, + NULL); /* XXX */ } /** diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 371290cc2..2cf8a9d6b 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -56,6 +56,7 @@ */ static const cairo_surface_backend_t cairo_ps_surface_backend; +static const cairo_paginated_funcs_t cairo_ps_paginated_funcs; typedef struct cairo_ps_surface { cairo_surface_t base; @@ -71,6 +72,8 @@ typedef struct cairo_ps_surface { cairo_bool_t need_start_page; int num_pages; + cairo_paginated_mode_t mode; + #if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED cairo_array_t fonts; #endif @@ -141,6 +144,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->height = height; surface->x_dpi = PS_SURFACE_DPI_DEFAULT; surface->y_dpi = PS_SURFACE_DPI_DEFAULT; + surface->mode = CAIRO_PAGINATED_MODE_EVALUATE; #if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED surface->base.device_x_scale = surface->x_dpi / 72.0; surface->base.device_y_scale = surface->y_dpi / 72.0; @@ -157,7 +161,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, - width, height); + width, height, + &cairo_ps_paginated_funcs); } /** @@ -472,17 +477,6 @@ _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface) } #endif -/* XXX: This function wil go away in favor of the new "analysis mode" - * of cairo_paginated_surface_t */ -static cairo_int_status_t -_cairo_ps_surface_add_fallback_area (cairo_ps_surface_t *surface, - int x, int y, - unsigned int width, - unsigned int height) -{ - return CAIRO_STATUS_SUCCESS; -} - static cairo_bool_t color_is_gray (cairo_color_t *color) { @@ -493,66 +487,66 @@ color_is_gray (cairo_color_t *color) } static cairo_bool_t -color_is_translucent (const cairo_color_t *color) +color_is_opaque (const cairo_color_t *color) { - return color->alpha < 0.999; + return color->alpha >= 0.999; } static cairo_bool_t -format_is_translucent (cairo_format_t format) +format_is_opaque (cairo_format_t format) { switch (format) { case CAIRO_FORMAT_ARGB32: - return TRUE; - case CAIRO_FORMAT_RGB24: return FALSE; - case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_RGB24: return TRUE; + case CAIRO_FORMAT_A8: + return FALSE; case CAIRO_FORMAT_A1: return TRUE; } - return TRUE; + return FALSE; } static cairo_bool_t -surface_is_translucent (const cairo_surface_t *surface) +surface_is_opaque (const cairo_surface_t *surface) { if (_cairo_surface_is_image (surface)) { const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - return format_is_translucent (image_surface->format); + return format_is_opaque (image_surface->format); } return TRUE; } static cairo_bool_t -gradient_is_translucent (const cairo_gradient_pattern_t *gradient) +gradient_is_opaque (const cairo_gradient_pattern_t *gradient) { - return TRUE; /* XXX no gradient support */ + return FALSE; /* XXX no gradient support */ #if 0 int i; for (i = 0; i < gradient->n_stops; i++) - if (color_is_translucent (&gradient->stops[i].color)) - return TRUE; - return FALSE; + if (!color_is_opaque (&gradient->stops[i].color)) + return FALSE; + return TRUE; #endif } static cairo_bool_t -pattern_is_translucent (const cairo_pattern_t *abstract_pattern) +pattern_is_opaque (const cairo_pattern_t *abstract_pattern) { const cairo_pattern_union_t *pattern; pattern = (cairo_pattern_union_t *) abstract_pattern; switch (pattern->base.type) { case CAIRO_PATTERN_TYPE_SOLID: - return color_is_translucent (&pattern->solid.color); + return color_is_opaque (&pattern->solid.color); case CAIRO_PATTERN_TYPE_SURFACE: - return surface_is_translucent (pattern->surface.surface); + return surface_is_opaque (pattern->surface.surface); case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: - return gradient_is_translucent (&pattern->gradient.base); + return gradient_is_opaque (&pattern->gradient.base); } ASSERT_NOT_REACHED; @@ -624,35 +618,35 @@ operator_always_translucent (cairo_operator_t op) } static cairo_bool_t -color_operation_needs_fallback (cairo_operator_t op, - const cairo_color_t *color) +pattern_surface_supported (const cairo_surface_pattern_t *pattern) { - if (operator_always_opaque (op)) + if (pattern->surface->backend->acquire_source_image == NULL) return FALSE; - if (operator_always_translucent (op)) - return TRUE; - return color_is_translucent (color); + return TRUE; } static cairo_bool_t -pattern_type_supported (const cairo_pattern_t *pattern) +pattern_supported (const cairo_pattern_t *pattern) { if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) return TRUE; + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) + return pattern_surface_supported ((const cairo_surface_pattern_t *) pattern); + return FALSE; } static cairo_bool_t -pattern_operation_needs_fallback (cairo_operator_t op, +pattern_operation_supported (cairo_operator_t op, const cairo_pattern_t *pattern) { - if (! pattern_type_supported (pattern)) - return TRUE; - if (operator_always_opaque (op)) + if (! pattern_supported (pattern)) return FALSE; - if (operator_always_translucent (op)) + if (operator_always_opaque (op)) return TRUE; - return pattern_is_translucent (pattern); + if (operator_always_translucent (op)) + return FALSE; + return pattern_is_opaque (pattern); } /* PS Output - this section handles output of the parts of the meta @@ -812,7 +806,15 @@ static void emit_surface_pattern (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern) { - /* XXX: NYI */ + cairo_image_surface_t *image; + cairo_status_t status; + void *image_extra; + + status = _cairo_surface_acquire_source_image (pattern->surface, + &image, + &image_extra); + assert (status == CAIRO_STATUS_SUCCESS); + emit_image (surface, image, &pattern->base.matrix); } static void @@ -855,200 +857,6 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) } } - -static cairo_int_status_t -_cairo_ps_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_ps_surface_t *surface = abstract_dst; - cairo_output_stream_t *stream = surface->stream; - cairo_surface_pattern_t *surface_pattern; - cairo_status_t status; - cairo_image_surface_t *image; - void *image_extra; - - if (surface->need_start_page) - _cairo_ps_surface_start_page (surface); - - if (mask_pattern) { - /* FIXME: Investigate how this can be done... we'll probably - * need pixmap fallbacks for this, though. */ - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite: with mask\n"); - goto bail; - } - - status = CAIRO_STATUS_SUCCESS; - switch (src_pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite: solid\n"); - goto bail; - - case CAIRO_PATTERN_TYPE_SURFACE: - surface_pattern = (cairo_surface_pattern_t *) src_pattern; - - if (src_pattern->extend != CAIRO_EXTEND_NONE) { - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite: repeating image\n"); - goto bail; - } - - - status = _cairo_surface_acquire_source_image (surface_pattern->surface, - &image, - &image_extra); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite: src_pattern not available as image\n"); - goto bail; - } else if (status) { - break; - } - status = emit_image (surface, image, &src_pattern->matrix); - _cairo_surface_release_source_image (surface_pattern->surface, - image, image_extra); - break; - - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite: gradient\n"); - goto bail; - } - - return status; -bail: - return _cairo_ps_surface_add_fallback_area (surface, dst_x, dst_y, width, height); -} - -static cairo_int_status_t -_cairo_ps_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_t *rects, - int num_rects) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_output_stream_t *stream = surface->stream; - cairo_solid_pattern_t solid; - int i; - - if (!num_rects) - return CAIRO_STATUS_SUCCESS; - - if (surface->need_start_page) - _cairo_ps_surface_start_page (surface); - - if (color_operation_needs_fallback (op, color)) { - int min_x = rects[0].x; - int min_y = rects[0].y; - int max_x = rects[0].x + rects[0].width; - int max_y = rects[0].y + rects[0].height; - - for (i = 1; i < num_rects; i++) { - if (rects[i].x < min_x) min_x = rects[i].x; - if (rects[i].y < min_y) min_y = rects[i].y; - if (rects[i].x + rects[i].width > max_x) max_x = rects[i].x + rects[i].width; - if (rects[i].y + rects[i].height > max_y) max_y = rects[i].y + rects[i].height; - } - return _cairo_ps_surface_add_fallback_area (surface, min_x, min_y, max_x - min_x, max_y - min_y); - } - - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_fill_rectangles\n"); - - _cairo_pattern_init_solid (&solid, color); - emit_pattern (surface, &solid.base); - _cairo_pattern_fini (&solid.base); - - _cairo_output_stream_printf (stream, "["); - for (i = 0; i < num_rects; i++) { - _cairo_output_stream_printf (stream, - " %d %d %d %d", - rects[i].x, rects[i].y, - rects[i].width, rects[i].height); - } - - _cairo_output_stream_printf (stream, " ] rectfill\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static double -intersect (cairo_line_t *line, cairo_fixed_t y) -{ - return _cairo_fixed_to_double (line->p1.x) + - _cairo_fixed_to_double (line->p2.x - line->p1.x) * - _cairo_fixed_to_double (y - line->p1.y) / - _cairo_fixed_to_double (line->p2.y - line->p1.y); -} - -static cairo_int_status_t -_cairo_ps_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int x_src, - int y_src, - int x_dst, - int y_dst, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_ps_surface_t *surface = abstract_dst; - cairo_output_stream_t *stream = surface->stream; - int i; - - if (pattern_operation_needs_fallback (op, pattern)) - return _cairo_ps_surface_add_fallback_area (surface, x_dst, y_dst, width, height); - - if (surface->need_start_page) - _cairo_ps_surface_start_page (surface); - - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_composite_trapezoids\n"); - - emit_pattern (surface, pattern); - - for (i = 0; i < num_traps; i++) { - double left_x1, left_x2, right_x1, right_x2, top, bottom; - - left_x1 = intersect (&traps[i].left, traps[i].top); - left_x2 = intersect (&traps[i].left, traps[i].bottom); - right_x1 = intersect (&traps[i].right, traps[i].top); - right_x2 = intersect (&traps[i].right, traps[i].bottom); - top = _cairo_fixed_to_double (traps[i].top); - bottom = _cairo_fixed_to_double (traps[i].bottom); - - _cairo_output_stream_printf - (stream, - "%f %f moveto %f %f lineto %f %f lineto %f %f lineto " - "closepath\n", - left_x1, top, - left_x2, bottom, - right_x2, bottom, - right_x1, top); - } - - _cairo_output_stream_printf (stream, - "fill\n"); - - return CAIRO_STATUS_SUCCESS; -} - typedef struct { cairo_output_stream_t *output_stream; @@ -1135,6 +943,9 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; + if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) + return CAIRO_STATUS_SUCCESS; + _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_intersect_clip_path\n"); @@ -1265,7 +1076,153 @@ _cairo_ps_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, #endif static cairo_int_status_t -_cairo_ps_surface_fill (void *abstract_surface, +_cairo_ps_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + cairo_ps_surface_t *surface = abstract_surface; + cairo_output_stream_t *stream = surface->stream; + cairo_ps_surface_path_info_t info; + + if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (!pattern_operation_supported (op, source)) + return CAIRO_INT_STATUS_UNSUPPORTED; + return CAIRO_STATUS_SUCCESS; + } + + if (surface->need_start_page) + _cairo_ps_surface_start_page (surface); + + _cairo_output_stream_printf (stream, + "%% _cairo_ps_surface_paint\n"); + + emit_pattern (surface, source); + + info.output_stream = stream; + info.has_current_point = FALSE; + + _cairo_output_stream_printf (stream, "0 0 moveto\n"); + _cairo_output_stream_printf (stream, "%f 0 lineto\n", surface->width); + _cairo_output_stream_printf (stream, "%f %f lineto\n", + surface->width, surface->height); + _cairo_output_stream_printf (stream, "0 %f lineto\n", surface->height); + _cairo_output_stream_printf (stream, "closepath fill\n"); + return CAIRO_STATUS_SUCCESS; +} + +static int +_cairo_ps_line_cap (cairo_line_cap_t cap) +{ + switch (cap) { + case CAIRO_LINE_CAP_BUTT: + return 0; + case CAIRO_LINE_CAP_ROUND: + return 1; + case CAIRO_LINE_CAP_SQUARE: + return 2; + default: + ASSERT_NOT_REACHED; + return 0; + } +} + +static int +_cairo_ps_line_join (cairo_line_join_t join) +{ + switch (join) { + case CAIRO_LINE_JOIN_MITER: + return 0; + case CAIRO_LINE_JOIN_ROUND: + return 1; + case CAIRO_LINE_JOIN_BEVEL: + return 2; + default: + ASSERT_NOT_REACHED; + return 0; + } +} + +static cairo_int_status_t +_cairo_ps_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_ps_surface_t *surface = abstract_surface; + cairo_output_stream_t *stream = surface->stream; + cairo_int_status_t status; + cairo_ps_surface_path_info_t info; + + if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (!pattern_operation_supported (op, source)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + return CAIRO_STATUS_SUCCESS; + } + + if (surface->need_start_page) + _cairo_ps_surface_start_page (surface); + + _cairo_output_stream_printf (stream, + "%% _cairo_ps_surface_stroke\n"); + + emit_pattern (surface, source); + + + info.output_stream = stream; + info.has_current_point = FALSE; + + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_ps_surface_path_move_to, + _cairo_ps_surface_path_line_to, + _cairo_ps_surface_path_curve_to, + _cairo_ps_surface_path_close_path, + &info); + + /* + * Switch to user space to set line parameters + */ + _cairo_output_stream_printf (stream, + "gsave\n"); + _cairo_output_stream_printf (stream, + "[%f %f %f %f 0 0] concat\n", + ctm->xx, ctm->yx, ctm->xy, ctm->yy); + /* line width */ + _cairo_output_stream_printf (stream, "%f setlinewidth\n", + style->line_width); + /* line cap */ + _cairo_output_stream_printf (stream, "%d setlinecap\n", + _cairo_ps_line_cap (style->line_cap)); + /* line join */ + _cairo_output_stream_printf (stream, "%d setlinejoin\n", + _cairo_ps_line_join (style->line_join)); + /* dashes */ + if (style->num_dashes) { + int d; + _cairo_output_stream_printf (stream, "["); + for (d = 0; d < style->num_dashes; d++) + _cairo_output_stream_printf (stream, " %f", style->dash[d]); + _cairo_output_stream_printf (stream, "] %f setdash\n", + style->dash_offset); + } + /* miter limit */ + _cairo_output_stream_printf (stream, "%f setmiterlimit\n", + style->miter_limit); + _cairo_output_stream_printf (stream, + "stroke\n"); + _cairo_output_stream_printf (stream, + "grestore\n"); + return status; +} + +static cairo_int_status_t +_cairo_ps_surface_fill (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, @@ -1279,12 +1236,12 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (pattern_operation_needs_fallback (op, source)) - return _cairo_ps_surface_add_fallback_area (surface, - 0, 0, - surface->width, - surface->height); - + if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (!pattern_operation_supported (op, source)) + return CAIRO_INT_STATUS_UNSUPPORTED; + return CAIRO_STATUS_SUCCESS; + } + if (surface->need_start_page) _cairo_ps_surface_start_page (surface); @@ -1329,9 +1286,9 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { NULL, /* acquire_dest_image */ NULL, /* release_dest_image */ NULL, /* clone_similar */ - _cairo_ps_surface_composite, - _cairo_ps_surface_fill_rectangles, - _cairo_ps_surface_composite_trapezoids, + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ _cairo_ps_surface_copy_page, _cairo_ps_surface_show_page, NULL, /* set_clip_region */ @@ -1350,9 +1307,22 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { /* Here are the drawing functions */ - NULL, /* paint */ + _cairo_ps_surface_paint, /* paint */ NULL, /* mask */ - NULL, /* stroke */ + _cairo_ps_surface_stroke, _cairo_ps_surface_fill, NULL /* show_glyphs */ }; + +static void +_cairo_ps_paginated_set_mode (cairo_surface_t *target, + cairo_paginated_mode_t mode) +{ + cairo_ps_surface_t *surface = (cairo_ps_surface_t *) target; + + surface->mode = mode; +} + +static const cairo_paginated_funcs_t cairo_ps_paginated_funcs = { + _cairo_ps_paginated_set_mode, +}; From f9d4482137e7f13e634cc578c64d84ffdea16bca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 17:14:57 -0500 Subject: [PATCH 017/155] rename evaluate surface to analyze surface, pull to separate files --- src/Makefile.am | 2 + src/cairo-analyze-surface-private.h | 55 ++++++ src/cairo-analyze-surface.c | 246 ++++++++++++++++++++++++++ src/cairo-paginated-surface-private.h | 2 +- src/cairo-paginated-surface.c | 210 ++-------------------- src/cairo-ps-surface.c | 10 +- 6 files changed, 319 insertions(+), 206 deletions(-) create mode 100644 src/cairo-analyze-surface-private.h create mode 100644 src/cairo-analyze-surface.c diff --git a/src/Makefile.am b/src/Makefile.am index 908bcb284..38947d4f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -173,6 +173,8 @@ libcairo_la_SOURCES = \ cairo-meta-surface-private.h \ cairo-paginated-surface.c \ cairo-paginated-surface-private.h \ + cairo-analyze-surface.c \ + cairo-analyze-surface-private.h \ $(libcairo_atsui_sources) \ $(libcairo_ft_sources) \ $(libcairo_ps_sources) \ diff --git a/src/cairo-analyze-surface-private.h b/src/cairo-analyze-surface-private.h new file mode 100644 index 000000000..1c90fc934 --- /dev/null +++ b/src/cairo-analyze-surface-private.h @@ -0,0 +1,55 @@ +/* $Id: $ + * + * Copyright © 2005 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 Packard + */ + +#ifndef CAIRO_ANALYZE_SURFACE_H +#define CAIRO_ANALYZE_SURFACE_H + +#include "cairoint.h" + +cairo_private cairo_surface_t * +_cairo_analyze_surface_create (cairo_surface_t *target, + int width, + int height); + +cairo_private pixman_region16_t * +_cairo_analyze_surface_region_supported (cairo_surface_t *surface); + +cairo_private pixman_region16_t * +_cairo_analyze_surface_region_unsupported (cairo_surface_t *unsupported); + +cairo_private cairo_bool_t +_cairo_analyze_surface_has_unsupported (cairo_surface_t *unsupported); + +#endif /* CAIRO_ANALYZE_SURFACE_H */ diff --git a/src/cairo-analyze-surface.c b/src/cairo-analyze-surface.c new file mode 100644 index 000000000..e2d5e845c --- /dev/null +++ b/src/cairo-analyze-surface.c @@ -0,0 +1,246 @@ +/* + * Copyright © 2006 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 Packard + */ + +#include "cairoint.h" + +#include "cairo-analyze-surface-private.h" +#include "cairo-paginated-surface-private.h" + +typedef struct { + cairo_surface_t base; + int width; + int height; + + cairo_surface_t *target; + + cairo_bool_t fallback; +} cairo_analyze_surface_t; + +static cairo_int_status_t +_cairo_analyze_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + cairo_analyze_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->paint) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->paint) (surface->target, op, + source); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_analyze_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) +{ + cairo_analyze_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->mask) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->mask) (surface->target, op, + source, mask); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_analyze_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_analyze_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->stroke) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->stroke) (surface->target, op, + source, path, style, + ctm, ctm_inverse, + tolerance, antialias); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_analyze_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_analyze_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->fill) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->fill) (surface->target, op, + source, path, fill_rule, + tolerance, antialias); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static cairo_int_status_t +_cairo_analyze_surface_show_glyphs (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + cairo_analyze_surface_t *surface = abstract_surface; + cairo_status_t status; + + if (!surface->target->backend->show_glyphs) + status = CAIRO_INT_STATUS_UNSUPPORTED; + else + status = (*surface->target->backend->show_glyphs) (surface->target, op, + source, + glyphs, num_glyphs, + scaled_font); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + surface->fallback = TRUE; + status = CAIRO_STATUS_SUCCESS; + } + return status; +} + +static const cairo_surface_backend_t cairo_analyze_surface_backend = { + NULL, /* create_similar */ + NULL, /* finish_surface */ + NULL, /* acquire_source_image */ + NULL, /* release_source_image */ + NULL, /* acquire_dest_image */ + NULL, /* release_dest_image */ + NULL, /* clone_similar */ + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ + NULL, /* copy_page */ + NULL, /* show_page */ + NULL, /* set_clip_region */ + NULL, /* clip_path */ + NULL, /* get_extents */ + NULL, /* old_show_glyphs */ + NULL, /* get_font_options */ + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + _cairo_analyze_surface_paint, + _cairo_analyze_surface_mask, + _cairo_analyze_surface_stroke, + _cairo_analyze_surface_fill, + _cairo_analyze_surface_show_glyphs, + NULL, /* snapshot */ +}; + +cairo_private cairo_surface_t * +_cairo_analyze_surface_create (cairo_surface_t *target, + int width, + int height) +{ + cairo_analyze_surface_t *surface; + + surface = malloc (sizeof (cairo_analyze_surface_t)); + if (surface == NULL) + goto FAIL; + + _cairo_surface_init (&surface->base, &cairo_analyze_surface_backend); + + surface->width = width; + surface->height = height; + + surface->target = target; + surface->fallback = FALSE; + + return &surface->base; +FAIL: + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return NULL; +} + +cairo_private pixman_region16_t * +_cairo_analyze_surface_region_supported (cairo_surface_t *abstract_surface) +{ + /* XXX */ + return NULL; +} + +cairo_private pixman_region16_t * +_cairo_analyze_surface_region_unsupported (cairo_surface_t *abstract_surface) +{ + /* XXX */ + return NULL; +} + +cairo_private cairo_bool_t +_cairo_analyze_surface_has_unsupported (cairo_surface_t *abstract_surface) +{ + cairo_analyze_surface_t *surface = (cairo_analyze_surface_t *) abstract_surface; + + return surface->fallback; +} + + diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index c4c656b48..b81b78b83 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -39,7 +39,7 @@ #include "cairoint.h" typedef enum { - CAIRO_PAGINATED_MODE_EVALUATE, /* evaluate page regions */ + CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */ CAIRO_PAGINATED_MODE_RENDER /* render page contents */ } cairo_paginated_mode_t; diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 6d4c02e14..a4979c1e7 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -69,6 +69,7 @@ #include "cairo-paginated-surface-private.h" #include "cairo-meta-surface-private.h" +#include "cairo-analyze-surface-private.h" typedef struct _cairo_paginated_surface { cairo_surface_t base; @@ -101,21 +102,6 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend; static cairo_int_status_t _cairo_paginated_surface_show_page (void *abstract_surface); -typedef struct { - cairo_surface_t base; - int width; - int height; - - cairo_surface_t *target; - - cairo_bool_t fallback; -} cairo_evaluate_surface_t; - -static cairo_evaluate_surface_t * -_cairo_evaluate_surface_create (cairo_surface_t *target, - int width, - int height); - cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, @@ -215,25 +201,25 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface, static cairo_int_status_t _paint_page (cairo_paginated_surface_t *surface) { - cairo_evaluate_surface_t *evaluate; + cairo_surface_t *analyze; cairo_surface_t *image; cairo_pattern_t *pattern; cairo_status_t status; - evaluate = _cairo_evaluate_surface_create (surface->target, - surface->width, surface->height); + analyze = _cairo_analyze_surface_create (surface->target, + surface->width, surface->height); - surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_EVALUATE); - _cairo_meta_surface_replay (surface->meta, &evaluate->base); + surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); + _cairo_meta_surface_replay (surface->meta, analyze); surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); - if (evaluate->base.status) { - status = evaluate->base.status; - cairo_surface_destroy (&evaluate->base); + if (analyze->status) { + status = analyze->status; + cairo_surface_destroy (analyze); return status; } - if (evaluate->fallback) + if (_cairo_analyze_surface_has_unsupported (analyze)) { image = _cairo_image_surface_create_with_content (surface->content, surface->width, @@ -454,179 +440,3 @@ const cairo_surface_backend_t cairo_paginated_surface_backend = { _cairo_paginated_surface_show_glyphs, _cairo_paginated_surface_snapshot }; - -static cairo_int_status_t -_cairo_evaluate_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_evaluate_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (!surface->target->backend->paint) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = (*surface->target->backend->paint) (surface->target, op, - source); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - surface->fallback = TRUE; - status = CAIRO_STATUS_SUCCESS; - } - return status; -} - -static cairo_int_status_t -_cairo_evaluate_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_evaluate_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (!surface->target->backend->mask) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = (*surface->target->backend->mask) (surface->target, op, - source, mask); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - surface->fallback = TRUE; - status = CAIRO_STATUS_SUCCESS; - } - return status; -} - -static cairo_int_status_t -_cairo_evaluate_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_evaluate_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (!surface->target->backend->stroke) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = (*surface->target->backend->stroke) (surface->target, op, - source, path, style, - ctm, ctm_inverse, - tolerance, antialias); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - surface->fallback = TRUE; - status = CAIRO_STATUS_SUCCESS; - } - return status; -} - -static cairo_int_status_t -_cairo_evaluate_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_evaluate_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (!surface->target->backend->fill) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = (*surface->target->backend->fill) (surface->target, op, - source, path, fill_rule, - tolerance, antialias); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - surface->fallback = TRUE; - status = CAIRO_STATUS_SUCCESS; - } - return status; -} - -static cairo_int_status_t -_cairo_evaluate_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_evaluate_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (!surface->target->backend->show_glyphs) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = (*surface->target->backend->show_glyphs) (surface->target, op, - source, - glyphs, num_glyphs, - scaled_font); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - surface->fallback = TRUE; - status = CAIRO_STATUS_SUCCESS; - } - return status; -} - -static const cairo_surface_backend_t cairo_evaluate_surface_backend = { - NULL, /* create_similar */ - NULL, /* finish_surface */ - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - NULL, /* clip_path */ - NULL, /* get_extents */ - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - _cairo_evaluate_surface_paint, - _cairo_evaluate_surface_mask, - _cairo_evaluate_surface_stroke, - _cairo_evaluate_surface_fill, - _cairo_evaluate_surface_show_glyphs, - NULL, /* snapshot */ -}; - -static cairo_evaluate_surface_t * -_cairo_evaluate_surface_create (cairo_surface_t *target, - int width, - int height) -{ - cairo_evaluate_surface_t *surface; - - surface = malloc (sizeof (cairo_evaluate_surface_t)); - if (surface == NULL) - goto FAIL; - - _cairo_surface_init (&surface->base, &cairo_evaluate_surface_backend); - - surface->width = width; - surface->height = height; - - surface->target = target; - surface->fallback = FALSE; - - return surface; -FAIL: - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return NULL; -} - - diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 2cf8a9d6b..f1ae414f6 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -144,7 +144,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->height = height; surface->x_dpi = PS_SURFACE_DPI_DEFAULT; surface->y_dpi = PS_SURFACE_DPI_DEFAULT; - surface->mode = CAIRO_PAGINATED_MODE_EVALUATE; + surface->mode = CAIRO_PAGINATED_MODE_ANALYZE; #if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED surface->base.device_x_scale = surface->x_dpi / 72.0; surface->base.device_y_scale = surface->y_dpi / 72.0; @@ -943,7 +943,7 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) + if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; _cairo_output_stream_printf (stream, @@ -1084,7 +1084,7 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_ps_surface_path_info_t info; - if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS; @@ -1158,7 +1158,7 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_int_status_t status; cairo_ps_surface_path_info_t info; - if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1236,7 +1236,7 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) { + if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS; From 2660e79e674a55e71014f83e9247372edd9ab531 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 14:56:41 -0800 Subject: [PATCH 018/155] Rename cairo_analyze_surface_t to cairo_analysis_surface_t. --- src/Makefile.am | 6 +- ...ate.h => cairo-analysis-surface-private.h} | 18 ++-- ...yze-surface.c => cairo-analysis-surface.c} | 100 +++++++++--------- src/cairo-paginated-surface.c | 18 ++-- 4 files changed, 71 insertions(+), 71 deletions(-) rename src/{cairo-analyze-surface-private.h => cairo-analysis-surface-private.h} (79%) rename src/{cairo-analyze-surface.c => cairo-analysis-surface.c} (68%) diff --git a/src/Makefile.am b/src/Makefile.am index 38947d4f1..adc6552be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -173,8 +173,8 @@ libcairo_la_SOURCES = \ cairo-meta-surface-private.h \ cairo-paginated-surface.c \ cairo-paginated-surface-private.h \ - cairo-analyze-surface.c \ - cairo-analyze-surface-private.h \ + cairo-analysis-surface.c \ + cairo-analysis-surface-private.h \ $(libcairo_atsui_sources) \ $(libcairo_ft_sources) \ $(libcairo_ps_sources) \ @@ -189,7 +189,7 @@ libcairo_la_SOURCES = \ $(libcairo_glitz_sources) \ $(libcairo_win32_sources) \ $(libcairo_beos_sources) \ - $(libcairo_directfb_sources) \ + $(libcairo_directfb_sources) \ cairoint.h libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols) diff --git a/src/cairo-analyze-surface-private.h b/src/cairo-analysis-surface-private.h similarity index 79% rename from src/cairo-analyze-surface-private.h rename to src/cairo-analysis-surface-private.h index 1c90fc934..75ec9ffd5 100644 --- a/src/cairo-analyze-surface-private.h +++ b/src/cairo-analysis-surface-private.h @@ -33,23 +33,23 @@ * Keith Packard */ -#ifndef CAIRO_ANALYZE_SURFACE_H -#define CAIRO_ANALYZE_SURFACE_H +#ifndef CAIRO_ANALYSIS_SURFACE_H +#define CAIRO_ANALYSIS_SURFACE_H #include "cairoint.h" cairo_private cairo_surface_t * -_cairo_analyze_surface_create (cairo_surface_t *target, - int width, - int height); +_cairo_analysis_surface_create (cairo_surface_t *target, + int width, + int height); cairo_private pixman_region16_t * -_cairo_analyze_surface_region_supported (cairo_surface_t *surface); +_cairo_analysis_surface_region_supported (cairo_surface_t *surface); cairo_private pixman_region16_t * -_cairo_analyze_surface_region_unsupported (cairo_surface_t *unsupported); +_cairo_analysis_surface_region_unsupported (cairo_surface_t *unsupported); cairo_private cairo_bool_t -_cairo_analyze_surface_has_unsupported (cairo_surface_t *unsupported); +_cairo_analysis_surface_has_unsupported (cairo_surface_t *unsupported); -#endif /* CAIRO_ANALYZE_SURFACE_H */ +#endif /* CAIRO_ANALYSIS_SURFACE_H */ diff --git a/src/cairo-analyze-surface.c b/src/cairo-analysis-surface.c similarity index 68% rename from src/cairo-analyze-surface.c rename to src/cairo-analysis-surface.c index e2d5e845c..4349da745 100644 --- a/src/cairo-analyze-surface.c +++ b/src/cairo-analysis-surface.c @@ -34,7 +34,7 @@ #include "cairoint.h" -#include "cairo-analyze-surface-private.h" +#include "cairo-analysis-surface-private.h" #include "cairo-paginated-surface-private.h" typedef struct { @@ -45,14 +45,14 @@ typedef struct { cairo_surface_t *target; cairo_bool_t fallback; -} cairo_analyze_surface_t; +} cairo_analysis_surface_t; static cairo_int_status_t -_cairo_analyze_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) +_cairo_analysis_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) { - cairo_analyze_surface_t *surface = abstract_surface; + cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status; if (!surface->target->backend->paint) @@ -68,12 +68,12 @@ _cairo_analyze_surface_paint (void *abstract_surface, } static cairo_int_status_t -_cairo_analyze_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) +_cairo_analysis_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) { - cairo_analyze_surface_t *surface = abstract_surface; + cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status; if (!surface->target->backend->mask) @@ -89,17 +89,17 @@ _cairo_analyze_surface_mask (void *abstract_surface, } static cairo_int_status_t -_cairo_analyze_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) +_cairo_analysis_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) { - cairo_analyze_surface_t *surface = abstract_surface; + cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status; if (!surface->target->backend->stroke) @@ -117,15 +117,15 @@ _cairo_analyze_surface_stroke (void *abstract_surface, } static cairo_int_status_t -_cairo_analyze_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) +_cairo_analysis_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) { - cairo_analyze_surface_t *surface = abstract_surface; + cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status; if (!surface->target->backend->fill) @@ -142,14 +142,14 @@ _cairo_analyze_surface_fill (void *abstract_surface, } static cairo_int_status_t -_cairo_analyze_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) +_cairo_analysis_surface_show_glyphs (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) { - cairo_analyze_surface_t *surface = abstract_surface; + cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status; if (!surface->target->backend->show_glyphs) @@ -166,7 +166,7 @@ _cairo_analyze_surface_show_glyphs (void *abstract_surface, return status; } -static const cairo_surface_backend_t cairo_analyze_surface_backend = { +static const cairo_surface_backend_t cairo_analysis_surface_backend = { NULL, /* create_similar */ NULL, /* finish_surface */ NULL, /* acquire_source_image */ @@ -188,26 +188,26 @@ static const cairo_surface_backend_t cairo_analyze_surface_backend = { NULL, /* mark_dirty_rectangle */ NULL, /* scaled_font_fini */ NULL, /* scaled_glyph_fini */ - _cairo_analyze_surface_paint, - _cairo_analyze_surface_mask, - _cairo_analyze_surface_stroke, - _cairo_analyze_surface_fill, - _cairo_analyze_surface_show_glyphs, + _cairo_analysis_surface_paint, + _cairo_analysis_surface_mask, + _cairo_analysis_surface_stroke, + _cairo_analysis_surface_fill, + _cairo_analysis_surface_show_glyphs, NULL, /* snapshot */ }; cairo_private cairo_surface_t * -_cairo_analyze_surface_create (cairo_surface_t *target, +_cairo_analysis_surface_create (cairo_surface_t *target, int width, int height) { - cairo_analyze_surface_t *surface; + cairo_analysis_surface_t *surface; - surface = malloc (sizeof (cairo_analyze_surface_t)); + surface = malloc (sizeof (cairo_analysis_surface_t)); if (surface == NULL) goto FAIL; - _cairo_surface_init (&surface->base, &cairo_analyze_surface_backend); + _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend); surface->width = width; surface->height = height; @@ -222,23 +222,23 @@ FAIL: } cairo_private pixman_region16_t * -_cairo_analyze_surface_region_supported (cairo_surface_t *abstract_surface) +_cairo_analysis_surface_region_supported (cairo_surface_t *abstract_surface) { /* XXX */ return NULL; } cairo_private pixman_region16_t * -_cairo_analyze_surface_region_unsupported (cairo_surface_t *abstract_surface) +_cairo_analysis_surface_region_unsupported (cairo_surface_t *abstract_surface) { /* XXX */ return NULL; } cairo_private cairo_bool_t -_cairo_analyze_surface_has_unsupported (cairo_surface_t *abstract_surface) +_cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface) { - cairo_analyze_surface_t *surface = (cairo_analyze_surface_t *) abstract_surface; + cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; return surface->fallback; } diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index a4979c1e7..80e87abf0 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -69,7 +69,7 @@ #include "cairo-paginated-surface-private.h" #include "cairo-meta-surface-private.h" -#include "cairo-analyze-surface-private.h" +#include "cairo-analysis-surface-private.h" typedef struct _cairo_paginated_surface { cairo_surface_t base; @@ -201,25 +201,25 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface, static cairo_int_status_t _paint_page (cairo_paginated_surface_t *surface) { - cairo_surface_t *analyze; + cairo_surface_t *analysis; cairo_surface_t *image; cairo_pattern_t *pattern; cairo_status_t status; - analyze = _cairo_analyze_surface_create (surface->target, - surface->width, surface->height); + analysis = _cairo_analysis_surface_create (surface->target, + surface->width, surface->height); surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); - _cairo_meta_surface_replay (surface->meta, analyze); + _cairo_meta_surface_replay (surface->meta, analysis); surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); - if (analyze->status) { - status = analyze->status; - cairo_surface_destroy (analyze); + if (analysis->status) { + status = analysis->status; + cairo_surface_destroy (analysis); return status; } - if (_cairo_analyze_surface_has_unsupported (analyze)) + if (_cairo_analysis_surface_has_unsupported (analysis)) { image = _cairo_image_surface_create_with_content (surface->content, surface->width, From aecb07a26d1db73cf6eee183de0f77615dea6830 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 14:58:51 -0800 Subject: [PATCH 019/155] cairo_analysis_surface: Rename region_[un]supported() to get_[un]supported(). --- src/cairo-analysis-surface-private.h | 4 ++-- src/cairo-analysis-surface.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cairo-analysis-surface-private.h b/src/cairo-analysis-surface-private.h index 75ec9ffd5..62e67ae68 100644 --- a/src/cairo-analysis-surface-private.h +++ b/src/cairo-analysis-surface-private.h @@ -44,10 +44,10 @@ _cairo_analysis_surface_create (cairo_surface_t *target, int height); cairo_private pixman_region16_t * -_cairo_analysis_surface_region_supported (cairo_surface_t *surface); +_cairo_analysis_surface_get_supported (cairo_surface_t *surface); cairo_private pixman_region16_t * -_cairo_analysis_surface_region_unsupported (cairo_surface_t *unsupported); +_cairo_analysis_surface_get_unsupported (cairo_surface_t *unsupported); cairo_private cairo_bool_t _cairo_analysis_surface_has_unsupported (cairo_surface_t *unsupported); diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index 4349da745..20ac5ae08 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -222,14 +222,14 @@ FAIL: } cairo_private pixman_region16_t * -_cairo_analysis_surface_region_supported (cairo_surface_t *abstract_surface) +_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface) { /* XXX */ return NULL; } cairo_private pixman_region16_t * -_cairo_analysis_surface_region_unsupported (cairo_surface_t *abstract_surface) +_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface) { /* XXX */ return NULL; From ce683a240236fbe8083f284195acf0f78aa05048 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 15:12:15 -0800 Subject: [PATCH 020/155] Drop gratuitous structure with single function pointer. Rename paginated_set_mode to set_paginated_mode. --- src/cairo-paginated-surface-private.h | 10 +++------ src/cairo-paginated-surface.c | 12 +++++------ src/cairo-ps-surface.c | 31 +++++++++++++-------------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index b81b78b83..cb3259617 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -43,19 +43,15 @@ typedef enum { CAIRO_PAGINATED_MODE_RENDER /* render page contents */ } cairo_paginated_mode_t; -typedef void (*cairo_paginated_set_mode_t) (cairo_surface_t *target, - cairo_paginated_mode_t mode); - -typedef struct { - cairo_paginated_set_mode_t set_mode; -} cairo_paginated_funcs_t; +typedef void (*cairo_set_paginated_mode_func_t) (cairo_surface_t *target, + cairo_paginated_mode_t mode); cairo_private cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, int width, int height, - const cairo_paginated_funcs_t *funcs); + cairo_set_paginated_mode_func_t set_paginated_mode); cairo_private cairo_surface_t * _cairo_paginated_surface_get_target (cairo_surface_t *surface); diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 80e87abf0..bb5e03436 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -87,8 +87,8 @@ typedef struct _cairo_paginated_surface { /* The target surface to hold the final result. */ cairo_surface_t *target; - /* Paginated-surface specific functions for the target */ - const cairo_paginated_funcs_t *funcs; + /* Paginated-surface specific function for the target */ + cairo_set_paginated_mode_func_t set_paginated_mode; /* A cairo_meta_surface to record all operations. To be replayed * against target, and also against image surface as necessary for @@ -107,7 +107,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, int width, int height, - const cairo_paginated_funcs_t *funcs) + cairo_set_paginated_mode_func_t set_paginated_mode) { cairo_paginated_surface_t *surface; @@ -122,7 +122,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, surface->height = height; surface->target = target; - surface->funcs = funcs; + surface->set_paginated_mode = set_paginated_mode; surface->meta = _cairo_meta_surface_create (content, width, height); if (cairo_surface_status (surface->meta)) @@ -209,9 +209,9 @@ _paint_page (cairo_paginated_surface_t *surface) analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); - surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); + surface->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); _cairo_meta_surface_replay (surface->meta, analysis); - surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); + surface->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); if (analysis->status) { status = analysis->status; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f1ae414f6..7f31f5831 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -56,7 +56,10 @@ */ static const cairo_surface_backend_t cairo_ps_surface_backend; -static const cairo_paginated_funcs_t cairo_ps_paginated_funcs; + +static void +_cairo_ps_set_paginated_mode (cairo_surface_t *target, + cairo_paginated_mode_t mode); typedef struct cairo_ps_surface { cairo_surface_t base; @@ -72,7 +75,7 @@ typedef struct cairo_ps_surface { cairo_bool_t need_start_page; int num_pages; - cairo_paginated_mode_t mode; + cairo_paginated_mode_t paginated_mode; #if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED cairo_array_t fonts; @@ -144,7 +147,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->height = height; surface->x_dpi = PS_SURFACE_DPI_DEFAULT; surface->y_dpi = PS_SURFACE_DPI_DEFAULT; - surface->mode = CAIRO_PAGINATED_MODE_ANALYZE; + surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; #if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED surface->base.device_x_scale = surface->x_dpi / 72.0; surface->base.device_y_scale = surface->y_dpi / 72.0; @@ -162,7 +165,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height, - &cairo_ps_paginated_funcs); + _cairo_ps_set_paginated_mode); } /** @@ -943,7 +946,7 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; _cairo_output_stream_printf (stream, @@ -1084,7 +1087,7 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_ps_surface_path_info_t info; - if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS; @@ -1158,7 +1161,7 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_int_status_t status; cairo_ps_surface_path_info_t info; - if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1236,7 +1239,7 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS; @@ -1315,14 +1318,10 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { }; static void -_cairo_ps_paginated_set_mode (cairo_surface_t *target, - cairo_paginated_mode_t mode) +_cairo_ps_set_paginated_mode (cairo_surface_t *target, + cairo_paginated_mode_t paginated_mode) { - cairo_ps_surface_t *surface = (cairo_ps_surface_t *) target; + cairo_ps_surface_t *surface = (cairo_ps_surface_t *) target; - surface->mode = mode; + surface->paginated_mode = paginated_mode; } - -static const cairo_paginated_funcs_t cairo_ps_paginated_funcs = { - _cairo_ps_paginated_set_mode, -}; From f2245a7932b857ff70dc0476490090d906ae61f8 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 17:07:22 -0800 Subject: [PATCH 021/155] Remove unused RCS $Id:$ tags. --- src/cairo-wideint.c | 3 +-- src/cairo-wideint.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c index 9e4914e61..89df00b37 100644 --- a/src/cairo-wideint.c +++ b/src/cairo-wideint.c @@ -1,5 +1,4 @@ -/* - * $Id: cairo-wideint.c,v 1.6 2005-07-30 19:57:54 keithp Exp $ +/* cairo - a vector graphics library with display and print output * * Copyright © 2004 Keith Packard * diff --git a/src/cairo-wideint.h b/src/cairo-wideint.h index b008b5d5a..795cde73d 100644 --- a/src/cairo-wideint.h +++ b/src/cairo-wideint.h @@ -1,5 +1,4 @@ -/* - * $Id: cairo-wideint.h,v 1.12 2005-08-05 14:48:19 cworth Exp $ +/* cairo - a vector graphics library with display and print output * * Copyright © 2004 Keith Packard * From 1769830e6eea08744830c1c7ea9220d56808831a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 17:22:45 -0800 Subject: [PATCH 022/155] Implement cairo_scaled_font_get_type --- src/cairo-atsui-font.c | 1 + src/cairo-ft-font.c | 1 + src/cairo-scaled-font.c | 6 ++++++ src/cairo-win32-font.c | 1 + src/cairoint.h | 2 ++ 5 files changed, 11 insertions(+) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 572359f8d..9c5585178 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -664,6 +664,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, } const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = { + CAIRO_FONT_TYPE_ATSUI, _cairo_atsui_font_create_toy, _cairo_atsui_font_fini, _cairo_atsui_font_scaled_glyph_init, diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index e159826a0..092838ab4 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -1901,6 +1901,7 @@ _cairo_ft_show_glyphs (void *abstract_font, } const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { + CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_create_toy, _cairo_ft_scaled_font_fini, _cairo_ft_scaled_glyph_init, diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 8ebbf455f..46e1caccf 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -118,6 +118,12 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, _cairo_error (status); } +cairo_font_type_t +cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font) +{ + return scaled_font->backend->type; +} + /** * cairo_scaled_font_status: * @scaled_font: a #cairo_scaled_font_t diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index ca8e4a610..a3289fced 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1355,6 +1355,7 @@ CLEANUP_FONT: } const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = { + CAIRO_FONT_TYPE_WIN32, _cairo_win32_scaled_font_create_toy, _cairo_win32_scaled_font_fini, _cairo_win32_scaled_font_glyph_init, diff --git a/src/cairoint.h b/src/cairoint.h index 401114cb7..a1978a90d 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -509,6 +509,8 @@ typedef enum _cairo_scaled_glyph_info { } cairo_scaled_glyph_info_t; struct _cairo_scaled_font_backend { + cairo_font_type_t type; + cairo_status_t (*create_toy) (cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, From 06b83b89fc4271060c63b284d7909162b92152f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 17:49:53 -0800 Subject: [PATCH 023/155] Support image surface patterns --- src/cairo-ps-surface.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f1ae414f6..c6aeff08e 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -672,7 +672,8 @@ compress_dup (const void *data, unsigned long data_size, static cairo_status_t emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, - cairo_matrix_t *matrix) + cairo_matrix_t *matrix, + char *name) { cairo_status_t status; unsigned char *rgb, *compressed; @@ -751,6 +752,17 @@ emit_image (cairo_ps_surface_t *surface, cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0); cairo_matrix_multiply (&d2i, &d2i, matrix); + _cairo_output_stream_printf (surface->stream, "/%sString %d string def\n", + name, (int) rgb_size); + _cairo_output_stream_printf (surface->stream, + "currentfile %sString readstring\n", name); + /* Compressed image data */ + _cairo_output_stream_write (surface->stream, rgb, rgb_size); + + _cairo_output_stream_printf (surface->stream, + "\n"); + + _cairo_output_stream_printf (surface->stream, "/%s {\n", name); _cairo_output_stream_printf (surface->stream, "/DeviceRGB setcolorspace\n" "<<\n" @@ -759,23 +771,20 @@ emit_image (cairo_ps_surface_t *surface, " /Height %d\n" " /BitsPerComponent 8\n" " /Decode [ 0 1 0 1 0 1 ]\n" - " /DataSource currentfile\n" + " /DataSource %sString\n" " /ImageMatrix [ %f %f %f %f %f %f ]\n" ">>\n" "image\n", opaque_image->width, opaque_image->height, + name, d2i.xx, d2i.yx, d2i.xy, d2i.yy, d2i.x0, d2i.y0); + _cairo_output_stream_printf (surface->stream, "} def\n"); - /* Compressed image data */ - _cairo_output_stream_write (surface->stream, rgb, rgb_size); status = CAIRO_STATUS_SUCCESS; - _cairo_output_stream_printf (surface->stream, - "\n"); - free (compressed); bail2: free (rgb); @@ -809,12 +818,26 @@ emit_surface_pattern (cairo_ps_surface_t *surface, cairo_image_surface_t *image; cairo_status_t status; void *image_extra; + cairo_rectangle_t extents; status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); assert (status == CAIRO_STATUS_SUCCESS); - emit_image (surface, image, &pattern->base.matrix); + emit_image (surface, image, &pattern->base.matrix, "MyPattern"); + _cairo_output_stream_printf (surface->stream, + "<< /PatternType 1 /PaintType 1 /TilingType 1\n"); + _cairo_surface_get_extents (&image->base, &extents); + _cairo_output_stream_printf (surface->stream, + "/BBox [0 0 %d %d]\n", + extents.width, extents.height); + _cairo_output_stream_printf (surface->stream, + "/XStep %d /YStep %d\n", + extents.width, extents.height); + _cairo_output_stream_printf (surface->stream, + "/PaintProc { begin MyPattern\n"); + _cairo_output_stream_printf (surface->stream, + " end } bind >> matrix makepattern setpattern\n"); } static void From 59e4a32d550d14cfaa0687e716c7df0cadf56adc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 19:23:47 -0800 Subject: [PATCH 024/155] Primitive ps glyph support. Fix ps strokes to not leave path defined --- src/cairo-ps-surface.c | 52 +++++++++++++++++++++++++++++++++++++---- src/cairo-scaled-font.c | 2 +- src/cairoint.h | 2 +- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index c6aeff08e..119b99eaa 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -752,10 +752,18 @@ emit_image (cairo_ps_surface_t *surface, cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0); cairo_matrix_multiply (&d2i, &d2i, matrix); +#if 1 + /* Construct a string holding the entire image (!) */ _cairo_output_stream_printf (surface->stream, "/%sString %d string def\n", name, (int) rgb_size); _cairo_output_stream_printf (surface->stream, "currentfile %sString readstring\n", name); +#else + /* Construct a reusable stream decoder holding the image */ + _cairo_output_stream_printf (surface->stream, "/%sString <<\n", name); + /* intent = image data */ + _cairo_output_stream_printf (surface->stream, "\t/Intent 0\n"); +#endif /* Compressed image data */ _cairo_output_stream_write (surface->stream, rgb, rgb_size); @@ -781,7 +789,7 @@ emit_image (cairo_ps_surface_t *surface, d2i.xx, d2i.yx, d2i.xy, d2i.yy, d2i.x0, d2i.y0); - _cairo_output_stream_printf (surface->stream, "} def\n"); + _cairo_output_stream_printf (surface->stream, "} bind def\n"); status = CAIRO_STATUS_SUCCESS; @@ -1200,6 +1208,8 @@ _cairo_ps_surface_stroke (void *abstract_surface, info.output_stream = stream; info.has_current_point = FALSE; + _cairo_output_stream_printf (stream, + "gsave\n"); status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, _cairo_ps_surface_path_move_to, @@ -1211,8 +1221,6 @@ _cairo_ps_surface_stroke (void *abstract_surface, /* * Switch to user space to set line parameters */ - _cairo_output_stream_printf (stream, - "gsave\n"); _cairo_output_stream_printf (stream, "[%f %f %f %f 0 0] concat\n", ctm->xx, ctm->yx, ctm->xy, ctm->yy); @@ -1301,6 +1309,41 @@ _cairo_ps_surface_fill (void *abstract_surface, return status; } +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, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + cairo_ps_surface_t *surface = abstract_surface; + cairo_output_stream_t *stream = surface->stream; + cairo_int_status_t status; + cairo_path_fixed_t *path; + + if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (!pattern_operation_supported (op, source)) + return CAIRO_INT_STATUS_UNSUPPORTED; + return CAIRO_STATUS_SUCCESS; + } + + if (surface->need_start_page) + _cairo_ps_surface_start_page (surface); + + _cairo_output_stream_printf (stream, + "%% _cairo_ps_surface_show_glyphs\n"); + + path = _cairo_path_fixed_create (); + _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, path); + status = _cairo_ps_surface_fill (abstract_surface, op, source, + path, CAIRO_FILL_RULE_WINDING, + 0.1, scaled_font->options.antialias); + _cairo_path_fixed_destroy (path); + + return CAIRO_STATUS_SUCCESS; +} + static const cairo_surface_backend_t cairo_ps_surface_backend = { NULL, /* create_similar */ _cairo_ps_surface_finish, @@ -1334,7 +1377,8 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { NULL, /* mask */ _cairo_ps_surface_stroke, _cairo_ps_surface_fill, - NULL /* show_glyphs */ + _cairo_ps_surface_show_glyphs, + NULL, /* snapshot */ }; static void diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 8ebbf455f..22d22bea2 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -1008,7 +1008,7 @@ _scaled_glyph_path_close_path (void *abstract_closure) cairo_status_t _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, + const cairo_glyph_t *glyphs, int num_glyphs, cairo_path_fixed_t *path) { diff --git a/src/cairoint.h b/src/cairoint.h index 401114cb7..3d01e40d1 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1529,7 +1529,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_private cairo_status_t _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, + const cairo_glyph_t *glyphs, int num_glyphs, cairo_path_fixed_t *path); From ad247974ebcfc5ede9fd3856eeaee4860318d118 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 19:34:32 -0800 Subject: [PATCH 025/155] Release pattern source image when done with it --- src/cairo-ps-surface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 119b99eaa..aa5ac89cb 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -833,6 +833,7 @@ emit_surface_pattern (cairo_ps_surface_t *surface, &image_extra); assert (status == CAIRO_STATUS_SUCCESS); emit_image (surface, image, &pattern->base.matrix, "MyPattern"); + _cairo_surface_release_source_image (pattern->surface, image, image_extra); _cairo_output_stream_printf (surface->stream, "<< /PatternType 1 /PaintType 1 /TilingType 1\n"); _cairo_surface_get_extents (&image->base, &extents); From 9ca67992a5816db49e8dca866816481483896814 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 20:05:57 -0800 Subject: [PATCH 026/155] Support meta surface patterns --- src/cairo-paginated-surface.c | 11 +++++++++- src/cairo-ps-surface.c | 39 +++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index a4979c1e7..17036a43d 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -155,6 +155,15 @@ _cairo_paginated_surface_get_target (cairo_surface_t *surface) return paginated_surface->target; } +static cairo_surface_t * +_cairo_paginated_surface_create_similar (void *other, + cairo_content_t content, + int width, + int height) +{ + return _cairo_meta_surface_create (content, width, height); +} + static cairo_status_t _cairo_paginated_surface_finish (void *abstract_surface) { @@ -412,7 +421,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other) } const cairo_surface_backend_t cairo_paginated_surface_backend = { - NULL, /* create_similar */ + _cairo_paginated_surface_create_similar, _cairo_paginated_surface_finish, _cairo_paginated_surface_acquire_source_image, _cairo_paginated_surface_release_source_image, diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index aa5ac89cb..4245c9be6 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -41,6 +41,7 @@ #include "cairo-ps.h" #include "cairo-font-subset-private.h" #include "cairo-paginated-surface-private.h" +#include "cairo-meta-surface-private.h" #include "cairo-ft-private.h" #include @@ -620,9 +621,11 @@ operator_always_translucent (cairo_operator_t op) static cairo_bool_t pattern_surface_supported (const cairo_surface_pattern_t *pattern) { - if (pattern->surface->backend->acquire_source_image == NULL) - return FALSE; - return TRUE; + if (_cairo_surface_is_meta (pattern->surface)) + return TRUE; + if (pattern->surface->backend->acquire_source_image != NULL) + return TRUE; + return FALSE; } static cairo_bool_t @@ -823,20 +826,30 @@ static void emit_surface_pattern (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern) { - cairo_image_surface_t *image; - cairo_status_t status; - void *image_extra; cairo_rectangle_t extents; - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, - &image_extra); - assert (status == CAIRO_STATUS_SUCCESS); - emit_image (surface, image, &pattern->base.matrix, "MyPattern"); - _cairo_surface_release_source_image (pattern->surface, image, image_extra); + 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; + _cairo_output_stream_printf (surface->stream, "} bind def\n"); + } else { + cairo_image_surface_t *image; + void *image_extra; + cairo_status_t status; + + status = _cairo_surface_acquire_source_image (pattern->surface, + &image, + &image_extra); + _cairo_surface_get_extents (&image->base, &extents); + assert (status == CAIRO_STATUS_SUCCESS); + emit_image (surface, image, &pattern->base.matrix, "MyPattern"); + _cairo_surface_release_source_image (pattern->surface, image, + image_extra); + } _cairo_output_stream_printf (surface->stream, "<< /PatternType 1 /PaintType 1 /TilingType 1\n"); - _cairo_surface_get_extents (&image->base, &extents); _cairo_output_stream_printf (surface->stream, "/BBox [0 0 %d %d]\n", extents.width, extents.height); From 2984f60a3a4571a8d4179fdc64a9e67ce9854f21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Feb 2006 20:09:24 -0800 Subject: [PATCH 027/155] Need cairo_analyze_surface_get_extents --- src/cairo-analyze-surface.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cairo-analyze-surface.c b/src/cairo-analyze-surface.c index e2d5e845c..a3ea7079e 100644 --- a/src/cairo-analyze-surface.c +++ b/src/cairo-analyze-surface.c @@ -47,6 +47,15 @@ typedef struct { cairo_bool_t fallback; } cairo_analyze_surface_t; +static cairo_int_status_t +_cairo_analyze_surface_get_extents (void *abstract_surface, + cairo_rectangle_t *rectangle) +{ + cairo_analyze_surface_t *surface = abstract_surface; + + return _cairo_surface_get_extents (surface->target, rectangle); +} + static cairo_int_status_t _cairo_analyze_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -181,7 +190,7 @@ static const cairo_surface_backend_t cairo_analyze_surface_backend = { NULL, /* show_page */ NULL, /* set_clip_region */ NULL, /* clip_path */ - NULL, /* get_extents */ + _cairo_analyze_surface_get_extents, NULL, /* old_show_glyphs */ NULL, /* get_font_options */ NULL, /* flush */ From 5ae0b9f912b7f5fd1700cbf18763a05493f55b62 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 23:11:32 -0800 Subject: [PATCH 028/155] Implement cairo_surface_get_type --- src/cairo-directfb-surface.c | 1 + src/cairo-glitz-surface.c | 1 + src/cairo-image-surface.c | 1 + src/cairo-meta-surface.c | 1 + src/cairo-paginated-surface.c | 5 +++++ src/cairo-pdf-surface.c | 1 + src/cairo-ps-surface.c | 1 + src/cairo-surface.c | 15 +++++++++++++++ src/cairo-svg-surface.c | 1 + src/cairo-win32-surface.c | 1 + src/cairo-xcb-surface.c | 1 + src/cairo-xlib-surface.c | 1 + src/cairoint.h | 12 ++++++++++++ 13 files changed, 42 insertions(+) diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c index be1791584..a02e56bf4 100644 --- a/src/cairo-directfb-surface.c +++ b/src/cairo-directfb-surface.c @@ -662,6 +662,7 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, static const cairo_surface_backend_t cairo_directfb_surface_backend = { + CAIRO_SURFACE_TYPE_DIRECTFB, _cairo_directfb_surface_create_similar, _cairo_directfb_surface_finish, _cairo_directfb_surface_acquire_source_image, diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index b62547236..667e231d5 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -2121,6 +2121,7 @@ _cairo_glitz_surface_flush (void *abstract_surface) } static const cairo_surface_backend_t cairo_glitz_surface_backend = { + CAIRO_SURFACE_TYPE_GLITZ, _cairo_glitz_surface_create_similar, _cairo_glitz_surface_finish, _cairo_glitz_surface_acquire_source_image, diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 108e89b5e..06219464c 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -903,6 +903,7 @@ _cairo_surface_is_image (const cairo_surface_t *surface) } const cairo_surface_backend_t cairo_image_surface_backend = { + CAIRO_SURFACE_TYPE_IMAGE, _cairo_image_surface_create_similar, _cairo_image_surface_finish, _cairo_image_surface_acquire_source_image, diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index 6f824634c..f7aeb719c 100644 --- a/src/cairo-meta-surface.c +++ b/src/cairo-meta-surface.c @@ -557,6 +557,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface) } static const cairo_surface_backend_t cairo_meta_surface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_META, _cairo_meta_surface_create_similar, _cairo_meta_surface_finish, _cairo_meta_surface_acquire_source_image, diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 6317d7083..4bb857265 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -111,6 +111,10 @@ _cairo_paginated_surface_create (cairo_surface_t *target, _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend); + /* Override surface->base.type with target's type so we don't leak + * evidence of the paginated wrapper out to the user. */ + surface->base.type = cairo_surface_get_type (target); + surface->content = content; surface->width = width; surface->height = height; @@ -381,6 +385,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other) } const cairo_surface_backend_t cairo_paginated_surface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, NULL, /* create_similar */ _cairo_paginated_surface_finish, _cairo_paginated_surface_acquire_source_image, diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 289eeb961..cb8287bcf 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1657,6 +1657,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface, } static const cairo_surface_backend_t cairo_pdf_surface_backend = { + CAIRO_SURFACE_TYPE_PDF, _cairo_pdf_surface_create_similar, _cairo_pdf_surface_finish, NULL, /* acquire_source_image */ diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 371290cc2..6028b6d50 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1322,6 +1322,7 @@ _cairo_ps_surface_fill (void *abstract_surface, } static const cairo_surface_backend_t cairo_ps_surface_backend = { + CAIRO_SURFACE_TYPE_PS, NULL, /* create_similar */ _cairo_ps_surface_finish, NULL, /* acquire_source_image */ diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 52aeafe46..a317e5b64 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -43,6 +43,7 @@ const cairo_surface_t _cairo_surface_nil = { &cairo_image_surface_backend, /* backend */ + CAIRO_SURFACE_TYPE_IMAGE, -1, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ FALSE, /* finished */ @@ -59,6 +60,7 @@ const cairo_surface_t _cairo_surface_nil = { const cairo_surface_t _cairo_surface_nil_file_not_found = { &cairo_image_surface_backend, /* backend */ + CAIRO_SURFACE_TYPE_IMAGE, -1, /* ref_count */ CAIRO_STATUS_FILE_NOT_FOUND, /* status */ FALSE, /* finished */ @@ -75,6 +77,7 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = { const cairo_surface_t _cairo_surface_nil_read_error = { &cairo_image_surface_backend, /* backend */ + CAIRO_SURFACE_TYPE_IMAGE, -1, /* ref_count */ CAIRO_STATUS_READ_ERROR, /* status */ FALSE, /* finished */ @@ -118,6 +121,16 @@ _cairo_surface_set_error (cairo_surface_t *surface, _cairo_error (status); } +cairo_surface_type_t +cairo_surface_get_type (cairo_surface_t *surface) +{ + /* We don't use surface->backend->type here so that some of the + * special "wrapper" surfaces such as cairo_paginated_surface_t + * can override surface->type with the type of the "child" + * surface. */ + return surface->type; +} + /** * cairo_surface_status: * @surface: a #cairo_surface_t @@ -141,6 +154,8 @@ _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend) { surface->backend = backend; + + surface->type = backend->type; surface->ref_count = 1; surface->status = CAIRO_STATUS_SUCCESS; diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 5a2c92fff..a5b02c9b8 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -1221,6 +1221,7 @@ _cairo_svg_surface_get_font_options (void *abstract_surface, static const cairo_surface_backend_t cairo_svg_surface_backend = { + CAIRO_SURFACE_TYPE_SVG, _cairo_svg_surface_create_similar, _cairo_svg_surface_finish, NULL, /* acquire_source_image */ diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index b1811a134..9dacd1d37 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -1030,6 +1030,7 @@ _cairo_surface_is_win32 (cairo_surface_t *surface) } static const cairo_surface_backend_t cairo_win32_surface_backend = { + CAIRO_SURFACE_TYPE_WIN32, _cairo_win32_surface_create_similar, _cairo_win32_surface_finish, _cairo_win32_surface_acquire_source_image, diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index faa207c0d..78eafc0fa 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -1025,6 +1025,7 @@ _cairo_xcb_surface_get_extents (void *abstract_surface, } static const cairo_surface_backend_t cairo_xcb_surface_backend = { + CAIRO_SURFACE_TYPE_XCB, _cairo_xcb_surface_create_similar, _cairo_xcb_surface_finish, _cairo_xcb_surface_acquire_source_image, diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 1ce7e890b..dc7d394e1 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1675,6 +1675,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font); static const cairo_surface_backend_t cairo_xlib_surface_backend = { + CAIRO_SURFACE_TYPE_XLIB, _cairo_xlib_surface_create_similar, _cairo_xlib_surface_finish, _cairo_xlib_surface_acquire_source_image, diff --git a/src/cairoint.h b/src/cairoint.h index a1978a90d..124612346 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -256,6 +256,11 @@ typedef enum cairo_int_status { CAIRO_INT_STATUS_CACHE_EMPTY } cairo_int_status_t; +typedef enum cairo_internal_surface_type { + CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000, + CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED +} cairo_internal_surface_type_t; + typedef enum cairo_direction { CAIRO_DIRECTION_FORWARD, CAIRO_DIRECTION_REVERSE @@ -604,6 +609,8 @@ typedef struct _cairo_stroke_style { } cairo_stroke_style_t; struct _cairo_surface_backend { + cairo_surface_type_t type; + cairo_surface_t * (*create_similar) (void *surface, cairo_content_t content, @@ -834,6 +841,11 @@ typedef struct _cairo_format_masks { struct _cairo_surface { const cairo_surface_backend_t *backend; + /* We allow surfaces to override the backend->type by shoving something + * else into surface->type. This is for "wrapper" surfaces that want to + * hide their internal type from the user-level API. */ + cairo_surface_type_t type; + unsigned int ref_count; cairo_status_t status; cairo_bool_t finished; From 5797f814852bb4f6ef559890640b8cd24ec5fa45 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 23:12:43 -0800 Subject: [PATCH 029/155] Implement cairo_pattern_get_type --- src/cairo-pattern.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 27ede9a64..a9628a3c9 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -524,6 +524,12 @@ cairo_pattern_reference (cairo_pattern_t *pattern) return pattern; } +cairo_pattern_type_t +cairo_pattern_get_type (cairo_pattern_t *pattern) +{ + return pattern->type; +} + /** * cairo_pattern_status: * @pattern: a #cairo_pattern_t From cd84e2ab32fe4648f9d172cdefe08798336938d2 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 27 Feb 2006 23:15:45 -0800 Subject: [PATCH 030/155] Add documentation for cairo_font_face_get_type, cairo_scaled_font_get_type, cairo_surface_get_type, and cairo_pattern_get_type. --- src/cairo-font.c | 6 ++++++ src/cairo-pattern.c | 6 ++++++ src/cairo-scaled-font.c | 6 ++++++ src/cairo-surface.c | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/src/cairo-font.c b/src/cairo-font.c index bb184c48d..65124803d 100644 --- a/src/cairo-font.c +++ b/src/cairo-font.c @@ -130,6 +130,12 @@ cairo_font_face_destroy (cairo_font_face_t *font_face) free (font_face); } +/** + * cairo_font_face_get_type: + * @font_face: a #cairo_font_face_t + * + * Return value: The type of @font_face. See #cairo_font_type_t. + **/ cairo_font_type_t cairo_font_face_get_type (cairo_font_face_t *font_face) { diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index a9628a3c9..8aa296988 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -524,6 +524,12 @@ cairo_pattern_reference (cairo_pattern_t *pattern) return pattern; } +/** + * cairo_pattern_get_type: + * @pattern: a #cairo_pattern_t + * + * Return value: The type of @pattern. See #cairo_pattern_type_t. + **/ cairo_pattern_type_t cairo_pattern_get_type (cairo_pattern_t *pattern) { diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 46e1caccf..a0469046d 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -118,6 +118,12 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, _cairo_error (status); } +/** + * cairo_scaled_font_get_type: + * @scaled_font: a #cairo_scaled_font_t + * + * Return value: The type of @scaled_font. See #cairo_font_type_t. + **/ cairo_font_type_t cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font) { diff --git a/src/cairo-surface.c b/src/cairo-surface.c index a317e5b64..b1a36df90 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -121,6 +121,12 @@ _cairo_surface_set_error (cairo_surface_t *surface, _cairo_error (status); } +/** + * cairo_surface_get_type: + * @surface: a #cairo_surface_t + * + * Return value: The type of @surface. See #cairo_surface_type_t. + **/ cairo_surface_type_t cairo_surface_get_type (cairo_surface_t *surface) { From 1dd6e417c10c90894c87565d4f7fa3f63e97f212 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Feb 2006 00:55:27 -0800 Subject: [PATCH 031/155] Add testing for cairo_surface_get_type. All test targets now list an expected cairo_surface_type_t. Add notes on current limitations of PDF/PS/meta-surface support that causes CAIRO_CONTENT_COLOR similar surfaces of PDF and PS surfaces to be returned as image surfaces. Add cairo_internal_surface_type_t for the meta, paginated, and various test surfaces. --- src/cairo-paginated-surface.c | 20 ++++++- src/cairoint.h | 6 +- src/test-fallback-surface.c | 1 + src/test-meta-surface.c | 1 + test/cairo-test.c | 107 +++++++++++++++++++++++++--------- 5 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 4bb857265..acfe44ad3 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -97,6 +97,24 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend; static cairo_int_status_t _cairo_paginated_surface_show_page (void *abstract_surface); +/* XXX: This would seem the natural thing to do here. But currently, + * PDF and PS surfaces do not yet work as source surfaces. So instead, + * we don't implement create_similar for the paginate_surface which + * means that any create_similar() call on a paginated_surfacae will + * result in a new image surface. */ +#if 0 +static cairo_surface_t * +_cairo_paginated_surface_create_similar (void *abstract_surface, + cairo_content_t content, + int width, + int height) +{ + cairo_paginated_surface_t *surface = abstract_surface; + return cairo_surface_create_similar (surface->target, content, + width, height); +} +#endif + cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, @@ -386,7 +404,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other) const cairo_surface_backend_t cairo_paginated_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, - NULL, /* create_similar */ + NULL, /* create_similar --- see note for _cairo_paginated_surface_create_similar */ _cairo_paginated_surface_finish, _cairo_paginated_surface_acquire_source_image, _cairo_paginated_surface_release_source_image, diff --git a/src/cairoint.h b/src/cairoint.h index 124612346..8db52ae00 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -258,7 +258,10 @@ typedef enum cairo_int_status { typedef enum cairo_internal_surface_type { CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000, - CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED + CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED } cairo_internal_surface_type_t; typedef enum cairo_direction { @@ -2157,7 +2160,6 @@ cairo_private int _cairo_dtostr (char *buffer, size_t size, double d); /* Avoid unnecessary PLT entries. */ - slim_hidden_proto(cairo_get_current_point) slim_hidden_proto(cairo_fill_preserve) slim_hidden_proto(cairo_clip_preserve) diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c index fe0cc6fb5..cb8fd92a0 100644 --- a/src/test-fallback-surface.c +++ b/src/test-fallback-surface.c @@ -175,6 +175,7 @@ _test_fallback_surface_get_extents (void *abstract_surface, } const cairo_surface_backend_t test_fallback_surface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, _test_fallback_surface_create_similar, _test_fallback_surface_finish, _test_fallback_surface_acquire_source_image, diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c index bdabf31d3..6d36fcab2 100644 --- a/src/test-meta-surface.c +++ b/src/test-meta-surface.c @@ -296,6 +296,7 @@ _test_meta_surface_snapshot (void *abstract_other) } const cairo_surface_backend_t test_meta_surface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, NULL, /* create_similar */ _test_meta_surface_finish, _test_meta_surface_acquire_source_image, diff --git a/test/cairo-test.c b/test/cairo-test.c index 557ccb6fd..d782a92f4 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -47,6 +47,20 @@ #include "write-png.h" #include "xmalloc.h" +/* This is copied from cairoint.h. That makes it painful to keep in + * sync, but the slim stuff makes cairoint.h "hard" to include when + * not actually building the cairo library itself. Fortunately, since + * we're checking all these values, we do have a safeguard for keeping + * them in sync. + */ +typedef enum cairo_internal_surface_type { + CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000, + CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, + CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED +} cairo_internal_surface_type_t; + #ifdef _MSC_VER #define vsnprintf _vsnprintf #define access _access @@ -163,6 +177,7 @@ typedef void typedef struct _cairo_test_target { const char *name; + cairo_surface_type_t expected_type; cairo_content_t content; cairo_test_create_target_surface_t create_target_surface; cairo_test_write_to_png_t write_to_png; @@ -1387,6 +1402,13 @@ cairo_test_for_target (cairo_test_t *test, goto UNWIND_STRINGS; } + if (cairo_surface_get_type (surface) != target->expected_type) { + cairo_test_log ("Error: Created surface is of type %d (expected %d)\n", + cairo_surface_get_type (surface), target->expected_type); + ret = CAIRO_TEST_FAILURE; + goto UNWIND_SURFACE; + } + cr = cairo_create (surface); /* Clear to transparent (or black) depending on whether the target @@ -1436,6 +1458,7 @@ cairo_test_for_target (cairo_test_t *test, UNWIND_CAIRO: cairo_destroy (cr); +UNWIND_SURFACE: cairo_surface_destroy (surface); cairo_debug_reset_static_data (); @@ -1461,102 +1484,128 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, cairo_test_target_t **targets_to_test; cairo_test_target_t targets[] = { - { "image", CAIRO_CONTENT_COLOR_ALPHA, + { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA, create_image_surface, cairo_surface_write_to_png, NULL}, - { "image", CAIRO_CONTENT_COLOR, + { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, create_image_surface, cairo_surface_write_to_png, NULL}, #ifdef CAIRO_HAS_TEST_SURFACES - { "test-fallback", CAIRO_CONTENT_COLOR_ALPHA, + { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, + CAIRO_CONTENT_COLOR_ALPHA, create_test_fallback_surface, cairo_surface_write_to_png, NULL }, - { "test-fallback", CAIRO_CONTENT_COLOR, + { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, + CAIRO_CONTENT_COLOR, create_test_fallback_surface, cairo_surface_write_to_png, NULL }, - { "test-meta", CAIRO_CONTENT_COLOR_ALPHA, + { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, + CAIRO_CONTENT_COLOR_ALPHA, create_test_meta_surface, cairo_surface_write_to_png, NULL }, - { "test-meta", CAIRO_CONTENT_COLOR, + { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, + CAIRO_CONTENT_COLOR, create_test_meta_surface, cairo_surface_write_to_png, NULL }, - { "test-paginated", CAIRO_CONTENT_COLOR_ALPHA, + { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE, + CAIRO_CONTENT_COLOR_ALPHA, create_test_paginated_surface, test_paginated_write_to_png, cleanup_test_paginated }, - { "test-paginated", CAIRO_CONTENT_COLOR, + { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE, + CAIRO_CONTENT_COLOR, create_test_paginated_surface, test_paginated_write_to_png, cleanup_test_paginated }, #endif #ifdef CAIRO_HAS_GLITZ_SURFACE #if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE - { "glitz-glx", CAIRO_CONTENT_COLOR_ALPHA, + { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA, create_cairo_glitz_glx_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_glx }, - { "glitz-glx", CAIRO_CONTENT_COLOR, + { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, create_cairo_glitz_glx_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_glx }, #endif #if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE - { "glitz-agl", CAIRO_CONTENT_COLOR_ALPHA, + { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, create_cairo_glitz_agl_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_agl }, - { "glitz-agl", CAIRO_CONTENT_COLOR, + { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, create_cairo_glitz_agl_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_agl }, #endif #if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE - { "glitz-wgl", CAIRO_CONTENT_COLOR_ALPHA, + { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, create_cairo_glitz_wgl_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_wgl }, - { "glitz-wgl", CAIRO_CONTENT_COLOR, + { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, create_cairo_glitz_wgl_surface, cairo_surface_write_to_png, cleanup_cairo_glitz_wgl }, #endif #endif /* CAIRO_HAS_GLITZ_SURFACE */ #if 0 && CAIRO_HAS_QUARTZ_SURFACE - { "quartz", CAIRO_CONTENT_COLOR, + { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR, create_quartz_surface, cairo_surface_write_to_png, cleanup_quartz }, #endif #if CAIRO_HAS_WIN32_SURFACE - { "win32", CAIRO_CONTENT_COLOR, + { "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, create_win32_surface, cairo_surface_write_to_png, cleanup_win32 }, #endif #if CAIRO_HAS_XCB_SURFACE - { "xcb", CAIRO_CONTENT_COLOR_ALPHA, + { "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA, create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb}, #endif #if CAIRO_HAS_XLIB_SURFACE - { "xlib", CAIRO_CONTENT_COLOR_ALPHA, + { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib}, - { "xlib", CAIRO_CONTENT_COLOR, + { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib}, #endif #if CAIRO_HAS_PS_SURFACE - { "ps", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, + { "ps", CAIRO_SURFACE_TYPE_PS, + CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, create_ps_surface, ps_surface_write_to_png, cleanup_ps }, - { "ps", CAIRO_CONTENT_COLOR, + + /* XXX: We expect type image here only due to a limitation in + * the current PS/meta-surface code. A PS surface is + * "naturally" COLOR_ALPHA, so the COLOR-only variant goes + * through create_similar in create_ps_surface which results + * in the similar surface being used as a source. We do not yet + * have source support for PS/meta-surfaces, so the + * create_similar path for all paginated surfaces currently + * returns an image surface.*/ + { "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, create_ps_surface, ps_surface_write_to_png, cleanup_ps }, #endif #if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE - { "pdf", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, + { "pdf", CAIRO_SURFACE_TYPE_PDF, + CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf }, - { "pdf", CAIRO_CONTENT_COLOR, + + /* XXX: We expect type image here only due to a limitation in + * the current PDF/meta-surface code. A PDF surface is + * "naturally" COLOR_ALPHA, so the COLOR-only variant goes + * through create_similar in create_pdf_surface which results + * in the similar surface being used as a source. We do not yet + * have source support for PDF/meta-surfaces, so the + * create_similar path for all paginated surfaces currently + * returns an image surface.*/ + { "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf }, #endif #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE - { "svg", CAIRO_CONTENT_COLOR_ALPHA, + { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, create_svg_surface, svg_surface_write_to_png, cleanup_svg }, #endif #if CAIRO_HAS_BEOS_SURFACE - { "beos", CAIRO_CONTENT_COLOR, + { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, create_beos_surface, cairo_surface_write_to_png, cleanup_beos}, - { "beos_bitmap", CAIRO_CONTENT_COLOR, + { "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap}, - { "beos_bitmap", CAIRO_CONTENT_COLOR_ALPHA, + { "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA, create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap}, #endif #if CAIRO_HAS_DIRECTFB_SURFACE - { "directfb", CAIRO_CONTENT_COLOR, + { "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR, create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb}, - { "directfb_bitmap", CAIRO_CONTENT_COLOR_ALPHA, + { "directfb_bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA, create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb}, #endif }; From f9534c856a71b0f56a1e5bc58141b7bc192a27e8 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Feb 2006 01:30:58 -0800 Subject: [PATCH 032/155] test/pattern-get-type: Add new test case for cairo_pattern_get_type. --- test/.gitignore | 1 + test/Makefile.am | 2 ++ test/pattern-get-type.c | 74 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 test/pattern-get-type.c diff --git a/test/.gitignore b/test/.gitignore index 5173349b2..30554c8f1 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -43,6 +43,7 @@ operator-source paint paint-with-alpha path-data +pattern-get-type pdf2png png-flatten svg2png diff --git a/test/Makefile.am b/test/Makefile.am index 0da8b5a74..0d866365f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -35,6 +35,7 @@ operator-source \ paint \ paint-with-alpha \ path-data \ +pattern-get-type \ pixman-rotate \ rectangle-rounding-error \ scale-source-surface-paint \ @@ -317,6 +318,7 @@ operator_source_LDADD = $(LDADDS) paint_LDADD = $(LDADDS) paint_with_alpha_LDADD = $(LDADDS) path_data_LDADD = $(LDADDS) +pattern_get_type_LDADD = $(LDADDS) svg_surface_LDADD = $(LDADDS) svg_clip_LDADD = $(LDADDS) pixman_rotate_LDADD = $(LDADDS) diff --git a/test/pattern-get-type.c b/test/pattern-get-type.c new file mode 100644 index 000000000..0e8fe255d --- /dev/null +++ b/test/pattern-get-type.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * 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 + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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. + * + * Author: Carl D. Worth + */ + +#include "cairo-test.h" + +int +main (void) +{ + cairo_surface_t *surface; + cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial; + + cairo_test_init ("pattern-get-type"); + + cairo_test_log ("Creating patterns of all types\n"); + + solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2); + solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6); + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + 1, 1); + surface_pattern = cairo_pattern_create_for_surface (surface); + linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0); + radial = cairo_pattern_create_radial (10.0, 10.0, 0.1, + 10.0, 10.0, 1.0); + + cairo_test_log ("Verifying return values of cairo_pattern_get_type\n"); + + if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID) + return CAIRO_TEST_FAILURE; + + if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID) + return CAIRO_TEST_FAILURE; + + if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE) + return CAIRO_TEST_FAILURE; + + if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR) + return CAIRO_TEST_FAILURE; + + if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL) + return CAIRO_TEST_FAILURE; + + cairo_test_log ("Cleaning up\n"); + + cairo_pattern_destroy (solid_rgb); + cairo_pattern_destroy (solid_rgba); + cairo_pattern_destroy (surface_pattern); + cairo_surface_destroy (surface); + cairo_pattern_destroy (linear); + cairo_pattern_destroy (radial); + + return CAIRO_TEST_SUCCESS; +} From bd2136a23f8a3d5f6a1306d18499fdcfc1e87f48 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Feb 2006 01:31:15 -0800 Subject: [PATCH 033/155] Correct copyright date --- test/pattern-get-type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pattern-get-type.c b/test/pattern-get-type.c index 0e8fe255d..a6aba03aa 100644 --- a/test/pattern-get-type.c +++ b/test/pattern-get-type.c @@ -1,5 +1,5 @@ /* - * Copyright © 2005 Red Hat, Inc. + * Copyright © 2006 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without From 210dd59a7441424f71658ca248f6657482c74c7e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Feb 2006 02:30:27 -0800 Subject: [PATCH 034/155] Add some basic testing of cairo_font_face_get_type and cairo_scaled_font_get_type. --- test/.gitignore | 1 + test/Makefile.am | 2 + test/font-face-get-type.c | 64 +++++++++++++++++++++++++++++++ test/ft-font-create-for-ft-face.c | 14 +++++++ 4 files changed, 81 insertions(+) create mode 100644 test/font-face-get-type.c diff --git a/test/.gitignore b/test/.gitignore index 30554c8f1..65741ca63 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -24,6 +24,7 @@ fill-and-stroke fill-rule filter-nearest-offset ft-font-create-for-ft-face +font-face-get-type get-and-set gradient-alpha imagediff diff --git a/test/Makefile.am b/test/Makefile.am index 0d866365f..8a67fc53e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -20,6 +20,7 @@ extend-reflect \ fill-and-stroke \ fill-rule \ filter-nearest-offset \ +font-face-get-type \ get-and-set \ gradient-alpha \ leaky-polygon \ @@ -300,6 +301,7 @@ dash_offset_negative_LDADD = $(LDADDS) extend_reflect_LDADD = $(LDADDS) fill_and_stroke_LDADD = $(LDADDS) fill_rule_LDADD = $(LDADDS) +font_face_get_type_LDADD = $(LDADDS) filter_nearest_offset_LDADD = $(LDADDS) ft_font_create_for_ft_face_LDADD = $(LDADDS) get_and_set_LDADD = $(LDADDS) diff --git a/test/font-face-get-type.c b/test/font-face-get-type.c new file mode 100644 index 000000000..c21d5c238 --- /dev/null +++ b/test/font-face-get-type.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2006 Red Hat, Inc. + * + * 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 + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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. + * + * Author: Carl D. Worth + */ + +#include "cairo-test.h" + +int +main (void) +{ + cairo_surface_t *surface; + cairo_t *cr; + cairo_font_face_t *font_face; + + cairo_test_init ("font-face-get-type"); + + cairo_test_log ("Creating cairo context and obtaining a font face\n"); + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); + cr = cairo_create (surface); + + cairo_select_font_face (cr, "Bitstream Vera Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + + font_face = cairo_get_font_face (cr); + + cairo_test_log ("Testing return value of cairo_font_face_get_type\n"); + + if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_TOY) { + cairo_test_log ("Unexpected value %d from cairo_font_face_get_type (expected %d)\n", + cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_TOY); + return CAIRO_TEST_FAILURE; + } + + cairo_destroy (cr); + cairo_surface_destroy (surface); + + return CAIRO_TEST_SUCCESS; +} + + + + diff --git a/test/ft-font-create-for-ft-face.c b/test/ft-font-create-for-ft-face.c index bf668b9d8..0bb3b8c0d 100644 --- a/test/ft-font-create-for-ft-face.c +++ b/test/ft-font-create-for-ft-face.c @@ -64,6 +64,13 @@ draw (cairo_t *cr, int width, int height) font_face = cairo_ft_font_face_create_for_pattern (resolved); + if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) { + cairo_test_log ("Unexpected value from cairo_font_face_get_type: %d (expected %d)\n", + cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT); + cairo_font_face_destroy (font_face); + return CAIRO_TEST_FAILURE; + } + cairo_matrix_init_identity (&font_matrix); cairo_get_matrix (cr, &ctm); @@ -82,6 +89,13 @@ draw (cairo_t *cr, int width, int height) FcPatternDestroy (pattern); FcPatternDestroy (resolved); + if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_FT) { + cairo_test_log ("Unexpected value from cairo_scaled_font_get_type: %d (expected %d)\n", + cairo_scaled_font_get_type (scaled_font), CAIRO_FONT_TYPE_FT); + cairo_scaled_font_destroy (scaled_font); + return CAIRO_TEST_FAILURE; + } + if (!ft_face) { cairo_test_log ("Failed to get an ft_face with cairo_ft_scaled_font_lock_face\n"); cairo_scaled_font_destroy (scaled_font); From 49b4fe10d0acdf6b9776d2908e98f2f0c596fbe5 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 28 Feb 2006 16:21:46 +0100 Subject: [PATCH 035/155] Remove ft-font's usage of device offset surface fields for storing bearings cairo-ft-font was being naughty and storing glyph bearings in the surface device_[xy]_offset fields -- this had no effect previously, because _cairo_surface_composite ignored those fields, but once it starts handling device offsets itself, this causes ft text rendering to break. --- src/cairo-ft-font.c | 22 +--------------------- src/cairo-scaled-font.c | 6 +++--- src/cairo-xlib-surface.c | 4 ++-- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 092838ab4..92b60c73b 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -1021,14 +1021,6 @@ _render_glyph_outline (FT_Face face, return status; } - /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinate of the control box needs to be negated. - */ - - (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0); - (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0); - return CAIRO_STATUS_SUCCESS; } @@ -1067,19 +1059,7 @@ _render_glyph_bitmap (FT_Face face, if (error) return CAIRO_STATUS_NO_MEMORY; - status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); - if (status) - return status; - - /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinate of the control box needs to be negated. - */ - - (*surface)->base.device_x_offset = glyphslot->bitmap_left; - (*surface)->base.device_y_offset = -glyphslot->bitmap_top; - - return status; + return _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); } #if 0 diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index a0469046d..cb0171ba5 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -858,7 +858,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, * they are implemented in terms of other operators in cairo-gstate.c */ assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - + if (scaled_font->status) return scaled_font->status; @@ -920,10 +920,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, /* round glyph locations to the nearest pixel */ x = (int) floor (glyphs[i].x + - glyph_surface->base.device_x_offset + + scaled_glyph->metrics.x_bearing + 0.5); y = (int) floor (glyphs[i].y + - glyph_surface->base.device_y_offset + + scaled_glyph->metrics.y_bearing + 0.5); _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index dc7d394e1..a62afed84 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -2119,8 +2119,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy, * sitting around for x and y. */ - glyph_info.x = -(int) glyph_surface->base.device_x_offset; - glyph_info.y = -(int) glyph_surface->base.device_y_offset; + glyph_info.x = -(int) floor(scaled_glyph->metrics.x_bearing + 0.5); + glyph_info.y = -(int) floor(scaled_glyph->metrics.y_bearing + 0.5); glyph_info.width = glyph_surface->width; glyph_info.height = glyph_surface->height; glyph_info.xOff = 0; From ef1c5c3961c2dff1a48606a45a6c9877924e5f15 Mon Sep 17 00:00:00 2001 From: manu Date: Tue, 28 Feb 2006 22:52:45 +0100 Subject: [PATCH 036/155] Git test --- src/cairo-svg-surface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index a5b02c9b8..e31a40b77 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -36,6 +36,8 @@ * Emmanuel Pacaud */ +/* test line */ + #include "cairoint.h" #include "cairo-svg.h" #include "cairo-path-fixed-private.h" From 0341305fd2f303a23d10b448ac385a981b8b35fe Mon Sep 17 00:00:00 2001 From: manu Date: Tue, 28 Feb 2006 23:33:00 +0100 Subject: [PATCH 037/155] Revert "Git test" This reverts ef1c5c3961c2dff1a48606a45a6c9877924e5f15 commit. --- src/cairo-svg-surface.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index e31a40b77..a5b02c9b8 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -36,8 +36,6 @@ * Emmanuel Pacaud */ -/* test line */ - #include "cairoint.h" #include "cairo-svg.h" #include "cairo-path-fixed-private.h" From a69b3f211654d1f221859f8e7f9608f8030e1ac4 Mon Sep 17 00:00:00 2001 From: manu Date: Tue, 28 Feb 2006 23:44:01 +0100 Subject: [PATCH 038/155] s/CAIRO_PATTERN/CAIRO_PATTERN_TYPE/ --- src/cairo-svg-surface.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index a5b02c9b8..2ad21372a 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -762,19 +762,19 @@ emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern, xmlBufferPtr style, int is_stroke) { switch (pattern->type) { - case CAIRO_PATTERN_SOLID: + case CAIRO_PATTERN_TYPE_SOLID: emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, style, is_stroke); break; - case CAIRO_PATTERN_SURFACE: + case CAIRO_PATTERN_TYPE_SURFACE: emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, style, is_stroke); break; - case CAIRO_PATTERN_LINEAR: + case CAIRO_PATTERN_TYPE_LINEAR: emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, style, is_stroke); break; - case CAIRO_PATTERN_RADIAL: + case CAIRO_PATTERN_TYPE_RADIAL: emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, style, is_stroke); break; } @@ -950,7 +950,7 @@ emit_paint (xmlNodePtr node, xmlBufferPtr style; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - if (source->type == CAIRO_PATTERN_SURFACE) + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) return emit_composite_pattern (node, (cairo_surface_pattern_t *) source, NULL, NULL, FALSE); From 566bb18dfee2daaaaf86e7a22e8a7883e81efd97 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Wed, 1 Mar 2006 00:06:43 +0100 Subject: [PATCH 039/155] Updating BeOS surface per the get_type changes --- src/cairo-beos-surface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp index b6448fa69..c952e018b 100644 --- a/src/cairo-beos-surface.cpp +++ b/src/cairo-beos-surface.cpp @@ -777,6 +777,7 @@ _cairo_beos_surface_get_extents (void *abstract_surface, } static const struct _cairo_surface_backend cairo_beos_surface_backend = { + CAIRO_SURFACE_TYPE_BEOS, NULL, /* create_similar */ _cairo_beos_surface_finish, _cairo_beos_surface_acquire_source_image, From d985a9d6696f1ed653a48d95bc401ede3ba86d5f Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Wed, 1 Mar 2006 00:40:35 +0100 Subject: [PATCH 040/155] Fixing BeOS surface part II --- src/cairo-beos-surface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp index c952e018b..5cd427761 100644 --- a/src/cairo-beos-surface.cpp +++ b/src/cairo-beos-surface.cpp @@ -598,7 +598,7 @@ _cairo_beos_composite (cairo_operator_t op, return CAIRO_INT_STATUS_UNSUPPORTED; // XXX should eventually support the others - if (src->type != CAIRO_PATTERN_SURFACE || + if (src->type != CAIRO_PATTERN_TYPE_SURFACE || src->extend != CAIRO_EXTEND_NONE) { return CAIRO_INT_STATUS_UNSUPPORTED; From e2855502f2f2e701b96a2a7eee4cda8c374bcbb9 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Feb 2006 14:10:36 -0800 Subject: [PATCH 041/155] Fix last piece of merge resolution missing from previous commit --- src/cairo-ps-surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 951e1d69c..f35f82391 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1339,7 +1339,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_int_status_t status; cairo_path_fixed_t *path; - if (surface->mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { if (!pattern_operation_supported (op, source)) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS; From 8176c93bc481414c1584bf4721ac1680ed827d97 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 1 Mar 2006 11:26:30 +0100 Subject: [PATCH 042/155] Revert "Remove ft-font's usage of device offset surface fields for storing bearings" Bogus fix; misunderstood the relationship between the font bearings and the computed device offsets. Real fix on my device offsets branch. This reverts 49b4fe10d0acdf6b9776d2908e98f2f0c596fbe5 commit. --- src/cairo-ft-font.c | 22 +++++++++++++++++++++- src/cairo-scaled-font.c | 6 +++--- src/cairo-xlib-surface.c | 4 ++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 92b60c73b..092838ab4 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -1021,6 +1021,14 @@ _render_glyph_outline (FT_Face face, return status; } + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinate of the control box needs to be negated. + */ + + (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0); + (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0); + return CAIRO_STATUS_SUCCESS; } @@ -1059,7 +1067,19 @@ _render_glyph_bitmap (FT_Face face, if (error) return CAIRO_STATUS_NO_MEMORY; - return _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); + status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); + if (status) + return status; + + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinate of the control box needs to be negated. + */ + + (*surface)->base.device_x_offset = glyphslot->bitmap_left; + (*surface)->base.device_y_offset = -glyphslot->bitmap_top; + + return status; } #if 0 diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index cb0171ba5..a0469046d 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -858,7 +858,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, * they are implemented in terms of other operators in cairo-gstate.c */ assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - + if (scaled_font->status) return scaled_font->status; @@ -920,10 +920,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, /* round glyph locations to the nearest pixel */ x = (int) floor (glyphs[i].x + - scaled_glyph->metrics.x_bearing + + glyph_surface->base.device_x_offset + 0.5); y = (int) floor (glyphs[i].y + - scaled_glyph->metrics.y_bearing + + glyph_surface->base.device_y_offset + 0.5); _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index a62afed84..dc7d394e1 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -2119,8 +2119,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy, * sitting around for x and y. */ - glyph_info.x = -(int) floor(scaled_glyph->metrics.x_bearing + 0.5); - glyph_info.y = -(int) floor(scaled_glyph->metrics.y_bearing + 0.5); + glyph_info.x = -(int) glyph_surface->base.device_x_offset; + glyph_info.y = -(int) glyph_surface->base.device_y_offset; glyph_info.width = glyph_surface->width; glyph_info.height = glyph_surface->height; glyph_info.xOff = 0; From 3490ed989672eaf2c08468ba81e3376fa362e41f Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Wed, 1 Mar 2006 19:16:01 +0100 Subject: [PATCH 043/155] Remove trailing comma in enumeration This fixes a gcc -pedantic warning and compilation with the xlc compiler. --- src/cairo-meta-surface-private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h index e57150904..eafe3f441 100644 --- a/src/cairo-meta-surface-private.h +++ b/src/cairo-meta-surface-private.h @@ -53,7 +53,7 @@ typedef enum { * fallbacks should never get triggered). So the plan is to * eliminate as many of these as possible. */ - CAIRO_COMMAND_INTERSECT_CLIP_PATH, + CAIRO_COMMAND_INTERSECT_CLIP_PATH } cairo_command_type_t; From 62812b25c7f0c11aa6c973b722fa8e1bd088d4b8 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Thu, 2 Mar 2006 14:54:37 +0100 Subject: [PATCH 044/155] Fix gcc 4.0 signedness warnings --- src/cairo-svg-surface.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 2ad21372a..76e7c6a77 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -263,22 +263,22 @@ emit_transform (xmlNodePtr node, xmlBufferCat (matrix_buffer, CC2XML ("matrix(")); _cairo_dtostr (buffer, sizeof buffer, matrix->xx); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ","); + xmlBufferCat (matrix_buffer, CC2XML (",")); _cairo_dtostr (buffer, sizeof buffer, matrix->yx); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ","); + xmlBufferCat (matrix_buffer, CC2XML (",")); _cairo_dtostr (buffer, sizeof buffer, matrix->xy); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ","); + xmlBufferCat (matrix_buffer, CC2XML (",")); _cairo_dtostr (buffer, sizeof buffer, matrix->yy); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ","); + xmlBufferCat (matrix_buffer, CC2XML (",")); _cairo_dtostr (buffer, sizeof buffer, matrix->x0); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ","); + xmlBufferCat (matrix_buffer, CC2XML(",")); _cairo_dtostr (buffer, sizeof buffer, matrix->y0); xmlBufferCat (matrix_buffer, C2XML (buffer)); - xmlBufferCat (matrix_buffer, ")"); + xmlBufferCat (matrix_buffer, CC2XML (")")); xmlSetProp (node, CC2XML (attribute_str), C2XML (xmlBufferContent (matrix_buffer))); xmlBufferFree (matrix_buffer); } @@ -292,7 +292,7 @@ typedef struct { unsigned int trailing; } base64_write_closure_t; -static unsigned char const *base64_table = +static char const *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static cairo_status_t @@ -325,7 +325,7 @@ base64_write_func (void *closure, info->count++; if (info->count >= 18) { info->count = 0; - xmlBufferCat (info->buffer, "\r\n"); + xmlBufferCat (info->buffer, CC2XML ("\r\n")); } dst[0] = base64_table[src[0] >> 2]; dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4]; @@ -898,9 +898,9 @@ _cairo_svg_surface_fill (void *abstract_surface, style = xmlBufferCreate (); emit_pattern (surface, source, style, 0); - xmlBufferCat (style, " stroke: none;"); - xmlBufferCat (style, " fill-rule: "); - xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd;" : "nonzero;"); + xmlBufferCat (style, CC2XML (" stroke: none;")); + xmlBufferCat (style, CC2XML (" fill-rule: ")); + xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? CC2XML("evenodd;") : CC2XML ("nonzero;")); status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, @@ -957,7 +957,7 @@ emit_paint (xmlNodePtr node, style = xmlBufferCreate (); emit_pattern (surface, source, style, 0); - xmlBufferCat (style, " stroke: none;"); + xmlBufferCat (style, CC2XML (" stroke: none;")); child = xmlNewChild (node, NULL, CC2XML ("rect"), NULL); xmlSetProp (child, CC2XML ("x"), CC2XML ("0")); @@ -1076,21 +1076,21 @@ _cairo_svg_surface_stroke (void *abstract_dst, xmlBufferCat (style, CC2XML (" stroke-dasharray: ")); for (i = 0; i < stroke_style->num_dashes; i++) { if (i != 0) - xmlBufferCat (style, ","); + xmlBufferCat (style, CC2XML (",")); /* FIXME: Is is really what we want ? */ rx = ry = stroke_style->dash[i]; cairo_matrix_transform_distance (ctm, &rx, &ry); _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0)); xmlBufferCat (style, C2XML (buffer)); } - xmlBufferCat (style, ";"); + xmlBufferCat (style, CC2XML (";")); if (stroke_style->dash_offset != 0.0) { xmlBufferCat (style, CC2XML (" stroke-dashoffset: ")); rx = ry = stroke_style->dash_offset; cairo_matrix_transform_distance (ctm, &rx, &ry); _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0)); xmlBufferCat (style, C2XML (buffer)); - xmlBufferCat (style, ";"); + xmlBufferCat (style, CC2XML (";")); } } From 34a4ad1e5bca8db34933718db245a232ebe30ce2 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 2 Mar 2006 10:32:38 -0800 Subject: [PATCH 045/155] test/show-glyphs-many: New test case to demonstrate bug #5528 This demonstrates an Xlib crash when rendering many glyphs. See: _XError from XRenderCompositeText8 https://bugs.freedesktop.org/show_bug.cgi?id=5528 for more details. --- test/.gitignore | 1 + test/Makefile.am | 2 + test/show-glyphs-many-ref.png | Bin 0 -> 118 bytes test/show-glyphs-many-rgb24-ref.png | Bin 0 -> 115 bytes test/show-glyphs-many.c | 127 ++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 test/show-glyphs-many-ref.png create mode 100644 test/show-glyphs-many-rgb24-ref.png create mode 100644 test/show-glyphs-many.c diff --git a/test/.gitignore b/test/.gitignore index 65741ca63..8a1a8acf0 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -61,6 +61,7 @@ select-font-no-show-text self-copy self-intersecting set-source +show-glyphs-many show-text-current-point source-clip source-surface-scale-paint diff --git a/test/Makefile.am b/test/Makefile.am index 8a67fc53e..f1fe6f512 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -44,6 +44,7 @@ select-font-no-show-text \ self-copy \ self-intersecting \ set-source \ +show-glyphs-many \ show-text-current-point \ source-clip \ source-surface-scale-paint \ @@ -331,6 +332,7 @@ select_font_no_show_text_LDADD = $(LDADDS) self_copy_LDADD = $(LDADDS) self_intersecting_LDADD = $(LDADDS) set_source_LDADD = $(LDADDS) +show_glyphs_many_LDADD = $(LDADDS) show_text_current_point_LDADD = $(LDADDS) source_clip_LDADD = $(LDADDS) source_surface_scale_paint_LDADD = $(LDADDS) diff --git a/test/show-glyphs-many-ref.png b/test/show-glyphs-many-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..b61c5f7b6a7ed59306efc2dcf201a4335e4054e5 GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRY!3HGPMlP2IQfx`y?k)`fL2$v|<&%LT>?NMQ zuI$&CnS`XQdS-6k2NaUY)lQE6Pf~DL&8`X;$>Kb{;*4g0o5>g My85}Sb4q9e0Da*f>i_@% literal 0 HcmV?d00001 diff --git a/test/show-glyphs-many-rgb24-ref.png b/test/show-glyphs-many-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..450e8e0bb5eb180b7c5e83e16782a552a9bf0e7d GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRY!2~3gtPOmC6kC$Fy9>jA5L~c#`DCC7dx@v7 zEBiHOCLt-So|&8X0fj_8T^vIsrY8US|KFaO??8)pQp;&ZhK20R!oKrXg##5Zc)I$z JtaD0e0sz6V9!UTI literal 0 HcmV?d00001 diff --git a/test/show-glyphs-many.c b/test/show-glyphs-many.c new file mode 100644 index 000000000..3c444114d --- /dev/null +++ b/test/show-glyphs-many.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2006 Red Hat, Inc. + * + * 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 + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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. + * + * Author: Carl D. Worth + */ + +#include "cairo-test.h" + +#include + +/* Bug history + * + * 2006-01-07 Jon Hellan + * + * Jon opened the following bug report: + * + * _XError from XRenderCompositeText8 + * https://bugs.freedesktop.org/show_bug.cgi?id=5528 + * + * 2006-03-02 Carl Worth + * + * I wrote this test case to demonstrate the bug. + * + * Approach: + * + * Draw 65535 glyphs white-on-white all on top of each other. + * + * Rationale: + * + * The number 65535 comes from the original bug report. + * + * I would use cairo_show_text with a long string of 'x's say, + * but then the surface would need to be enormous to contain + * them. A smaller surface could be used, but I fear that at some + * point the off-surface glyph drawing would be optimized away + * and not exercise the bug. + * + * So, to keep the surface size under control, I use + * cairo_show_glyphs which allows me to place the glyphs all on + * top of each other. But, since cairo doesn't provide any + * character-to-glyphs mapping, I can't get a reliable glyph + * index (for character 'x' for example). So I just "guess" a + * glyph index and use white-on-white drawing to ignore the + * result. (I don't care what's drawn---I just want to ensure + * that things don't crash.) + * + * Status: I replicated bug. The largest value of NUM_GLYPHS for + * which I saw success is 21842. + */ + +#define TEXT_SIZE 12 +#define NUM_GLYPHS 65535 + +/* This is the index into the font for what glyph we'll draw. Since we + * don't guarantee we'll get any particular font, we can't relibably + * get any particular glyph. But we don't care what we draw anyway, + * (see discussion of white-on-white drawing above). For what it's + * worth, this appears to be giving me 'M' with Bitstream Vera + * Sans Mono. */ +#define GLYPH_INDEX 48 + +cairo_test_t test = { + "show-glyphs-many", + "Test that cairo_show_glyps works when handed 'many' glyphs", + 9, 11 +}; + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_glyph_t glyphs[NUM_GLYPHS]; + cairo_font_options_t *font_options; + int i; + + /* Initialize our giant array of glyphs. */ + for (i=0; i < NUM_GLYPHS; i++) { + glyphs[i].index = GLYPH_INDEX; + glyphs[i].x = 1.0; + glyphs[i].y = height - 1; + } + + /* Paint white background. */ + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ + cairo_paint (cr); + + cairo_select_font_face (cr, "Bitstream Vera Sans Mono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, TEXT_SIZE); + + font_options = cairo_font_options_create (); + + cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); + + cairo_set_font_options (cr, font_options); + cairo_font_options_destroy (font_options); + + cairo_show_glyphs (cr, glyphs, NUM_GLYPHS); + + return CAIRO_TEST_SUCCESS; +} + +int +main (void) +{ + return cairo_test (&test, draw); +} From 3370cd631858cac0fd3ce33c74db3af40991e6f1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 3 Mar 2006 15:40:58 -0800 Subject: [PATCH 046/155] _cairo_xlib_surface_old_show_glyphs: Break up rendering into chunks to fit into X max request length protocol limits. This fixes bug #5528: _XError from XRenderCompositeText8 https://bugs.freedesktop.org/show_bug.cgi?id=5528 (cherry picked from 7d498ca91279a4e793d704c5b878f070be4c878f commit) --- src/cairo-xlib-surface.c | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index a62afed84..6def99891 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -41,6 +41,7 @@ #include "cairo-xlib-test.h" #include "cairo-xlib-private.h" #include +#include /* Xlib doesn't define a typedef, so define one ourselves */ typedef int (*cairo_xlib_error_func_t) (Display *display, @@ -2404,6 +2405,8 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_int_status_t status; cairo_xlib_surface_t *self = abstract_surface; cairo_xlib_surface_t *src; + const cairo_glyph_t *glyphs_chunk; + int glyphs_remaining, chunk_size, max_chunk_size; composite_operation_t operation; cairo_scaled_glyph_t *scaled_glyph; cairo_xlib_surface_font_private_t *font_private; @@ -2458,23 +2461,41 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, } _cairo_xlib_surface_ensure_dst_picture (self); - /* Call the appropriate sub-function. */ + max_chunk_size = XMaxRequestSize (self->dpy); if (max_index < 256) - status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self, - source_x + attributes.x_offset - dest_x, - source_y + attributes.y_offset - dest_y, - glyphs, num_glyphs); + max_chunk_size -= sz_xRenderCompositeGlyphs8Req; else if (max_index < 65536) - status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self, - source_x + attributes.x_offset - dest_x, - source_y + attributes.y_offset - dest_y, - glyphs, num_glyphs); - else - status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self, - source_x + attributes.x_offset - dest_x, - source_y + attributes.y_offset - dest_y, - glyphs, num_glyphs); + max_chunk_size -= sz_xRenderCompositeGlyphs16Req; + else + max_chunk_size -= sz_xRenderCompositeGlyphs32Req; + max_chunk_size /= sz_xGlyphElt; + + for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs; + glyphs_remaining; + glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) + { + chunk_size = MIN (glyphs_remaining, max_chunk_size); + + /* Call the appropriate sub-function. */ + if (max_index < 256) + status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs_chunk, chunk_size); + else if (max_index < 65536) + status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs_chunk, chunk_size); + else + status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs_chunk, chunk_size); + if (status != CAIRO_STATUS_SUCCESS) + break; + } if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_t extents; From 7563a23921a4d6f9f826a13b42d61f3ba3c31c10 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Sun, 5 Mar 2006 23:49:38 +0100 Subject: [PATCH 047/155] Fix self-copy test --- src/cairo-svg-surface.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 76e7c6a77..b5cee7502 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -88,6 +88,7 @@ struct cairo_svg_surface { cairo_svg_document_t *document; xmlNodePtr xml_node; + xmlNodePtr xml_root_node; unsigned int clip_level; }; @@ -209,10 +210,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, _cairo_dtostr (buffer, sizeof buffer, height); xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer)); - surface->xml_node = xmlNewChild (surface->id == 0 ? - document->xml_node_main : - document->xml_node_defs, - NULL, CC2XML ("g"), NULL); + surface->xml_node = xmlNewNode (NULL, CC2XML ("g")); + surface->xml_root_node = surface->xml_node; snprintf (buffer, sizeof buffer, "surface%d", surface->id); xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer)); @@ -240,14 +239,19 @@ _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; + - if (document->owner == &surface->base) + if (document->owner == &surface->base) { + xmlAddChild (document->xml_node_main, xmlCopyNode (surface->xml_root_node, 1)); status = _cairo_svg_document_finish (document); - else + } else status = CAIRO_STATUS_SUCCESS; _cairo_svg_document_destroy (document); + xmlFreeNode (surface->xml_root_node); + surface->xml_node = NULL; + return status; } @@ -450,13 +454,12 @@ emit_composite_svg_pattern (xmlNodePtr node, cairo_bool_t is_pattern) { cairo_svg_surface_t *surface = (cairo_svg_surface_t *) pattern->surface; + cairo_svg_document_t *document = surface->document; cairo_matrix_t p2u; xmlNodePtr child; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - /* FIXME: self copy is not supported yet */ - if (surface->id == 0) - return NULL; + xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); child = xmlNewChild (node, NULL, CC2XML("use"), NULL); snprintf (buffer, sizeof buffer, "#surface%d", surface->id); @@ -473,6 +476,10 @@ emit_composite_svg_pattern (xmlNodePtr node, if (height != NULL) *height = surface->height; + surface->id = document->surface_id++; + snprintf (buffer, sizeof buffer, "surface%d", surface->id); + xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer)); + return child; } @@ -1167,10 +1174,8 @@ _cairo_svg_surface_intersect_clip_path (void *dst, char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; if (path == NULL) { - while (surface->clip_level > 0) { - surface->xml_node = surface->xml_node->parent; - surface->clip_level--; - } + surface->xml_node = surface->xml_root_node; + surface->clip_level = 0; return CAIRO_STATUS_SUCCESS; } From 1cffb39ff04bbb29bb070e42c51aa1ae6aaf5a4c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 8 Mar 2006 08:16:49 -0800 Subject: [PATCH 048/155] cairo_show_glyphs: Do nothing if num_glyphs == 0 --- src/cairo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cairo.c b/src/cairo.c index 96cd504b7..d0dd4ecfb 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -2155,6 +2155,9 @@ cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) if (cr->status) return; + if (num_glyphs == 0) + return; + cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs); if (cr->status) _cairo_set_error (cr, cr->status); From 92e09ee72fdde9059300b2b63d87e2bbd4286605 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Thu, 9 Mar 2006 08:23:43 -0800 Subject: [PATCH 049/155] Complete the CAIRO_PATTERN_TYPE renaming This fixes compilation of the glitz backend, and also fixes missing renames in win32, atsui, and directfb backends. --- src/cairo-atsui-font.c | 2 +- src/cairo-directfb-surface.c | 6 +++--- src/cairo-glitz-surface.c | 14 +++++++------- src/cairo-win32-surface.c | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index a4c2dc2ad..cab7843a4 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -602,7 +602,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, CGContextSetFontSize(myBitmapContext, 1.0); CGContextSetTextMatrix(myBitmapContext, textTransform); - if (pattern->type == CAIRO_PATTERN_SOLID && + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID && _cairo_pattern_is_opaque_solid(pattern)) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c index 4c3e9cd71..fcd5dd781 100644 --- a/src/cairo-directfb-surface.c +++ b/src/cairo-directfb-surface.c @@ -483,9 +483,9 @@ _cairo_directfb_surface_composite (cairo_operator_t op, if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED ) return CAIRO_INT_STATUS_UNSUPPORTED; - if (src_pattern->type == CAIRO_PATTERN_SOLID ) { + if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID ) { - } else if (src_pattern->type != CAIRO_PATTERN_SURFACE || + } else if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE || src_pattern->extend != CAIRO_EXTEND_NONE) { return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -494,7 +494,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op, /* FIXME: When we fully support RENDER style 4-channel * masks we need to check r/g/b != 1.0. */ - if (mask_pattern->type != CAIRO_PATTERN_SOLID) + if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) return CAIRO_INT_STATUS_UNSUPPORTED; alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8; diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index 667e231d5..c000917ac 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -551,8 +551,8 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, attr->acquired = FALSE; switch (pattern->type) { - case CAIRO_PATTERN_LINEAR: - case CAIRO_PATTERN_RADIAL: { + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; char *data; @@ -587,7 +587,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM)) break; - if (pattern->type == CAIRO_PATTERN_RADIAL) + if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) n_base_params = 6; else n_base_params = 4; @@ -639,7 +639,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, glitz_buffer_destroy (buffer); - if (pattern->type == CAIRO_PATTERN_LINEAR) + if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern; @@ -776,8 +776,8 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, * information in mask, so this will need to change when we * support RENDER-style 4-channel masks. */ - if (src->type == CAIRO_PATTERN_SOLID && - mask->type == CAIRO_PATTERN_SOLID) + if (src->type == CAIRO_PATTERN_TYPE_SOLID && + mask->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_color_t combined; cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; @@ -1018,7 +1018,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; - if (pattern->type == CAIRO_PATTERN_SURFACE) + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern); diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 5e1e34203..3e88ec55e 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -631,7 +631,7 @@ _cairo_win32_surface_composite (cairo_operator_t op, int integer_transform; int itx, ity; - if (pattern->type != CAIRO_PATTERN_SURFACE || + if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE || pattern->extend != CAIRO_EXTEND_NONE) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -639,7 +639,7 @@ _cairo_win32_surface_composite (cairo_operator_t op, /* FIXME: When we fully support RENDER style 4-channel * masks we need to check r/g/b != 1.0. */ - if (mask_pattern->type != CAIRO_PATTERN_SOLID) + if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) return CAIRO_INT_STATUS_UNSUPPORTED; alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8; From 66599911e0664afd145975e3afb0f580e6d1bb3c Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Thu, 9 Mar 2006 22:09:14 +0100 Subject: [PATCH 050/155] Don't duplicate unmodified SVG surfaces --- src/cairo-svg-surface.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index b5cee7502..58faa32e0 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -91,6 +91,9 @@ struct cairo_svg_surface { xmlNodePtr xml_root_node; unsigned int clip_level; + + cairo_bool_t modified; + unsigned int previous_id; }; static cairo_svg_document_t * @@ -217,6 +220,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer)); snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id); xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer)); + + surface->modified = TRUE; + surface->previous_id = surface->id; return &surface->base; } @@ -459,10 +465,11 @@ emit_composite_svg_pattern (xmlNodePtr node, xmlNodePtr child; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); + if (surface->modified) + xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); child = xmlNewChild (node, NULL, CC2XML("use"), NULL); - snprintf (buffer, sizeof buffer, "#surface%d", surface->id); + snprintf (buffer, sizeof buffer, "#surface%d", surface->previous_id); xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer)); if (!is_pattern) { @@ -476,9 +483,13 @@ emit_composite_svg_pattern (xmlNodePtr node, if (height != NULL) *height = surface->height; - surface->id = document->surface_id++; - snprintf (buffer, sizeof buffer, "surface%d", surface->id); - xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer)); + if (surface->modified) { + surface->modified = FALSE; + surface->previous_id = surface->id; + surface->id = document->surface_id++; + snprintf (buffer, sizeof buffer, "surface%d", surface->id); + xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer)); + } return child; } @@ -925,6 +936,7 @@ _cairo_svg_surface_fill (void *abstract_surface, xmlBufferFree (info.path); xmlBufferFree (style); + surface->modified = TRUE; return status; } @@ -987,8 +999,10 @@ _cairo_svg_surface_paint (void *abstract_surface, cairo_pattern_t *source) { cairo_svg_surface_t *surface = abstract_surface; - + emit_paint (surface->xml_node, surface, op, source); + + surface->modified = TRUE; return CAIRO_STATUS_SUCCESS; } @@ -1017,6 +1031,7 @@ _cairo_svg_surface_mask (void *abstract_surface, document->mask_id++; + surface->modified = TRUE; return CAIRO_STATUS_SUCCESS; } @@ -1122,6 +1137,7 @@ _cairo_svg_surface_stroke (void *abstract_dst, xmlBufferFree (info.path); xmlBufferFree (style); + surface->modified = TRUE; return status; } @@ -1133,6 +1149,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, int num_glyphs, cairo_scaled_font_t *scaled_font) { + cairo_svg_surface_t *surface = abstract_surface; cairo_path_fixed_t path; cairo_status_t status; @@ -1156,6 +1173,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, _cairo_path_fixed_fini (&path); + surface->modified = TRUE; return status; } From c780f4a5624f27a6cbf7829e10e8cd3544ae4f38 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 13 Mar 2006 12:05:13 -0800 Subject: [PATCH 051/155] cairo-output-stream: Don't dereference a NULL pointer due to OOM. This close bug #6176: Null pointer dereference on OOM in _cairo_output_stream_create_for_file() https://bugs.freedesktop.org/show_bug.cgi?id=6176 --- src/cairo-output-stream.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index a6db09198..b07423c10 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -305,9 +305,11 @@ _cairo_output_stream_create_for_file (const char *filename) return NULL; stream = _cairo_output_stream_create (stdio_write, fp); - if (stream == NULL) + + if (stream) + stream->owns_closure_is_file = TRUE; + else fclose (fp); - stream->owns_closure_is_file = TRUE; return stream; } From fc51a78a1ed5f7649ce55ab30fc42939a9b295d1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 13 Mar 2006 12:14:47 -0800 Subject: [PATCH 052/155] cairo-pdf-surface: Close memory leak during OOM handling. This fixes bug #6186: Memory leak in emit_image_rgb_data (src/cairo-pdf-surface.c) https://bugs.freedesktop.org/show_bug.cgi?id=6186 --- src/cairo-pdf-surface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index cb8287bcf..6d18196b5 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -654,8 +654,10 @@ emit_image_rgb_data (cairo_pdf_document_t *document, opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, image->width, image->height); - if (opaque->status) + if (opaque->status) { + free (rgb); return 0; + } _cairo_pattern_init_for_surface (&pattern.surface, &image->base); From 79075b2cb1ce1397506fc10572df96f6fd00ecc3 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 13 Mar 2006 12:20:23 -0800 Subject: [PATCH 053/155] cairo-clip: Fix memory leak during OOM handling. This closes bug #6196: Memory leak in _cairo_clip_intersect_path (src/cairo-clip.c) https://bugs.freedesktop.org/show_bug.cgi?id=6196 --- src/cairo-clip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cairo-clip.c b/src/cairo-clip.c index c76ebdcbf..0c862a388 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -248,8 +248,10 @@ _cairo_clip_intersect_path (cairo_clip_t *clip, return CAIRO_STATUS_NO_MEMORY; status = _cairo_path_fixed_init_copy (&clip_path->path, path); - if (status) + if (status) { + free (clip_path); return status; + } clip_path->ref_count = 1; clip_path->fill_rule = fill_rule; From 6f0d8eedc504e8af2224c502be25dc82b5df70f4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 13 Mar 2006 12:25:25 -0800 Subject: [PATCH 054/155] _clip_and_composite_trapezoids: Avoid NULL pointer dereference due to OOM. This closes bug #6197: Null pointer dereference on OOM in _clip_and_composite_trapezoids() https://bugs.freedesktop.org/show_bug.cgi?id=6197 --- src/cairo-surface-fallback.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 9dde31f23..9b6cfd616 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -549,6 +549,9 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src, return status; clear_region = _cairo_region_create_from_rectangle (&extents); + if (clear_region == NULL) + return CAIRO_STATUS_NO_MEMORY; + status = _cairo_clip_intersect_to_region (clip, clear_region); if (status) return status; From 5d89faf6b37bb0367c8ba8f8637fc80bd745c888 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 13 Mar 2006 13:20:29 -0800 Subject: [PATCH 055/155] fbCompositeTrans_0888xnx0888: Fix suspicious logical negation of pointer value. Surely, the ! instead of ~ here was just a typo. I'd feel better if I had a failing test case for this though, (time to break out gcov again). Fixes bug #6185: Strange pointer operations in fbCompositeTrans_0888xnx0888 (pixman/src/fbpict.c) https://bugs.freedesktop.org/show_bug.cgi?id=6185 --- pixman/src/fbpict.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c index e074174e7..ef7f4e208 100644 --- a/pixman/src/fbpict.c +++ b/pixman/src/fbpict.c @@ -1151,7 +1151,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op, setupPackedReader(ws,wt,isrc,wsrc,workingSource); /* get to word aligned */ - switch(!(long)dst&3) + switch(~(long)dst&3) { case 1: readPackedSource(rs); @@ -1227,7 +1227,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op, srcLine += srcStride; w = width*3; /* get to word aligned */ - switch(!(long)src&3) + switch(~(long)src&3) { case 1: rd=alphamaskCombine24(*src++, *dst)>>8; From 2af29f720faac0a9ee3961a81b81acae9a716220 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Tue, 14 Mar 2006 23:02:39 +0100 Subject: [PATCH 056/155] SVG: use xmlOutputBuffer for file creation, instead of dumping xml tree in a memory buffer. --- src/cairo-svg-surface.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 58faa32e0..5d569bd6b 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -1342,21 +1342,32 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document) free (document); } +static int +_cairo_svg_document_write (cairo_output_stream_t *output_stream, + const char * buffer, + int len) +{ + if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS) + return -1; +} + + static cairo_status_t _cairo_svg_document_finish (cairo_svg_document_t *document) { cairo_status_t status; cairo_output_stream_t *output = document->output_stream; - xmlChar *xml_buffer; - int xml_buffer_size; + xmlOutputBufferPtr xml_output_buffer; if (document->finished) return CAIRO_STATUS_SUCCESS; - /* FIXME: Dumping xml tree in memory is silly. */ - xmlDocDumpFormatMemoryEnc (document->xml_doc, &xml_buffer, &xml_buffer_size, "UTF-8", 1); - _cairo_output_stream_write (document->output_stream, xml_buffer, xml_buffer_size); - xmlFree(xml_buffer); + xml_output_buffer = xmlOutputBufferCreateIO ((xmlOutputWriteCallback) _cairo_svg_document_write, + (xmlOutputCloseCallback) NULL, + (void *) document->output_stream, + NULL); + xmlSaveFormatFileTo (xml_output_buffer, document->xml_doc, "UTF-8", 1); + xmlFreeDoc (document->xml_doc); status = _cairo_output_stream_get_status (output); From d6f8df7417bdab75dbcfe9658616dd3367276ed0 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 15 Mar 2006 07:31:48 -0800 Subject: [PATCH 057/155] Remove annoyinc RCS magic lines that are not being used, but cause conflicts. --- pixman/src/fbedge.c | 2 -- pixman/src/fbedgeimp.h | 2 -- pixman/src/fbpict.c | 2 -- pixman/src/fbpict.h | 2 -- pixman/src/icpixels.c | 2 -- pixman/src/ictrap.c | 2 -- pixman/src/pixman.h | 2 -- pixman/src/pixregionint.h | 2 -- pixman/src/renderedge.c | 2 -- pixman/src/renderedge.h | 2 -- 10 files changed, 20 deletions(-) diff --git a/pixman/src/fbedge.c b/pixman/src/fbedge.c index 2ee6e6cdc..f1289b3fa 100644 --- a/pixman/src/fbedge.c +++ b/pixman/src/fbedge.c @@ -1,6 +1,4 @@ /* - * $Id: fbedge.c,v 1.3 2005-08-02 01:01:24 vektor Exp $ - * * Copyright © 2004 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/fbedgeimp.h b/pixman/src/fbedgeimp.h index 87691faf2..aa9ca90fa 100644 --- a/pixman/src/fbedgeimp.h +++ b/pixman/src/fbedgeimp.h @@ -1,6 +1,4 @@ /* - * $Id: fbedgeimp.h,v 1.2 2005-01-21 18:38:42 cworth Exp $ - * * Copyright © 2004 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c index ef7f4e208..a09174009 100644 --- a/pixman/src/fbpict.c +++ b/pixman/src/fbpict.c @@ -1,6 +1,4 @@ /* - * $Id: fbpict.c,v 1.8 2006-01-21 17:39:11 biesi Exp $ - * * Copyright © 2000 SuSE, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/fbpict.h b/pixman/src/fbpict.h index 95742ed8b..fbf00ed77 100644 --- a/pixman/src/fbpict.h +++ b/pixman/src/fbpict.h @@ -1,6 +1,4 @@ /* - * $Id: fbpict.h,v 1.2 2005-09-12 12:55:11 otaylor Exp $ - * * Copyright © 2000 Keith Packard * 2005 Lars Knoll & Zack Rusin, Trolltech * diff --git a/pixman/src/icpixels.c b/pixman/src/icpixels.c index 7b3798ed8..cdec492e3 100644 --- a/pixman/src/icpixels.c +++ b/pixman/src/icpixels.c @@ -1,6 +1,4 @@ /* - * $Id: icpixels.c,v 1.9 2005-06-25 03:13:19 jrmuizel Exp $ - * * Copyright © 1998 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/ictrap.c b/pixman/src/ictrap.c index 0ac51ca09..08bd0247b 100644 --- a/pixman/src/ictrap.c +++ b/pixman/src/ictrap.c @@ -1,6 +1,4 @@ /* - * $Id: ictrap.c,v 1.27 2005-08-28 02:32:57 vektor Exp $ - * * Copyright © 2002 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h index bd5194eb1..ecba78a55 100644 --- a/pixman/src/pixman.h +++ b/pixman/src/pixman.h @@ -54,8 +54,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ -/* $Id: pixman.h,v 1.25 2006-01-05 00:26:10 cworth Exp $ */ - /* libic.h */ /* diff --git a/pixman/src/pixregionint.h b/pixman/src/pixregionint.h index 86ff8e655..e47c45590 100644 --- a/pixman/src/pixregionint.h +++ b/pixman/src/pixregionint.h @@ -44,8 +44,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ -/* $Id: pixregionint.h,v 1.7 2004-04-16 15:32:53 cworth Exp $ */ - #ifndef _PIXREGIONINT_H_ #define _PIXREGIONINT_H_ diff --git a/pixman/src/renderedge.c b/pixman/src/renderedge.c index 525ea73f2..56fcfb3e0 100644 --- a/pixman/src/renderedge.c +++ b/pixman/src/renderedge.c @@ -1,6 +1,4 @@ /* - * $Id: renderedge.c,v 1.2 2005-01-21 18:26:28 cworth Exp $ - * * Copyright © 2004 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its diff --git a/pixman/src/renderedge.h b/pixman/src/renderedge.h index 5c7c1e540..522e5034e 100644 --- a/pixman/src/renderedge.h +++ b/pixman/src/renderedge.h @@ -1,6 +1,4 @@ /* - * $Id: renderedge.h,v 1.3 2005-02-21 21:29:22 cworth Exp $ - * * Copyright © 2004 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its From a7f58f886253f4ae66c9b0ed4472f575eaf2ec1d Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 15 Mar 2006 10:44:09 -0800 Subject: [PATCH 058/155] Add LZW image compression and ASCII85 encoding for PostScript image output. * src/Makefile.am: Add cairo-lzw.c to sources Remove erronous space at start of line * src/cairo-lzw.c: New file implementing _cairo_compress_lzw which does Lempel-Ziv & Welch compression as used by postscript. Based on code from libtiff. * src/cairo-output-stream.c: Add _cairo_output_stream_write_base85_string which implements an encoder for the ASCII85Decode postscript filter. * src/cairoint.h: Add _cairo_compress_lzw and _cairo_output_stream_write_base85_string. * src/cairo-ps-surface.c: Write Images LZW + Base85 encoded. Change ps level to 2 (we only needed level 3 for FlateDecode). Change DocumentData to Clean7Bit as we don't include binary data anymore. --- src/Makefile.am | 3 +- src/cairo-lzw.c | 499 ++++++++++++++++++++++++++++++++++++++ src/cairo-output-stream.c | 63 +++++ src/cairo-ps-surface.c | 37 +-- src/cairoint.h | 10 + 5 files changed, 582 insertions(+), 30 deletions(-) create mode 100644 src/cairo-lzw.c diff --git a/src/Makefile.am b/src/Makefile.am index 908bcb284..a7efc1efe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -145,6 +145,7 @@ libcairo_la_SOURCES = \ cairo-hash-private.h \ cairo-hull.c \ cairo-image-surface.c \ + cairo-lzw.c \ cairo-matrix.c \ cairo-path.c \ cairo-path-bounds.c \ @@ -187,7 +188,7 @@ libcairo_la_SOURCES = \ $(libcairo_glitz_sources) \ $(libcairo_win32_sources) \ $(libcairo_beos_sources) \ - $(libcairo_directfb_sources) \ + $(libcairo_directfb_sources) \ cairoint.h libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols) diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c new file mode 100644 index 000000000..bb764f3a8 --- /dev/null +++ b/src/cairo-lzw.c @@ -0,0 +1,499 @@ +/* cairo - a vector graphics library with display and print output + * + * 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 + * 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. + * + * Contributor(s): + * Alexander Larsson + * + * This code is derived from tif_lzw.c in libtiff 3.8.0. + * The original copyright notice appears below in its entirety. + */ + +#include "cairoint.h" + +#include +#include +#include +#include +#include +#include + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * Rev 5.0 Lempel-Ziv & Welch Compression Support + * + * This code is derived from the compress program whose code is + * derived from software contributed to Berkeley by James A. Woods, + * derived from original work by Spencer Thomas and Joseph Orost. + * + * The original Berkeley copyright notice appears below in its entirety. + */ + +#define MAXCODE(n) ((1L<<(n))-1) +/* + * The TIFF spec specifies that encoded bit + * strings range from 9 to 12 bits. + */ +#define BITS_MIN 9 /* start with 9 bits */ +#define BITS_MAX 12 /* max of 12 bit strings */ +/* predefined codes */ +#define CODE_CLEAR 256 /* code to clear string table */ +#define CODE_EOI 257 /* end-of-information code */ +#define CODE_FIRST 258 /* first free code entry */ +#define CODE_MAX MAXCODE(BITS_MAX) +#define HSIZE 9001L /* 91% occupancy */ +#define HSHIFT (13-8) +#ifdef LZW_COMPAT +/* NB: +1024 is for compatibility with old files */ +#define CSIZE (MAXCODE(BITS_MAX)+1024L) +#else +#define CSIZE (MAXCODE(BITS_MAX)+1L) +#endif + +typedef uint16_t hcode_t; /* codes fit in 16 bits */ +typedef struct { + long hash; + hcode_t code; +} hash_t; + +typedef struct { + /* Out buffer */ + unsigned char *out_buffer; /* compressed out buffer */ + size_t out_buffer_size; /* # of allocated bytes in out buffer */ + unsigned char *out_buffer_pos; /* current spot in out buffer */ + size_t out_buffer_bytes; /* # of data bytes in out buffer */ + unsigned char *out_buffer_end; /* bound on out_buffer */ + + unsigned short nbits; /* # of bits/code */ + unsigned short maxcode; /* maximum code for lzw_nbits */ + unsigned short free_ent; /* next free entry in hash table */ + long nextdata; /* next bits of i/o */ + long nextbits; /* # of valid bits in lzw_nextdata */ + + int enc_oldcode; /* last code encountered */ + long enc_checkpoint; /* point at which to clear table */ +#define CHECK_GAP 10000 /* enc_ratio check interval */ + long enc_ratio; /* current compression ratio */ + long enc_incount; /* (input) data bytes encoded */ + long enc_outcount; /* encoded (output) bytes */ + hash_t* enc_hashtab; /* kept separate for small machines */ +} LZWCodecState; + +static void cl_hash(LZWCodecState*); + +/* + * LZW Encoding. + */ + +static unsigned char * +grow_out_buffer (LZWCodecState *sp, unsigned char *op) +{ + size_t cc; + + cc = (size_t)(op - sp->out_buffer); + + sp->out_buffer_size = sp->out_buffer_size * 2; + sp->out_buffer = realloc (sp->out_buffer, sp->out_buffer_size); + /* + * The 4 here insures there is space for 2 max-sized + * codes in LZWEncode and LZWPostDecode. + */ + sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4; + + return sp->out_buffer + cc; +} + +static int +LZWSetupEncode (LZWCodecState* sp) +{ + memset (sp, 0, sizeof (LZWCodecState)); + sp->enc_hashtab = (hash_t*) malloc (HSIZE * sizeof (hash_t)); + if (sp->enc_hashtab == NULL) + return 0; + return 1; +} + +static void +LZWFreeEncode (LZWCodecState* sp) +{ + if (sp->enc_hashtab) + free (sp->enc_hashtab); +} + + +/* + * Reset encoding state at the start of a strip. + */ +static void +LZWPreEncode (LZWCodecState *sp) +{ + sp->nbits = BITS_MIN; + sp->maxcode = MAXCODE(BITS_MIN); + sp->free_ent = CODE_FIRST; + sp->nextbits = 0; + sp->nextdata = 0; + sp->enc_checkpoint = CHECK_GAP; + sp->enc_ratio = 0; + sp->enc_incount = 0; + sp->enc_outcount = 0; + /* + * The 4 here insures there is space for 2 max-sized + * codes in LZWEncode and LZWPostDecode. + */ + sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4; + cl_hash(sp); /* clear hash table */ + sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ +} + +#define CALCRATIO(sp, rat) { \ + if (incount > 0x007fffff) { /* NB: shift will overflow */ \ + rat = outcount >> 8; \ + rat = (rat == 0 ? 0x7fffffff : incount/rat); \ + } else \ + rat = (incount << 8) / outcount; \ +} +#define PutNextCode(op, c) { \ + nextdata = (nextdata << nbits) | c; \ + nextbits += nbits; \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + if (nextbits >= 8) { \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + } \ + outcount += nbits; \ +} + +/* + * Encode a chunk of pixels. + * + * Uses an open addressing double hashing (no chaining) on the + * prefix code/next character combination. We do a variant of + * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's + * relatively-prime secondary probe. Here, the modular division + * first probe is gives way to a faster exclusive-or manipulation. + * Also do block compression with an adaptive reset, whereby the + * code table is cleared when the compression ratio decreases, + * but after the table fills. The variable-length output codes + * are re-sized at this point, and a CODE_CLEAR is generated + * for the decoder. + */ +static int +LZWEncode (LZWCodecState *sp, + unsigned char *bp, + size_t cc) +{ + register long fcode; + register hash_t *hp; + register int h, c; + hcode_t ent; + long disp; + long incount, outcount, checkpoint; + long nextdata, nextbits; + int free_ent, maxcode, nbits; + unsigned char *op; + + /* + * Load local state. + */ + incount = sp->enc_incount; + outcount = sp->enc_outcount; + checkpoint = sp->enc_checkpoint; + nextdata = sp->nextdata; + nextbits = sp->nextbits; + free_ent = sp->free_ent; + maxcode = sp->maxcode; + nbits = sp->nbits; + op = sp->out_buffer_pos; + ent = sp->enc_oldcode; + + if (ent == (hcode_t) -1 && cc > 0) { + /* + * NB: This is safe because it can only happen + * at the start of a strip where we know there + * is space in the data buffer. + */ + PutNextCode(op, CODE_CLEAR); + ent = *bp++; cc--; incount++; + } + while (cc > 0) { + c = *bp++; cc--; incount++; + fcode = ((long)c << BITS_MAX) + ent; + h = (c << HSHIFT) ^ ent; /* xor hashing */ +#ifdef _WINDOWS + /* + * Check hash index for an overflow. + */ + if (h >= HSIZE) + h -= HSIZE; +#endif + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + continue; + } + if (hp->hash >= 0) { + /* + * Primary hash failed, check secondary hash. + */ + disp = HSIZE - h; + if (h == 0) + disp = 1; + do { + /* + * Avoid pointer arithmetic 'cuz of + * wraparound problems with segments. + */ + if ((h -= disp) < 0) + h += HSIZE; + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + goto hit; + } + } while (hp->hash >= 0); + } + /* + * New entry, emit code and add to table. + */ + /* + * Verify there is space in the buffer for the code + * and any potential Clear code that might be emitted + * below. The value of limit is setup so that there + * are at least 4 bytes free--room for 2 codes. + */ + if (op > sp->out_buffer_end) { + op = grow_out_buffer (sp, op); + if (sp->out_buffer == NULL) { + return 0; + } + } + PutNextCode(op, ent); + ent = c; + hp->code = free_ent++; + hp->hash = fcode; + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + maxcode = (int) MAXCODE(nbits); + } else if (incount >= checkpoint) { + long rat; + /* + * Check compression ratio and, if things seem + * to be slipping, clear the hash table and + * reset state. The compression ratio is a + * 24+8-bit fractional number. + */ + checkpoint = incount+CHECK_GAP; + CALCRATIO(sp, rat); + if (rat <= sp->enc_ratio) { + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else + sp->enc_ratio = rat; + } + } + hit: + ; + } + + /* + * Restore global state. + */ + sp->enc_incount = incount; + sp->enc_outcount = outcount; + sp->enc_checkpoint = checkpoint; + sp->enc_oldcode = ent; + sp->nextdata = nextdata; + sp->nextbits = nextbits; + sp->free_ent = free_ent; + sp->maxcode = maxcode; + sp->nbits = nbits; + sp->out_buffer_pos = op; + return 1; +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ +static int +LZWPostEncode (LZWCodecState *sp) +{ + unsigned char *op = sp->out_buffer_pos; + long nextbits = sp->nextbits; + long nextdata = sp->nextdata; + long outcount = sp->enc_outcount; + int nbits = sp->nbits; + + if (op > sp->out_buffer_end) { + op = grow_out_buffer (sp, op); + if (sp->out_buffer == NULL) { + return 0; + } + } + if (sp->enc_oldcode != (hcode_t) -1) { + PutNextCode(op, sp->enc_oldcode); + sp->enc_oldcode = (hcode_t) -1; + } + PutNextCode(op, CODE_EOI); + if (nextbits > 0) + *op++ = (unsigned char)(nextdata << (8-nextbits)); + sp->out_buffer_bytes = (size_t)(op - sp->out_buffer); + return 1; +} + +/* + * Reset encoding hash table. + */ +static void +cl_hash (LZWCodecState* sp) +{ + register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; + register long i = HSIZE-8; + + do { + i -= 8; + hp[-7].hash = -1; + hp[-6].hash = -1; + hp[-5].hash = -1; + hp[-4].hash = -1; + hp[-3].hash = -1; + hp[-2].hash = -1; + hp[-1].hash = -1; + hp[ 0].hash = -1; + hp -= 8; + } while (i >= 0); + for (i += 8; i > 0; i--, hp--) + hp->hash = -1; +} + +/* + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +void * +_cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compressed_size) +{ + LZWCodecState state; + + if (!LZWSetupEncode (&state)) + goto bail0; + + state.out_buffer_size = data_size/4; + /* We need *some* space at least */ + if (state.out_buffer_size < 256) + state.out_buffer_size = 256; + state.out_buffer = malloc (state.out_buffer_size); + if (state.out_buffer == NULL) + goto bail1; + + state.out_buffer_pos = state.out_buffer; + state.out_buffer_bytes = 0; + + LZWPreEncode (&state); + if (!LZWEncode (&state, data, data_size)) + goto bail2; + if (!LZWPostEncode(&state)) + goto bail2; + + LZWFreeEncode(&state); + + *compressed_size = state.out_buffer_bytes; + return state.out_buffer; + + bail2: + if (state.out_buffer) + free (state.out_buffer); + bail1: + LZWFreeEncode(&state); + bail0: + return NULL; +} diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index b07423c10..6fd61813a 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -114,6 +114,69 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, } } +static cairo_bool_t +convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5]) +{ + cairo_bool_t all_zero; + uint32_t value; + int digit, i; + + value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3]; + all_zero = TRUE; + for (i = 0; i < 5; i++) { + digit = value % 85; + if (digit != 0) + all_zero = FALSE; + five_tuple[4-i] = digit + 33; + value = value / 85; + } + return all_zero; +} + +void +_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, + const char *data, + size_t length) +{ + unsigned char *ptr; + unsigned char four_tuple[4]; + char five_tuple[5]; + int column; + + ptr = (unsigned char *)data; + column = 0; + while (length > 0) { + if (length >= 4) { + if (convert_four_tuple (ptr, five_tuple)) { + column += 1; + _cairo_output_stream_write (stream, "z", 1); + } else { + column += 5; + _cairo_output_stream_write (stream, five_tuple, 5); + } + length -= 4; + ptr += 4; + } else { /* length < 4 */ + memset (four_tuple, 0, 4); + memcpy (four_tuple, ptr, length); + convert_four_tuple (four_tuple, five_tuple); + column += length + 1; + _cairo_output_stream_write (stream, five_tuple, length + 1); + length = 0; + } + if (column >= 72) { + _cairo_output_stream_write (stream, "\n", 1); + column = 0; + } + } + + if (column > 0) { + _cairo_output_stream_write (stream, "\n", 1); + } +} + + + /* Format a double in a locale independent way and trim trailing * zeros. Based on code from Alex Larson . * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 6028b6d50..ff4f0e8c4 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -50,8 +50,6 @@ * * - Add document structure convention comments where appropriate. * - * - Fix image compression. - * * - Create a set of procs to use... specifically a trapezoid proc. */ @@ -101,11 +99,9 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) surface->width, surface->height); - /* The "/FlateDecode filter" currently used is a feature of - * LanguageLevel 3 */ _cairo_output_stream_printf (surface->stream, - "%%%%DocumentData: Binary\n" - "%%%%LanguageLevel: 3\n" + "%%%%DocumentData: Clean7Bit\n" + "%%%%LanguageLevel: 2\n" "%%%%Orientation: Portrait\n" "%%%%EndComments\n"); } @@ -658,23 +654,6 @@ pattern_operation_needs_fallback (cairo_operator_t op, /* PS Output - this section handles output of the parts of the meta * surface we can render natively in PS. */ -static void * -compress_dup (const void *data, unsigned long data_size, - unsigned long *compressed_size) -{ - void *compressed; - - /* Bound calculation taken from zlib. */ - *compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11; - compressed = malloc (*compressed_size); - if (compressed == NULL) - return NULL; - - compress (compressed, compressed_size, data, data_size); - - return compressed; -} - static cairo_status_t emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, @@ -745,7 +724,7 @@ emit_image (cairo_ps_surface_t *surface, } } - compressed = compress_dup (rgb, rgb_size, &compressed_size); + compressed = _cairo_compress_lzw (rgb, rgb_size, &compressed_size); if (compressed == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto bail2; @@ -765,7 +744,7 @@ emit_image (cairo_ps_surface_t *surface, " /Height %d\n" " /BitsPerComponent 8\n" " /Decode [ 0 1 0 1 0 1 ]\n" - " /DataSource currentfile\n" + " /DataSource currentfile /ASCII85Decode filter /LZWDecode filter \n" " /ImageMatrix [ %f %f %f %f %f %f ]\n" ">>\n" "image\n", @@ -775,13 +754,13 @@ emit_image (cairo_ps_surface_t *surface, d2i.xy, d2i.yy, d2i.x0, d2i.y0); - /* Compressed image data */ - _cairo_output_stream_write (surface->stream, rgb, rgb_size); + /* Compressed image data (Base85 encoded) */ + _cairo_output_stream_write_base85_string (surface->stream, (char *)compressed, compressed_size); status = CAIRO_STATUS_SUCCESS; + /* Mark end of base85 data */ _cairo_output_stream_printf (surface->stream, - "\n"); - + "~>\n"); free (compressed); bail2: free (rgb); diff --git a/src/cairoint.h b/src/cairoint.h index 04096c52b..d5abfc79a 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2140,6 +2140,16 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, const char *data, size_t length); +cairo_private void +_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, + const char *data, + size_t length); + +cairo_private void * +_cairo_compress_lzw (void *data, + unsigned long data_size, + unsigned long *compressed_size); + cairo_private cairo_status_t _cairo_output_stream_vprintf (cairo_output_stream_t *stream, const char *fmt, va_list ap); From 037732cac9ff402e51d80d6ed54cc32d669aa0d9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Mar 2006 10:59:59 -0500 Subject: [PATCH 059/155] Add make bits to autogenerate ChangeLog (cherry picked from 393000021c2e082d4b3c235939009a90035b0daf commit) --- .gitignore | 1 + Makefile.am | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/.gitignore b/.gitignore index aaa9f03b1..ebcd09396 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +ChangeLog Makefile Makefile.in aclocal.m4 diff --git a/Makefile.am b/Makefile.am index ab5ca24bf..1b209da55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,21 @@ EXTRA_DIST = \ COPYING-LGPL-2.1 \ COPYING-MPL-1.1 \ cairo.pc.in +MAINTAINERCLEANFILES = \ + $(srcdir)/INSTALL \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/compile \ + $(srcdir)/config.guess \ + $(srcdir)/config.h.in \ + $(srcdir)/config.sub \ + $(srcdir)/configure.scan \ + $(srcdir)/depcomp \ + $(srcdir)/install-sh \ + $(srcdir)/ltmain.sh \ + $(srcdir)/missing \ + $(srcdir)/mkinstalldirs \ + `find "$(srcdir)" -type f -name Makefile.in -print` pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = cairo.pc @@ -20,6 +35,30 @@ check-valgrind: all DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc +# Creating ChangeLog from git log: + +MAINTAINERCLEANFILES += ChangeLog + +EXTRA_DIST += ChangeLog + +ChangeLog: $(srcdir)/ChangeLog + +$(srcdir)/ChangeLog: + @if test -d "$(srcdir)/.git"; then \ + (cd "$(srcdir)" && \ + ./missing --run git-log) | fmt --split-only > $@.tmp \ + && mv -f $@.tmp $@ \ + || ($(RM) $@.tmp; \ + echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ + (test -f $@ || echo git-log is required to generate this file >> $@)); \ + else \ + test -f $@ || \ + (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ + echo A git checkout and git-log is required to generate this file >> $@); \ + fi + +.PHONY: ChangeLog $(srcdir)/ChangeLog + # Some custom targets to make it easier to release things. # Use either: # make release-check From f00a1833341699135e792e3a77e19dca0d1dba86 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Mar 2006 11:18:40 -0500 Subject: [PATCH 060/155] Update release infra to reflect git transition. (cherry picked from 508b0be5f2023dabe9561f4ca62481d6a4c8c5ae commit) --- INSTALL | 2 +- Makefile.am | 4 ++-- RELEASING | 21 +++++++++------------ configure.in | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/INSTALL b/INSTALL index 4a49f008d..ab82781bd 100644 --- a/INSTALL +++ b/INSTALL @@ -16,7 +16,7 @@ This final step may require temporary root access (eg. with sudo) if you don't have write permission to the directory in which cairo will be installed. -NOTE: If you are working with source from CVS rather than from a tar +NOTE: If you are working with source from git/cvs rather than from a tar file, then you should use ./autogen.sh in place of ./configure anywhere it is mentioned in these instructions. diff --git a/Makefile.am b/Makefile.am index 1b209da55..47bedefda 100644 --- a/Makefile.am +++ b/Makefile.am @@ -121,7 +121,7 @@ release-verify-newer: @echo -n "Checking that no $(VERSION) release already exists..." @ssh $(RELEASE_UPLOAD_HOST) test ! -e $(RELEASE_UPLOAD_DIR)/$(tar_file) \ || (echo "Ouch." && echo "Found: $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)/$(tar_file)" \ - && echo "Are you sure you have an updated CVS checkout?" \ + && echo "Are you sure you have an updated checkout?" \ && echo "This should never happen." \ && false) @echo "Good." @@ -143,7 +143,7 @@ release-upload: release-check $(tar_file) $(sha1_file) $(gpg_file) scp $(tar_file) $(sha1_file) $(gpg_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR) mv $(tar_file) $(sha1_file) $(gpg_file) releases ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)" - $(CVS) tag RELEASE_$(CAIRO_VERSION_MAJOR)_$(CAIRO_VERSION_MINOR)_$(CAIRO_VERSION_MICRO) + git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO) release-publish: release-upload releases/$(sha1_file) @echo "" diff --git a/RELEASING b/RELEASING index df87e3847..bf7317b53 100644 --- a/RELEASING +++ b/RELEASING @@ -1,12 +1,7 @@ Here are the steps to follow to create a new cairo release: -1) Ensure that there are no local, uncommitted modifications. The best - thing to do here may be to begin with a fresh checkout from CVS: - - cvs -d cairographics.org:/cvs/cairo co cairo - - But it's probably good enough if "cvs -q update -Ad" generates no - output. +1) Ensure that there are no local, uncommitted modifications. + It's probably good enough if "git status" says so. 2) Verify that the code passes "make distcheck" @@ -32,7 +27,10 @@ Here are the steps to follow to create a new cairo release: previous release tag: find src/ -name '*.h' -not -name '*-private.h' -not -name 'cairoint.h' | \ - xargs cvs diff -r RELEASE_X_Y_Z + xargs git diff X.Y.Z -- + + Note that for older releases made under CVS, the tag name is + RELEASE_X_Y_Z instead. 4) Increment cairo_version_{minor|micro} and LT_{CURRENT|VERSION|AGE} in configure.in: @@ -55,9 +53,8 @@ Here are the steps to follow to create a new cairo release: 5) Commit the changes to NEWS and configure.in - Don't forget to fill out the ChangeLog just like with any - other commit. It's especially important to mention the new - version number in the ChangeLog. + It's especially important to mention the new version number in your + commit log. 6) Run "make release-publish" which will perform the following steps for you: @@ -71,7 +68,7 @@ Here are the steps to follow to create a new cairo release: * scp the three files to appear on http://cairographics.org/releases * Place local copies of the three files in the releases directory * Create a LATEST-package-version file (after deleting any old one) - * Tag the entire source tree with a tag of the form RELEASE_X_Y_Z + * Tag the entire source tree with a tag of the form X.Y.Z * Provide some text for the release announcement (see below). 7) Increment cairo_version_micro to the next larger (odd) number in diff --git a/configure.in b/configure.in index b957ada3d..44783bd29 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ AC_PREREQ(2.54) # cairo package version number, (as distinct from shared library version) -# An odd micro number indicates in-progress development, (eg. from CVS) +# An odd micro number indicates in-progress development, (eg. from git/cvs) # An even micro number indicates a released version. m4_define(cairo_version_major, 1) m4_define(cairo_version_minor, 1) From 46e5ed66d3329f1608950d817e7248c91087893a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Mar 2006 11:25:02 -0500 Subject: [PATCH 061/155] Note using "git diff" instead of "git status" as the latter is a bit tricky when it says nothing to commit... (cherry picked from a1621eadb655806de8bb47c2e701de6eaa9d2090 commit) --- RELEASING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASING b/RELEASING index bf7317b53..802040452 100644 --- a/RELEASING +++ b/RELEASING @@ -1,7 +1,7 @@ Here are the steps to follow to create a new cairo release: 1) Ensure that there are no local, uncommitted modifications. - It's probably good enough if "git status" says so. + It's probably good enough if "git diff" doesn't output anything. 2) Verify that the code passes "make distcheck" From f5013b6dc6442493ea38949fdcc137e5c44b6872 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Mar 2006 14:19:08 -0500 Subject: [PATCH 062/155] Add a release-publish-message target to only get the message. (cherry picked from 98facc6c2d0f57f05de7b98c2aaa592c895d1a09 commit) --- Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 47bedefda..165f9c349 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,7 +145,7 @@ release-upload: release-check $(tar_file) $(sha1_file) $(gpg_file) ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)" git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO) -release-publish: release-upload releases/$(sha1_file) +release-publish-message: releases/$(sha1_file) @echo "" @echo "Please send an announcement to $(RELEASE_ANNOUNCE_LIST)" @echo "including the following:" @@ -172,6 +172,8 @@ release-publish: release-upload releases/$(sha1_file) @echo "Last but not least, do not forget to bump up the micro" @echo "version component to the next (odd) number and commit." +release-publish: release-upload release-publish-message + # XXX: Depending on all here is rather overkill. We don't really need # the library built in order to create the documentation. docs-publish: all From 26b06b3638ec768da01839cfa3c75e9807b14ee8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Mar 2006 15:17:26 -0500 Subject: [PATCH 063/155] Clarify that git tag -s does GPG signing. (cherry picked from e94251861565ed154e15ca3a7198ffe3828536fe commit) --- RELEASING | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/RELEASING b/RELEASING index 802040452..49dd82ce9 100644 --- a/RELEASING +++ b/RELEASING @@ -68,8 +68,13 @@ Here are the steps to follow to create a new cairo release: * scp the three files to appear on http://cairographics.org/releases * Place local copies of the three files in the releases directory * Create a LATEST-package-version file (after deleting any old one) - * Tag the entire source tree with a tag of the form X.Y.Z + * Tag the entire source tree with a tag of the form X.Y.Z, and sign + the tag with your GPG key (asks for your GPG password, and you + may need to set GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to match + your public-key's setting or this fails.) * Provide some text for the release announcement (see below). + If for some reason you lost this message, "make release-publish-message" + prints it for you. 7) Increment cairo_version_micro to the next larger (odd) number in configure, and commit. From 69acfa6576e8d2b97e3e3b8c06badf5486ae0315 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Fri, 17 Mar 2006 21:26:27 +0100 Subject: [PATCH 064/155] Don't link to C++ libraries on non-BeOS systems --- src/Makefile.am | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index a7efc1efe..ad1856866 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,11 @@ libcairo_beos_sources = if CAIRO_HAS_BEOS_SURFACE libcairo_beos_headers = cairo-beos.h libcairo_beos_sources += cairo-beos-surface.cpp + +noinst_LTLIBRARIES = libcairo_beos.la +libcairo_beos_la_SOURCES = $(libcairo_beos_sources) +# BeOS system headers trigger this warning +libcairo_beos_la_CXXFLAGS = -Wno-multichar endif if CAIRO_HAS_GLITZ_SURFACE @@ -187,20 +192,16 @@ libcairo_la_SOURCES = \ $(libcairo_xcb_sources) \ $(libcairo_glitz_sources) \ $(libcairo_win32_sources) \ - $(libcairo_beos_sources) \ $(libcairo_directfb_sources) \ cairoint.h libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols) -# this -Wno-multichar line is really just for the beos surface, because the -# system headers trigger this warning. -libcairo_la_CXXFLAGS = -Wno-multichar INCLUDES = -I$(srcdir) -I$(top_srcdir)/pixman/src $(CAIRO_CFLAGS) -libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS) +libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS) $(noinst_LTLIBRARIES) -libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la +libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la $(noinst_LTLIBRARIES) EXTRA_DIST = \ cairo.def From ef04471b1b90057c00ec51e1f3d7c7ed4ab1e34c Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Sat, 18 Mar 2006 18:08:20 +0100 Subject: [PATCH 065/155] More consistent naming for the BeOS surface functions --- src/cairo-beos-surface.cpp | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp index 5cd427761..6347ba772 100644 --- a/src/cairo-beos-surface.cpp +++ b/src/cairo-beos-surface.cpp @@ -570,18 +570,18 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface, } static cairo_int_status_t -_cairo_beos_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - void *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) +_cairo_beos_surface_composite (cairo_operator_t op, + cairo_pattern_t *src, + cairo_pattern_t *mask, + void *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + int dst_x, + int dst_y, + unsigned int width, + unsigned int height) { cairo_beos_surface_t *surface = reinterpret_cast( dst); @@ -661,19 +661,19 @@ _cairo_beos_composite (cairo_operator_t op, static void -_cairo_beos_fill_rectangle (cairo_beos_surface_t *surface, - cairo_rectangle_t *rect) +_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface, + cairo_rectangle_t *rect) { BRect brect(_cairo_rect_to_brect(rect)); surface->view->FillRect(brect); } static cairo_int_status_t -_cairo_beos_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_t *rects, - int num_rects) +_cairo_beos_surface_fill_rectangles (void *abstract_surface, + cairo_operator_t op, + const cairo_color_t *color, + cairo_rectangle_t *rects, + int num_rects) { fprintf(stderr, "Drawing %i rectangles\n", num_rects); cairo_beos_surface_t *surface = reinterpret_cast( @@ -716,7 +716,7 @@ _cairo_beos_fill_rectangles (void *abstract_surface, surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); for (int i = 0; i < num_rects; ++i) { - _cairo_beos_fill_rectangle(surface, &rects[i]); + _cairo_beos_surface_fill_rectangle(surface, &rects[i]); } surface->view->PopState(); @@ -785,8 +785,8 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = { _cairo_beos_surface_acquire_dest_image, _cairo_beos_surface_release_dest_image, NULL, /* clone_similar */ - _cairo_beos_composite, /* composite */ - _cairo_beos_fill_rectangles, + _cairo_beos_surface_composite, /* composite */ + _cairo_beos_surface_fill_rectangles, NULL, /* composite_trapezoids */ NULL, /* copy_page */ NULL, /* show_page */ From a193f70b94667808f573caa5b82a1bf50281555e Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Wed, 22 Mar 2006 11:48:44 +0100 Subject: [PATCH 066/155] SVG: return len in _cairo_svg_document_write when operation succeed. --- src/cairo-svg-surface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 5d569bd6b..d4134084a 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -1349,6 +1349,8 @@ _cairo_svg_document_write (cairo_output_stream_t *output_stream, { if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS) return -1; + + return len; } From cabe94a15c277bb8a5f0c71f25cc8bc9e22ecb41 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 22 Mar 2006 23:12:23 -0800 Subject: [PATCH 067/155] Make all hash/cache keys_equal function accept const pointers. --- src/cairo-cache-private.h | 2 +- src/cairo-font.c | 12 ++++++------ src/cairo-ft-font.c | 12 ++++++------ src/cairo-hash-private.h | 2 +- src/cairo-scaled-font.c | 14 +++++++------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/cairo-cache-private.h b/src/cairo-cache-private.h index a75e8c0be..566dbe22d 100644 --- a/src/cairo-cache-private.h +++ b/src/cairo-cache-private.h @@ -88,7 +88,7 @@ typedef struct _cairo_cache_entry { } cairo_cache_entry_t; typedef cairo_bool_t -(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b); +(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b); typedef void (*cairo_cache_callback_func_t) (void *entry, diff --git a/src/cairo-font.c b/src/cairo-font.c index 65124803d..425021a1e 100644 --- a/src/cairo-font.c +++ b/src/cairo-font.c @@ -210,8 +210,8 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face, static const cairo_font_face_backend_t _cairo_toy_font_face_backend; static int -_cairo_toy_font_face_keys_equal (void *key_a, - void *key_b); +_cairo_toy_font_face_keys_equal (const void *key_a, + const void *key_b); /* We maintain a hash table from family/weight/slant => * cairo_font_face_t for cairo_toy_font_t. The primary purpose of @@ -312,11 +312,11 @@ _cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face) } static int -_cairo_toy_font_face_keys_equal (void *key_a, - void *key_b) +_cairo_toy_font_face_keys_equal (const void *key_a, + const void *key_b) { - cairo_toy_font_face_t *face_a = key_a; - cairo_toy_font_face_t *face_b = key_b; + const cairo_toy_font_face_t *face_a = key_a; + const cairo_toy_font_face_t *face_b = key_b; return (strcmp (face_a->family, face_b->family) == 0 && face_a->slant == face_b->slant && diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 092838ab4..a23388a72 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -103,8 +103,8 @@ struct _cairo_ft_unscaled_font { }; static int -_cairo_ft_unscaled_font_keys_equal (void *key_a, - void *key_b); +_cairo_ft_unscaled_font_keys_equal (const void *key_a, + const void *key_b); static void _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled); @@ -365,11 +365,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled) } static int -_cairo_ft_unscaled_font_keys_equal (void *key_a, - void *key_b) +_cairo_ft_unscaled_font_keys_equal (const void *key_a, + const void *key_b) { - cairo_ft_unscaled_font_t *unscaled_a = key_a; - cairo_ft_unscaled_font_t *unscaled_b = key_b; + const cairo_ft_unscaled_font_t *unscaled_a = key_a; + const cairo_ft_unscaled_font_t *unscaled_b = key_b; return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 && unscaled_a->id == unscaled_b->id); diff --git a/src/cairo-hash-private.h b/src/cairo-hash-private.h index 6dc9c9073..617b8410d 100644 --- a/src/cairo-hash-private.h +++ b/src/cairo-hash-private.h @@ -85,7 +85,7 @@ typedef struct _cairo_hash_entry { } cairo_hash_entry_t; typedef cairo_bool_t -(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b); +(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b); typedef cairo_bool_t (*cairo_hash_predicate_func_t) (void *entry); diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index a0469046d..afefac48f 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -39,10 +39,10 @@ #include "cairoint.h" static cairo_bool_t -_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b) +_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b) { - cairo_scaled_glyph_t *key_a = abstract_key_a; - cairo_scaled_glyph_t *key_b = abstract_key_b; + const cairo_scaled_glyph_t *key_a = abstract_key_a; + const cairo_scaled_glyph_t *key_b = abstract_key_b; return (_cairo_scaled_glyph_index (key_a) == _cairo_scaled_glyph_index (key_b)); @@ -180,7 +180,7 @@ static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL; CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex); static int -_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b); +_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b); static cairo_scaled_font_map_t * _cairo_scaled_font_map_lock (void) @@ -298,10 +298,10 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, } static cairo_bool_t -_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b) +_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b) { - cairo_scaled_font_t *key_a = abstract_key_a; - cairo_scaled_font_t *key_b = abstract_key_b; + const cairo_scaled_font_t *key_a = abstract_key_a; + const cairo_scaled_font_t *key_b = abstract_key_b; return (key_a->font_face == key_b->font_face && memcmp ((unsigned char *)(&key_a->font_matrix.xx), From ec60bb0a606cadf3120d1cebc88e248a3e056c19 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 23 Mar 2006 15:00:40 -0800 Subject: [PATCH 068/155] Rename _cairo_compress_lzw to _cairo_lzw_compress and tighten the parameter list. --- src/cairo-lzw.c | 8 ++++---- src/cairo-ps-surface.c | 3 ++- src/cairoint.h | 4 +--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index bb764f3a8..a0d737e25 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -460,14 +460,14 @@ cl_hash (LZWCodecState* sp) */ void * -_cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compressed_size) +_cairo_lzw_compress (void *data, unsigned long *data_size_in_out) { LZWCodecState state; if (!LZWSetupEncode (&state)) goto bail0; - state.out_buffer_size = data_size/4; + state.out_buffer_size = *data_size_in_out/4; /* We need *some* space at least */ if (state.out_buffer_size < 256) state.out_buffer_size = 256; @@ -479,14 +479,14 @@ _cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compres state.out_buffer_bytes = 0; LZWPreEncode (&state); - if (!LZWEncode (&state, data, data_size)) + if (!LZWEncode (&state, data, *data_size_in_out)) goto bail2; if (!LZWPostEncode(&state)) goto bail2; LZWFreeEncode(&state); - *compressed_size = state.out_buffer_bytes; + *data_size_in_out = state.out_buffer_bytes; return state.out_buffer; bail2: diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index ff4f0e8c4..a646d45ba 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -724,7 +724,8 @@ emit_image (cairo_ps_surface_t *surface, } } - compressed = _cairo_compress_lzw (rgb, rgb_size, &compressed_size); + compressed_size = rgb_size; + compressed = _cairo_lzw_compress (rgb, &compressed_size); if (compressed == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto bail2; diff --git a/src/cairoint.h b/src/cairoint.h index d5abfc79a..fdb8fc5df 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2146,9 +2146,7 @@ _cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, size_t length); cairo_private void * -_cairo_compress_lzw (void *data, - unsigned long data_size, - unsigned long *compressed_size); +_cairo_lzw_compress (void *data, unsigned long *data_size_in_out); cairo_private cairo_status_t _cairo_output_stream_vprintf (cairo_output_stream_t *stream, From 639c2fe4df880546d71b2c73ea972fb08b609603 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 23 Mar 2006 15:23:29 -0800 Subject: [PATCH 069/155] cairo-lzw: Replace LZW code from libtiff with an original implementation. This new implementation is an entirely original work directly from the description of the LZWDecode filter in the PostScript Language Reference, (and in spite of the bugs in the examples provided in that reference). This implementation uses the existing cairo-hash.c for the symbol table. This implementation is somewhat easier to read than the libtiff code, and avoids any code that may have an advertising clause attached. This new implementation is the simplest thing I could implement. It is not as efficient as the libtiff code, (though I did expect better things from cairo-hash.c). --- src/cairo-lzw.c | 753 ++++++++++++++++++++---------------------------- src/cairoint.h | 4 +- 2 files changed, 307 insertions(+), 450 deletions(-) diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index a0d737e25..67a41bde3 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright © 2006 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 @@ -27,473 +27,330 @@ * * The Original Code is the cairo graphics library. * - * Contributor(s): - * Alexander Larsson + * The Initial Developer of the Original Code is University of Southern + * California. * - * This code is derived from tif_lzw.c in libtiff 3.8.0. - * The original copyright notice appears below in its entirety. + * Contributor(s): + * Carl D. Worth */ #include "cairoint.h" -#include -#include -#include -#include -#include -#include +static unsigned long +_cairo_hash_bytes (const unsigned char *c, int size); -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. +typedef struct _lzw_buf { + unsigned char *data; + int data_size; + int num_data; + uint32_t pending; + int pending_bits; +} lzw_buf_t; + +/* An lzw_buf_t is a simple, growable chunk of memory for holding + * variable-size objects of up to 16 bits each. * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* - * TIFF Library. - * Rev 5.0 Lempel-Ziv & Welch Compression Support + * Initialize an lzw_buf_t to the given size in bytes. * - * This code is derived from the compress program whose code is - * derived from software contributed to Berkeley by James A. Woods, - * derived from original work by Spencer Thomas and Joseph Orost. - * - * The original Berkeley copyright notice appears below in its entirety. + * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. */ - -#define MAXCODE(n) ((1L<<(n))-1) -/* - * The TIFF spec specifies that encoded bit - * strings range from 9 to 12 bits. - */ -#define BITS_MIN 9 /* start with 9 bits */ -#define BITS_MAX 12 /* max of 12 bit strings */ -/* predefined codes */ -#define CODE_CLEAR 256 /* code to clear string table */ -#define CODE_EOI 257 /* end-of-information code */ -#define CODE_FIRST 258 /* first free code entry */ -#define CODE_MAX MAXCODE(BITS_MAX) -#define HSIZE 9001L /* 91% occupancy */ -#define HSHIFT (13-8) -#ifdef LZW_COMPAT -/* NB: +1024 is for compatibility with old files */ -#define CSIZE (MAXCODE(BITS_MAX)+1024L) -#else -#define CSIZE (MAXCODE(BITS_MAX)+1L) -#endif - -typedef uint16_t hcode_t; /* codes fit in 16 bits */ -typedef struct { - long hash; - hcode_t code; -} hash_t; - -typedef struct { - /* Out buffer */ - unsigned char *out_buffer; /* compressed out buffer */ - size_t out_buffer_size; /* # of allocated bytes in out buffer */ - unsigned char *out_buffer_pos; /* current spot in out buffer */ - size_t out_buffer_bytes; /* # of data bytes in out buffer */ - unsigned char *out_buffer_end; /* bound on out_buffer */ - - unsigned short nbits; /* # of bits/code */ - unsigned short maxcode; /* maximum code for lzw_nbits */ - unsigned short free_ent; /* next free entry in hash table */ - long nextdata; /* next bits of i/o */ - long nextbits; /* # of valid bits in lzw_nextdata */ - - int enc_oldcode; /* last code encountered */ - long enc_checkpoint; /* point at which to clear table */ -#define CHECK_GAP 10000 /* enc_ratio check interval */ - long enc_ratio; /* current compression ratio */ - long enc_incount; /* (input) data bytes encoded */ - long enc_outcount; /* encoded (output) bytes */ - hash_t* enc_hashtab; /* kept separate for small machines */ -} LZWCodecState; - -static void cl_hash(LZWCodecState*); - -/* - * LZW Encoding. - */ - -static unsigned char * -grow_out_buffer (LZWCodecState *sp, unsigned char *op) +static cairo_status_t +_lzw_buf_init (lzw_buf_t *buf, int size) { - size_t cc; - - cc = (size_t)(op - sp->out_buffer); - - sp->out_buffer_size = sp->out_buffer_size * 2; - sp->out_buffer = realloc (sp->out_buffer, sp->out_buffer_size); - /* - * The 4 here insures there is space for 2 max-sized - * codes in LZWEncode and LZWPostDecode. - */ - sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4; - - return sp->out_buffer + cc; -} + if (size == 0) + size = 16; -static int -LZWSetupEncode (LZWCodecState* sp) -{ - memset (sp, 0, sizeof (LZWCodecState)); - sp->enc_hashtab = (hash_t*) malloc (HSIZE * sizeof (hash_t)); - if (sp->enc_hashtab == NULL) - return 0; - return 1; -} - -static void -LZWFreeEncode (LZWCodecState* sp) -{ - if (sp->enc_hashtab) - free (sp->enc_hashtab); -} - - -/* - * Reset encoding state at the start of a strip. - */ -static void -LZWPreEncode (LZWCodecState *sp) -{ - sp->nbits = BITS_MIN; - sp->maxcode = MAXCODE(BITS_MIN); - sp->free_ent = CODE_FIRST; - sp->nextbits = 0; - sp->nextdata = 0; - sp->enc_checkpoint = CHECK_GAP; - sp->enc_ratio = 0; - sp->enc_incount = 0; - sp->enc_outcount = 0; - /* - * The 4 here insures there is space for 2 max-sized - * codes in LZWEncode and LZWPostDecode. - */ - sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4; - cl_hash(sp); /* clear hash table */ - sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ -} - -#define CALCRATIO(sp, rat) { \ - if (incount > 0x007fffff) { /* NB: shift will overflow */ \ - rat = outcount >> 8; \ - rat = (rat == 0 ? 0x7fffffff : incount/rat); \ - } else \ - rat = (incount << 8) / outcount; \ -} -#define PutNextCode(op, c) { \ - nextdata = (nextdata << nbits) | c; \ - nextbits += nbits; \ - *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ - nextbits -= 8; \ - if (nextbits >= 8) { \ - *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ - nextbits -= 8; \ - } \ - outcount += nbits; \ -} - -/* - * Encode a chunk of pixels. - * - * Uses an open addressing double hashing (no chaining) on the - * prefix code/next character combination. We do a variant of - * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's - * relatively-prime secondary probe. Here, the modular division - * first probe is gives way to a faster exclusive-or manipulation. - * Also do block compression with an adaptive reset, whereby the - * code table is cleared when the compression ratio decreases, - * but after the table fills. The variable-length output codes - * are re-sized at this point, and a CODE_CLEAR is generated - * for the decoder. - */ -static int -LZWEncode (LZWCodecState *sp, - unsigned char *bp, - size_t cc) -{ - register long fcode; - register hash_t *hp; - register int h, c; - hcode_t ent; - long disp; - long incount, outcount, checkpoint; - long nextdata, nextbits; - int free_ent, maxcode, nbits; - unsigned char *op; - - /* - * Load local state. - */ - incount = sp->enc_incount; - outcount = sp->enc_outcount; - checkpoint = sp->enc_checkpoint; - nextdata = sp->nextdata; - nextbits = sp->nextbits; - free_ent = sp->free_ent; - maxcode = sp->maxcode; - nbits = sp->nbits; - op = sp->out_buffer_pos; - ent = sp->enc_oldcode; - - if (ent == (hcode_t) -1 && cc > 0) { - /* - * NB: This is safe because it can only happen - * at the start of a strip where we know there - * is space in the data buffer. - */ - PutNextCode(op, CODE_CLEAR); - ent = *bp++; cc--; incount++; + buf->data = malloc (size); + if (buf->data == NULL) { + buf->data_size = 0; + return CAIRO_STATUS_NO_MEMORY; } - while (cc > 0) { - c = *bp++; cc--; incount++; - fcode = ((long)c << BITS_MAX) + ent; - h = (c << HSHIFT) ^ ent; /* xor hashing */ -#ifdef _WINDOWS - /* - * Check hash index for an overflow. - */ - if (h >= HSIZE) - h -= HSIZE; -#endif - hp = &sp->enc_hashtab[h]; - if (hp->hash == fcode) { - ent = hp->code; - continue; + + buf->data_size = size; + buf->num_data = 0; + buf->pending = 0; + buf->pending_bits = 0; + + return CAIRO_STATUS_SUCCESS; +} + +static void +_lzw_buf_fini (lzw_buf_t *buf) +{ + assert (buf->pending_bits == 0); + + free (buf->data); + buf->data = 0; +} + +static cairo_status_t +_lzw_buf_grow (lzw_buf_t *buf) +{ + int new_size = buf->data_size * 2; + unsigned char *new_data; + + new_data = realloc (buf->data, new_size); + if (new_data == NULL) + return CAIRO_STATUS_NO_MEMORY; + + buf->data = new_data; + buf->data_size = new_size; + + return CAIRO_STATUS_SUCCESS; +} + +/* Store the lowest num_bits bits of values into buf. + * + * NOTE: The bits of value above size_in_bits must be 0, (so don't lie + * about the size). + * + * See also _lzw_buf_store_pending which must be called after the last + * call to _lzw_buf_store_bits. + * + * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. + */ +static cairo_status_t +_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits) +{ + cairo_status_t status; + + assert (value <= (1 << num_bits) - 1); + + if (getenv ("CAIRO_DEBUG_LZW")) + printf ("%d(%d) ", value, num_bits); + + buf->pending = (buf->pending << num_bits) | value; + buf->pending_bits += num_bits; + + while (buf->pending_bits >= 8) { + if (buf->num_data >= buf->data_size) { + status = _lzw_buf_grow (buf); + if (status) + return status; } - if (hp->hash >= 0) { - /* - * Primary hash failed, check secondary hash. - */ - disp = HSIZE - h; - if (h == 0) - disp = 1; - do { - /* - * Avoid pointer arithmetic 'cuz of - * wraparound problems with segments. - */ - if ((h -= disp) < 0) - h += HSIZE; - hp = &sp->enc_hashtab[h]; - if (hp->hash == fcode) { - ent = hp->code; - goto hit; - } - } while (hp->hash >= 0); + buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8); + buf->pending_bits -= 8; + } + + return CAIRO_STATUS_SUCCESS; +} + +/* Store the last remaining pending bits into the buffer. + * + * NOTE: This function must be called after the last call to + * _lzw_buf_store_bits. + * + * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. + */ +static cairo_status_t +_lzw_buf_store_pending (lzw_buf_t *buf) +{ + cairo_status_t status; + + if (buf->pending_bits == 0) + return CAIRO_STATUS_SUCCESS; + + assert (buf->pending_bits < 8); + + if (buf->num_data >= buf->data_size) { + status = _lzw_buf_grow (buf); + if (status) + return status; + } + + buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits); + buf->pending_bits = 0; + + return CAIRO_STATUS_SUCCESS; +} + +typedef struct _lzw_symbol { + cairo_hash_entry_t hash_entry; + + /* "key" is the symbol */ + unsigned char *data; + int size; + /* "value" is the code */ + int value; +} lzw_symbol_t; + +#define LZW_BITS_MIN 9 +#define LZW_BITS_MAX 12 +#define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1) +#define LZW_MAX_SYMBOLS (1<size != symbol_b->size) + return FALSE; + + return ! memcmp (symbol_a->data, symbol_b->data, symbol_a->size); +} + +static cairo_status_t +_lzw_symbols_init (lzw_symbols_t *symbols) +{ + symbols->num_symbols = 0; + + symbols->table = _cairo_hash_table_create (_lzw_symbols_equal); + if (symbols->table == NULL) + return CAIRO_STATUS_NO_MEMORY; + + return CAIRO_STATUS_SUCCESS; +} + +static void +_lzw_symbols_fini (lzw_symbols_t *symbols) +{ + int i; + + for (i=0; i < symbols->num_symbols; i++) + _cairo_hash_table_remove (symbols->table, &symbols->symbols[i].hash_entry); + + symbols->num_symbols = 0; + + _cairo_hash_table_destroy (symbols->table); +} + +static cairo_bool_t +_lzw_symbols_has (lzw_symbols_t *symbols, + lzw_symbol_t *symbol, + lzw_symbol_t **code) +{ + symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size); + + return _cairo_hash_table_lookup (symbols->table, + &symbol->hash_entry, + (cairo_hash_entry_t **) code); +} + +static cairo_status_t +_lzw_symbols_store (lzw_symbols_t *symbols, + lzw_symbol_t *symbol) +{ + cairo_status_t status; + + symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size); + + symbols->symbols[symbols->num_symbols] = *symbol; + + status = _cairo_hash_table_insert (symbols->table, &symbols->symbols[symbols->num_symbols].hash_entry); + if (status) + return status; + + symbols->num_symbols++; + + return CAIRO_STATUS_SUCCESS; +} + +#define LZW_CODE_CLEAR_TABLE 256 +#define LZW_CODE_EOD 257 +#define LZW_CODE_FIRST 258 + +unsigned char * +_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) +{ + cairo_status_t status; + int bytes_remaining = *size_in_out; + lzw_symbols_t symbols; + lzw_symbol_t symbol, *tmp, *code; + lzw_buf_t buf; + int code_next = LZW_CODE_FIRST; + int code_bits = LZW_BITS_MIN; + + status = _lzw_buf_init (&buf, *size_in_out / 4); + if (status) + return NULL; + + status = _lzw_symbols_init (&symbols); + if (status) { + _lzw_buf_fini (&buf); + return NULL; + } + + _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); + + symbol.data = data; + symbol.size = 2; + + while (bytes_remaining) { + code = NULL; + while (symbol.size <= bytes_remaining && + _lzw_symbols_has (&symbols, &symbol, &tmp)) + { + code = tmp; + symbol.size++; } - /* - * New entry, emit code and add to table. - */ - /* - * Verify there is space in the buffer for the code - * and any potential Clear code that might be emitted - * below. The value of limit is setup so that there - * are at least 4 bytes free--room for 2 codes. - */ - if (op > sp->out_buffer_end) { - op = grow_out_buffer (sp, op); - if (sp->out_buffer == NULL) { - return 0; + + if (code) + _lzw_buf_store_bits (&buf, code->value, code_bits); + else + _lzw_buf_store_bits (&buf, symbol.data[0], code_bits); + + if (symbol.size == bytes_remaining + 1) + break; + + symbol.value = code_next++; + _lzw_symbols_store (&symbols, &symbol); + + /* XXX: This is just for compatibility testing against libtiff. */ + if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) { + _lzw_symbols_fini (&symbols); + _lzw_symbols_init (&symbols); + _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); + code_bits = LZW_BITS_MIN; + code_next = LZW_CODE_FIRST; + } + + if (code_next > LZW_BITS_BOUNDARY(code_bits)) + { + code_bits++; + if (code_bits > LZW_BITS_MAX) { + _lzw_symbols_fini (&symbols); + _lzw_symbols_init (&symbols); + _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); + code_bits = LZW_BITS_MIN; + code_next = LZW_CODE_FIRST; } } - PutNextCode(op, ent); - ent = c; - hp->code = free_ent++; - hp->hash = fcode; - if (free_ent == CODE_MAX-1) { - /* table is full, emit clear code and reset */ - cl_hash(sp); - sp->enc_ratio = 0; - incount = 0; - outcount = 0; - free_ent = CODE_FIRST; - PutNextCode(op, CODE_CLEAR); - nbits = BITS_MIN; - maxcode = MAXCODE(BITS_MIN); + + if (code) { + symbol.data += (symbol.size - 1); + bytes_remaining -= (symbol.size - 1); } else { - /* - * If the next entry is going to be too big for - * the code size, then increase it, if possible. - */ - if (free_ent > maxcode) { - nbits++; - assert(nbits <= BITS_MAX); - maxcode = (int) MAXCODE(nbits); - } else if (incount >= checkpoint) { - long rat; - /* - * Check compression ratio and, if things seem - * to be slipping, clear the hash table and - * reset state. The compression ratio is a - * 24+8-bit fractional number. - */ - checkpoint = incount+CHECK_GAP; - CALCRATIO(sp, rat); - if (rat <= sp->enc_ratio) { - cl_hash(sp); - sp->enc_ratio = 0; - incount = 0; - outcount = 0; - free_ent = CODE_FIRST; - PutNextCode(op, CODE_CLEAR); - nbits = BITS_MIN; - maxcode = MAXCODE(BITS_MIN); - } else - sp->enc_ratio = rat; - } + symbol.data += 1; + bytes_remaining -= 1; } - hit: - ; + symbol.size = 2; } - - /* - * Restore global state. - */ - sp->enc_incount = incount; - sp->enc_outcount = outcount; - sp->enc_checkpoint = checkpoint; - sp->enc_oldcode = ent; - sp->nextdata = nextdata; - sp->nextbits = nextbits; - sp->free_ent = free_ent; - sp->maxcode = maxcode; - sp->nbits = nbits; - sp->out_buffer_pos = op; - return 1; + + _lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits); + + _lzw_buf_store_pending (&buf); + + _lzw_symbols_fini (&symbols); + + *size_in_out = buf.num_data; + return buf.data; } -/* - * Finish off an encoded strip by flushing the last - * string and tacking on an End Of Information code. - */ -static int -LZWPostEncode (LZWCodecState *sp) +static unsigned long +_cairo_hash_bytes (const unsigned char *c, int size) { - unsigned char *op = sp->out_buffer_pos; - long nextbits = sp->nextbits; - long nextdata = sp->nextdata; - long outcount = sp->enc_outcount; - int nbits = sp->nbits; - - if (op > sp->out_buffer_end) { - op = grow_out_buffer (sp, op); - if (sp->out_buffer == NULL) { - return 0; - } - } - if (sp->enc_oldcode != (hcode_t) -1) { - PutNextCode(op, sp->enc_oldcode); - sp->enc_oldcode = (hcode_t) -1; - } - PutNextCode(op, CODE_EOI); - if (nextbits > 0) - *op++ = (unsigned char)(nextdata << (8-nextbits)); - sp->out_buffer_bytes = (size_t)(op - sp->out_buffer); - return 1; -} - -/* - * Reset encoding hash table. - */ -static void -cl_hash (LZWCodecState* sp) -{ - register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; - register long i = HSIZE-8; - - do { - i -= 8; - hp[-7].hash = -1; - hp[-6].hash = -1; - hp[-5].hash = -1; - hp[-4].hash = -1; - hp[-3].hash = -1; - hp[-2].hash = -1; - hp[-1].hash = -1; - hp[ 0].hash = -1; - hp -= 8; - } while (i >= 0); - for (i += 8; i > 0; i--, hp--) - hp->hash = -1; -} - -/* - * Copyright (c) 1985, 1986 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * James A. Woods, derived from original work by Spencer Thomas - * and Joseph Orost. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -void * -_cairo_lzw_compress (void *data, unsigned long *data_size_in_out) -{ - LZWCodecState state; - - if (!LZWSetupEncode (&state)) - goto bail0; - - state.out_buffer_size = *data_size_in_out/4; - /* We need *some* space at least */ - if (state.out_buffer_size < 256) - state.out_buffer_size = 256; - state.out_buffer = malloc (state.out_buffer_size); - if (state.out_buffer == NULL) - goto bail1; - - state.out_buffer_pos = state.out_buffer; - state.out_buffer_bytes = 0; - - LZWPreEncode (&state); - if (!LZWEncode (&state, data, *data_size_in_out)) - goto bail2; - if (!LZWPostEncode(&state)) - goto bail2; - - LZWFreeEncode(&state); - - *data_size_in_out = state.out_buffer_bytes; - return state.out_buffer; - - bail2: - if (state.out_buffer) - free (state.out_buffer); - bail1: - LZWFreeEncode(&state); - bail0: - return NULL; + /* This is the djb2 hash. */ + unsigned long hash = 5381; + while (size--) + hash = ((hash << 5) + hash) + *c++; + return hash; } diff --git a/src/cairoint.h b/src/cairoint.h index fdb8fc5df..3dc0f7e5e 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2145,8 +2145,8 @@ _cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, const char *data, size_t length); -cairo_private void * -_cairo_lzw_compress (void *data, unsigned long *data_size_in_out); +unsigned char * +_cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out); cairo_private cairo_status_t _cairo_output_stream_vprintf (cairo_output_stream_t *stream, From bcfe344608150aa56b1cb37dbc774455bfcf6830 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 23 Mar 2006 15:27:00 -0800 Subject: [PATCH 070/155] Optimize the implementation of _cairo_lzw_compress. This switches the implementation of _cairo_lzw_compress from using cairo-hash.c to a custom implementation of the same algorithm that takes advantage of the specific details of what is needed here. This final version now has comparable performance to the libtiff code, but should hopefully be easier to understand. Add a bunch of comments explaining how the various pieces work. --- src/cairo-lzw.c | 405 +++++++++++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 174 deletions(-) diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index 67a41bde3..1de618cc5 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -36,10 +36,9 @@ #include "cairoint.h" -static unsigned long -_cairo_hash_bytes (const unsigned char *c, int size); - typedef struct _lzw_buf { + cairo_status_t status; + unsigned char *data; int data_size; int num_data; @@ -52,46 +51,56 @@ typedef struct _lzw_buf { * * Initialize an lzw_buf_t to the given size in bytes. * - * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. + * To store objects into the lzw_buf_t, call _lzw_buf_store_bits and + * when finished, call _lzw_buf_store_pending, (which flushes out the + * last few bits that hadn't yet made a complete byte yet). + * + * Instead of returning failure from any functions, lzw_buf_t provides + * a status value that the caller can query, (and should query at + * least once when done with the object). The status value will be + * either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY; */ -static cairo_status_t +static void _lzw_buf_init (lzw_buf_t *buf, int size) { if (size == 0) size = 16; + buf->status = CAIRO_STATUS_SUCCESS; + buf->data = malloc (size); if (buf->data == NULL) { buf->data_size = 0; - return CAIRO_STATUS_NO_MEMORY; + buf->status = CAIRO_STATUS_NO_MEMORY; + return; } buf->data_size = size; buf->num_data = 0; buf->pending = 0; buf->pending_bits = 0; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_lzw_buf_fini (lzw_buf_t *buf) -{ - assert (buf->pending_bits == 0); - - free (buf->data); - buf->data = 0; } +/* Increase the buffer size by doubling. + * + * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY + */ static cairo_status_t _lzw_buf_grow (lzw_buf_t *buf) { int new_size = buf->data_size * 2; unsigned char *new_data; + if (buf->status) + return buf->status; + new_data = realloc (buf->data, new_size); - if (new_data == NULL) - return CAIRO_STATUS_NO_MEMORY; + if (new_data == NULL) { + free (buf->data); + buf->data_size = 0; + buf->status = CAIRO_STATUS_NO_MEMORY; + return buf->status; + } buf->data = new_data; buf->data_size = new_size; @@ -107,17 +116,17 @@ _lzw_buf_grow (lzw_buf_t *buf) * See also _lzw_buf_store_pending which must be called after the last * call to _lzw_buf_store_bits. * - * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. + * Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. */ -static cairo_status_t +static void _lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits) { cairo_status_t status; assert (value <= (1 << num_bits) - 1); - if (getenv ("CAIRO_DEBUG_LZW")) - printf ("%d(%d) ", value, num_bits); + if (buf->status) + return; buf->pending = (buf->pending << num_bits) | value; buf->pending_bits += num_bits; @@ -126,13 +135,11 @@ _lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits) if (buf->num_data >= buf->data_size) { status = _lzw_buf_grow (buf); if (status) - return status; + return; } buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8); buf->pending_bits -= 8; } - - return CAIRO_STATUS_SUCCESS; } /* Store the last remaining pending bits into the buffer. @@ -140,217 +147,267 @@ _lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits) * NOTE: This function must be called after the last call to * _lzw_buf_store_bits. * - * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. + * Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY. */ -static cairo_status_t +static void _lzw_buf_store_pending (lzw_buf_t *buf) { cairo_status_t status; + if (buf->status) + return; + if (buf->pending_bits == 0) - return CAIRO_STATUS_SUCCESS; + return; assert (buf->pending_bits < 8); if (buf->num_data >= buf->data_size) { status = _lzw_buf_grow (buf); if (status) - return status; + return; } buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits); buf->pending_bits = 0; - - return CAIRO_STATUS_SUCCESS; } -typedef struct _lzw_symbol { - cairo_hash_entry_t hash_entry; +/* LZW defines a few magic code values */ +#define LZW_CODE_CLEAR_TABLE 256 +#define LZW_CODE_EOD 257 +#define LZW_CODE_FIRST 258 - /* "key" is the symbol */ - unsigned char *data; - int size; - /* "value" is the code */ - int value; -} lzw_symbol_t; +/* We pack three separate values into a symbol as follows: + * + * 12 bits (31 down to 20): CODE: code value used to represent this symbol + * 12 bits (19 down to 8): PREV: previous code value in chain + * 8 bits ( 7 down to 0): NEXT: next byte value in chain + */ +typedef uint32_t lzw_symbol_t; +#define LZW_SYMBOL_SET(sym, prev, next) ((sym) = ((prev) << 8)|(next)) +#define LZW_SYMBOL_SET_CODE(sym, code, prev, next) ((sym) = ((code << 20)|(prev) << 8)|(next)) +#define LZW_SYMBOL_GET_CODE(sym) (((sym) >> 20)) +#define LZW_SYMBOL_GET_PREV(sym) (((sym) >> 8) & 0x7ff) +#define LZW_SYMBOL_GET_BYTE(sym) (((sym) >> 0) & 0x0ff) + +/* The PREV+NEXT fields can be seen as the key used to fetch values + * from the hash table, while the code is the value fetched. + */ +#define LZW_SYMBOL_KEY_MASK 0x000fffff + +/* Since code values are only stored starting with 258 we can safely + * use a zero value to represent free slots in the hash table. */ +#define LZW_SYMBOL_FREE 0x00000000 + +/* These really aren't very free for modifying. First, the PostScript + * specification sets the 9-12 bit range. Second, the encoding of + * lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte + * fitting within 32 bits. + * + * But other than that, the LZW compression scheme could function with + * more bits per code. + */ #define LZW_BITS_MIN 9 #define LZW_BITS_MAX 12 #define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1) #define LZW_MAX_SYMBOLS (1<size != symbol_b->size) - return FALSE; - - return ! memcmp (symbol_a->data, symbol_b->data, symbol_a->size); -} - -static cairo_status_t -_lzw_symbols_init (lzw_symbols_t *symbols) -{ - symbols->num_symbols = 0; - - symbols->table = _cairo_hash_table_create (_lzw_symbols_equal); - if (symbols->table == NULL) - return CAIRO_STATUS_NO_MEMORY; - - return CAIRO_STATUS_SUCCESS; -} +typedef struct _lzw_symbol_table { + lzw_symbol_t table[LZW_SYMBOL_TABLE_SIZE]; +} lzw_symbol_table_t; +/* Initialize the hash table to entirely empty */ static void -_lzw_symbols_fini (lzw_symbols_t *symbols) +_lzw_symbol_table_init (lzw_symbol_table_t *table) { - int i; - - for (i=0; i < symbols->num_symbols; i++) - _cairo_hash_table_remove (symbols->table, &symbols->symbols[i].hash_entry); - - symbols->num_symbols = 0; - - _cairo_hash_table_destroy (symbols->table); + memset (table->table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t)); } +/* Lookup a symbol in the symbol table. The PREV and NEXT fields of + * symbol form the key for the lookup. + * + * If succesful, then this function returns TRUE and slot_ret will be + * left pointing at the result that will have the CODE field of + * interest. + * + * If the lookup fails, then this function returns FALSE and slot_ret + * will be pointing at the location in the table to which a new CODE + * value should be stored along with PREV and NEXT. + */ static cairo_bool_t -_lzw_symbols_has (lzw_symbols_t *symbols, - lzw_symbol_t *symbol, - lzw_symbol_t **code) +_lzw_symbol_table_lookup (lzw_symbol_table_t *table, + lzw_symbol_t symbol, + lzw_symbol_t **slot_ret) { - symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size); + /* The algorithm here is identical to that in cairo-hash.c. We + * copy it here to allow for a rather more efficient + * implementation due to several circumstances that do not apply + * to the more general case: + * + * 1) We have a known bound on the total number of symbols, so we + * have a fixed-size table without any copying when growing + * + * 2) We never delete any entries, so we don't need to + * support/check for DEAD entries during lookup. + * + * 3) The object fits in 32 bits so we store each object in its + * entirety within the table rather than storing objects + * externally and putting pointers in the table, (which here + * would just double the storage requirements and have negative + * impacts on memory locality). + */ + int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK; + lzw_symbol_t candidate; - return _cairo_hash_table_lookup (symbols->table, - &symbol->hash_entry, - (cairo_hash_entry_t **) code); -} + idx = hash % LZW_SYMBOL_MOD1; + step = 0; -static cairo_status_t -_lzw_symbols_store (lzw_symbols_t *symbols, - lzw_symbol_t *symbol) -{ - cairo_status_t status; - - symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size); - - symbols->symbols[symbols->num_symbols] = *symbol; - - status = _cairo_hash_table_insert (symbols->table, &symbols->symbols[symbols->num_symbols].hash_entry); - if (status) - return status; - - symbols->num_symbols++; - - return CAIRO_STATUS_SUCCESS; -} - -#define LZW_CODE_CLEAR_TABLE 256 -#define LZW_CODE_EOD 257 -#define LZW_CODE_FIRST 258 - -unsigned char * -_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) -{ - cairo_status_t status; - int bytes_remaining = *size_in_out; - lzw_symbols_t symbols; - lzw_symbol_t symbol, *tmp, *code; - lzw_buf_t buf; - int code_next = LZW_CODE_FIRST; - int code_bits = LZW_BITS_MIN; - - status = _lzw_buf_init (&buf, *size_in_out / 4); - if (status) - return NULL; - - status = _lzw_symbols_init (&symbols); - if (status) { - _lzw_buf_fini (&buf); - return NULL; - } - - _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); - - symbol.data = data; - symbol.size = 2; - - while (bytes_remaining) { - code = NULL; - while (symbol.size <= bytes_remaining && - _lzw_symbols_has (&symbols, &symbol, &tmp)) + *slot_ret = NULL; + for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++) + { + candidate = table->table[idx]; + if (candidate == LZW_SYMBOL_FREE) { - code = tmp; - symbol.size++; + *slot_ret = &table->table[idx]; + return FALSE; + } + else /* candidate is LIVE */ + { + if ((candidate & LZW_SYMBOL_KEY_MASK) == + (symbol & LZW_SYMBOL_KEY_MASK)) + { + *slot_ret = &table->table[idx]; + return TRUE; + } } - if (code) - _lzw_buf_store_bits (&buf, code->value, code_bits); - else - _lzw_buf_store_bits (&buf, symbol.data[0], code_bits); + if (step == 0) { + step = hash % LZW_SYMBOL_MOD2; + if (step == 0) + step = 1; + } - if (symbol.size == bytes_remaining + 1) + idx += step; + if (idx >= LZW_SYMBOL_TABLE_SIZE) + idx -= LZW_SYMBOL_TABLE_SIZE; + } + + return FALSE; +} + +/* Compress a bytestream using the LZW algorithm. + * + * This is an original implementation based on reading the + * specification of the LZWDecode filter in the PostScript Language + * Reference. The free parameters in the LZW algorithm are set to the + * values mandated by PostScript, (symbols encoded with widths from 9 + * to 12 bits). + * + * This function returns a pointer to a newly allocated buffer holding + * the compressed data, or NULL if an out-of-memory situation + * occurs. + * + * Notice that any one of the _lzw_buf functions called here could + * trigger an out-of-memory condition. But lzw_buf_t uses cairo's + * shutdown-on-error idiom, so it's safe to continue to call into + * lzw_buf without having to check for errors, (until a final check at + * the end). + */ +cairo_public unsigned char * +_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) +{ + int bytes_remaining = *size_in_out; + lzw_buf_t buf; + lzw_symbol_table_t table; + lzw_symbol_t symbol, *slot; + int code_next = LZW_CODE_FIRST; + int code_bits = LZW_BITS_MIN; + int prev, next; + + if (*size_in_out == 0) + return NULL; + + _lzw_buf_init (&buf, *size_in_out); + + _lzw_symbol_table_init (&table); + + /* The LZW header is a clear table code. */ + _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); + + while (1) { + + /* Find the longest existing code in the symbol table that + * matches the current input, if any. */ + prev = *data++; + bytes_remaining--; + if (bytes_remaining) { + do + { + next = *data++; + bytes_remaining--; + LZW_SYMBOL_SET (symbol, prev, next); + if (_lzw_symbol_table_lookup (&table, symbol, &slot)) + prev = LZW_SYMBOL_GET_CODE (*slot); + } while (bytes_remaining && *slot != LZW_SYMBOL_FREE); + if (*slot == LZW_SYMBOL_FREE) { + data--; + bytes_remaining++; + } + } + + /* Write the code into the output. This is either a byte read + * directly from the input, or a code from the last successful + * lookup. */ + _lzw_buf_store_bits (&buf, prev, code_bits); + + if (bytes_remaining == 0) break; - symbol.value = code_next++; - _lzw_symbols_store (&symbols, &symbol); + LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next); - /* XXX: This is just for compatibility testing against libtiff. */ + /* The libtiff code detects a full table and clears it a bit + * earlier than strictly necessary. Here is the code to do + * that which might be useful in doing correctness comparisons + * against the output of libtiff. */ +#if CLEAR_TABLE_EARLY_FOR_IDENTICAL_OUTPUT_COMPAREED_TO_LIBTIFF if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) { - _lzw_symbols_fini (&symbols); - _lzw_symbols_init (&symbols); + _lzw_symbol_table_init (&table); _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); code_bits = LZW_BITS_MIN; code_next = LZW_CODE_FIRST; } +#endif if (code_next > LZW_BITS_BOUNDARY(code_bits)) { code_bits++; if (code_bits > LZW_BITS_MAX) { - _lzw_symbols_fini (&symbols); - _lzw_symbols_init (&symbols); - _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); + _lzw_symbol_table_init (&table); + _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1); code_bits = LZW_BITS_MIN; code_next = LZW_CODE_FIRST; } } - - if (code) { - symbol.data += (symbol.size - 1); - bytes_remaining -= (symbol.size - 1); - } else { - symbol.data += 1; - bytes_remaining -= 1; - } - symbol.size = 2; } + /* The LZW footer is an end-of-data code. */ _lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits); _lzw_buf_store_pending (&buf); - _lzw_symbols_fini (&symbols); + /* See if we ever ran out of memory while writing to buf. */ + if (buf.status == CAIRO_STATUS_NO_MEMORY) { + *size_in_out = 0; + return NULL; + } + + assert (buf.status == CAIRO_STATUS_SUCCESS); *size_in_out = buf.num_data; return buf.data; } - -static unsigned long -_cairo_hash_bytes (const unsigned char *c, int size) -{ - /* This is the djb2 hash. */ - unsigned long hash = 5381; - while (size--) - hash = ((hash << 5) + hash) + *c++; - return hash; -} From 3259efed7690670754d7c1e76176ff26464111c3 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 23 Mar 2006 15:36:41 -0800 Subject: [PATCH 071/155] _cairo_lzw_compress: Remove unused code which we had for testing conformance with the LZW compression from libtiff. --- src/cairo-lzw.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index 1de618cc5..2a4a8e1e7 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -370,19 +370,6 @@ _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next); - /* The libtiff code detects a full table and clears it a bit - * earlier than strictly necessary. Here is the code to do - * that which might be useful in doing correctness comparisons - * against the output of libtiff. */ -#if CLEAR_TABLE_EARLY_FOR_IDENTICAL_OUTPUT_COMPAREED_TO_LIBTIFF - if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) { - _lzw_symbol_table_init (&table); - _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); - code_bits = LZW_BITS_MIN; - code_next = LZW_CODE_FIRST; - } -#endif - if (code_next > LZW_BITS_BOUNDARY(code_bits)) { code_bits++; From ecb062a6792d39f7ddb670ef35ea89b868e79353 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Mar 2006 11:48:35 -0800 Subject: [PATCH 072/155] Update PDF backend for new paginated API so it at least doesn't crash. --- src/cairo-pdf-surface.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index dd2fa9096..1d6eeac35 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -140,6 +140,8 @@ struct cairo_pdf_surface { cairo_array_t alphas; cairo_array_t fonts; cairo_bool_t has_clip; + + cairo_paginated_mode_t paginated_mode; }; #define DEFAULT_DPI 300 @@ -185,6 +187,10 @@ _cairo_pdf_surface_add_stream (cairo_pdf_surface_t *surface, static void _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface); +static void +_cairo_pdf_set_paginated_mode (cairo_surface_t *target, + cairo_paginated_mode_t mode); + static const cairo_surface_backend_t cairo_pdf_surface_backend; static unsigned int @@ -307,7 +313,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (target, CAIRO_CONTENT_COLOR_ALPHA, width, height, - NULL); /* XXX */ + _cairo_pdf_set_paginated_mode); } /** @@ -452,6 +458,8 @@ _cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document, _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_resource_t)); surface->has_clip = FALSE; + surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; + return &surface->base; } @@ -2111,3 +2119,12 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document, return CAIRO_STATUS_SUCCESS; } + +static void +_cairo_pdf_set_paginated_mode (cairo_surface_t *target, + cairo_paginated_mode_t paginated_mode) +{ + cairo_pdf_surface_t *surface = (cairo_pdf_surface_t *) target; + + surface->paginated_mode = paginated_mode; +} From 498094027e18fbc8f190a225a87787a5b445e547 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Mar 2006 11:49:48 -0800 Subject: [PATCH 073/155] Back out use of meta-surface for similar-paginated-surface. It's not ready yet. --- src/cairo-paginated-surface.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index fb5695309..bb5e03436 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -155,15 +155,6 @@ _cairo_paginated_surface_get_target (cairo_surface_t *surface) return paginated_surface->target; } -static cairo_surface_t * -_cairo_paginated_surface_create_similar (void *other, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - static cairo_status_t _cairo_paginated_surface_finish (void *abstract_surface) { @@ -421,7 +412,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other) } const cairo_surface_backend_t cairo_paginated_surface_backend = { - _cairo_paginated_surface_create_similar, + NULL, /* create_similar */ _cairo_paginated_surface_finish, _cairo_paginated_surface_acquire_source_image, _cairo_paginated_surface_release_source_image, From 7cee03957b805db55df6f54deef5012535dfa7f4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Mar 2006 11:57:18 -0800 Subject: [PATCH 074/155] cairo-ps-surface: Fix characterization of CLEAR and SOURCE operators. CLEAR should always be considered a translucent operator, while SOURCE is not necessarily always opaque. --- src/cairo-ps-surface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f35f82391..66069929c 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -562,9 +562,10 @@ operator_always_opaque (cairo_operator_t op) { switch (op) { case CAIRO_OPERATOR_CLEAR: + return FALSE; case CAIRO_OPERATOR_SOURCE: - return TRUE; + return FALSE; case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_IN: @@ -594,6 +595,7 @@ operator_always_translucent (cairo_operator_t op) { switch (op) { case CAIRO_OPERATOR_CLEAR: + return TRUE; case CAIRO_OPERATOR_SOURCE: return FALSE; From 29dad9867aa5f00f4f38da5da7df6aded794682c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Mar 2006 11:58:45 -0800 Subject: [PATCH 075/155] cairo-ps-surface: Don't support meta-surfaces. This isn't ready yet. --- src/cairo-ps-surface.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 66069929c..f90a9c83f 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -626,8 +626,6 @@ operator_always_translucent (cairo_operator_t op) static cairo_bool_t pattern_surface_supported (const cairo_surface_pattern_t *pattern) { - if (_cairo_surface_is_meta (pattern->surface)) - return TRUE; if (pattern->surface->backend->acquire_source_image != NULL) return TRUE; return FALSE; From edb83e306bda8a78a8a72006f257922cda7adc69 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 24 Mar 2006 12:07:21 -0800 Subject: [PATCH 076/155] cairo-ps-surface: Simplify operation analysis. Introduce a new pattern_operation_analyze function which allows a much simpler idiom to be used by all of the drawing operations. This also provides new assertions that when we are not analyzing we are never called to perform an operation that we would analyze as unsupported. --- src/cairo-ps-surface.c | 57 ++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f90a9c83f..305240a10 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -644,7 +644,7 @@ pattern_supported (const cairo_pattern_t *pattern) static cairo_bool_t pattern_operation_supported (cairo_operator_t op, - const cairo_pattern_t *pattern) + const cairo_pattern_t *pattern) { if (! pattern_supported (pattern)) return FALSE; @@ -655,6 +655,16 @@ pattern_operation_supported (cairo_operator_t op, return pattern_is_opaque (pattern); } +static cairo_int_status_t +pattern_operation_analyze (cairo_operator_t op, + const cairo_pattern_t *pattern) +{ + if (pattern_operation_supported (op, pattern)) + return CAIRO_STATUS_SUCCESS; + else + return CAIRO_INT_STATUS_UNSUPPORTED; +} + /* PS Output - this section handles output of the parts of the meta * surface we can render natively in PS. */ @@ -1132,11 +1142,18 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_ps_surface_path_info_t info; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - if (!pattern_operation_supported (op, source)) - return CAIRO_INT_STATUS_UNSUPPORTED; - return CAIRO_STATUS_SUCCESS; - } + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return pattern_operation_analyze (op, source); + + /* XXX: It would be nice to be able to assert this condition + * here. But, we actually allow one 'cheat' that is used when + * painting the final image-based fallbacks. The final fallbacks + * do have alpha which we support by blending with white. This is + * possible only because there is nothing between the fallback + * images and the paper, nor is anything painted above. */ + /* + assert (pattern_operation_supported (op, source)); + */ if (surface->need_start_page) _cairo_ps_surface_start_page (surface); @@ -1206,12 +1223,10 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_int_status_t status; cairo_ps_surface_path_info_t info; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - if (!pattern_operation_supported (op, source)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; - } + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return pattern_operation_analyze (op, source); + + assert (pattern_operation_supported (op, source)); if (surface->need_start_page) _cairo_ps_surface_start_page (surface); @@ -1284,11 +1299,10 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - if (!pattern_operation_supported (op, source)) - return CAIRO_INT_STATUS_UNSUPPORTED; - return CAIRO_STATUS_SUCCESS; - } + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return pattern_operation_analyze (op, source); + + assert (pattern_operation_supported (op, source)); if (surface->need_start_page) _cairo_ps_surface_start_page (surface); @@ -1339,11 +1353,10 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_int_status_t status; cairo_path_fixed_t *path; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - if (!pattern_operation_supported (op, source)) - return CAIRO_INT_STATUS_UNSUPPORTED; - return CAIRO_STATUS_SUCCESS; - } + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return pattern_operation_analyze (op, source); + + assert (pattern_operation_supported (op, source)); if (surface->need_start_page) _cairo_ps_surface_start_page (surface); From 8fbd0d448dbdf8f556315366b64abe2468588ea6 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Mon, 27 Mar 2006 02:31:51 +0200 Subject: [PATCH 077/155] Implement create_similar for BeOS --- src/cairo-beos-surface.cpp | 218 ++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 52 deletions(-) diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp index 6347ba772..dfb0217a2 100644 --- a/src/cairo-beos-surface.cpp +++ b/src/cairo-beos-surface.cpp @@ -70,6 +70,9 @@ struct cairo_beos_surface_t { BBitmap* bitmap; + // If true, surface and view should be deleted when this surface is + // destroyed + bool owns_bitmap_view; }; class AutoLockView { @@ -92,6 +95,11 @@ class AutoLockView { bool mOK; }; +static cairo_surface_t * +_cairo_beos_surface_create_internal (BView* view, + BBitmap* bmp, + bool owns_bitmap_view = false); + static BRect _cairo_rect_to_brect (const cairo_rectangle_t* rect) { @@ -414,10 +422,76 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op, }; } +static cairo_surface_t * +_cairo_beos_surface_create_similar (void *abstract_surface, + cairo_content_t content, + int width, + int height) +{ + fprintf(stderr, "Creating similar\n"); + + cairo_beos_surface_t *surface = reinterpret_cast( + abstract_surface); + + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; + + BRect rect(0.0, 0.0, width - 1, height - 1); + BBitmap* bmp; + switch (content) { + case CAIRO_CONTENT_ALPHA: + // Can't support this natively + return _cairo_image_surface_create_with_content(content, width, + height); + case CAIRO_CONTENT_COLOR_ALPHA: + bmp = new BBitmap(rect, B_RGBA32, true); + break; + case CAIRO_CONTENT_COLOR: + // Match the color depth + if (surface->bitmap) { + color_space space = surface->bitmap->ColorSpace(); + // No alpha was requested -> make sure not to return + // a surface with alpha + if (space == B_RGBA32) + space = B_RGB32; + if (space == B_RGBA15) + space = B_RGB15; + bmp = new BBitmap(rect, space, true); + } else { + BScreen scr(surface->view->Window()); + color_space space = B_RGB32; + if (scr.IsValid()) + space = scr.ColorSpace(); + bmp = new BBitmap(rect, space, true); + } + break; + default: + assert(0); + return NULL; + + }; + BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0); + bmp->AddChild(view); + return _cairo_beos_surface_create_internal(view, bmp, true); +} + static cairo_status_t _cairo_beos_surface_finish (void *abstract_surface) { - // Nothing to do + cairo_beos_surface_t *surface = reinterpret_cast( + abstract_surface); + if (surface->owns_bitmap_view) { + if (surface->bitmap) + surface->bitmap->RemoveChild(surface->view); + + delete surface->view; + delete surface->bitmap; + + surface->view = NULL; + surface->bitmap = NULL; + } return CAIRO_STATUS_SUCCESS; } @@ -549,13 +623,12 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface, cairo_beos_surface_t *surface = reinterpret_cast( abstract_surface); + AutoLockView locker(surface->view); if (!locker) return; - BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image); - surface->view->PushState(); surface->view->SetDrawingMode(B_OP_COPY); @@ -617,46 +690,78 @@ _cairo_beos_surface_composite (cairo_operator_t op, cairo_surface_t* src_surface = reinterpret_cast(src)-> surface; - if (_cairo_surface_is_image(src_surface)) { - fprintf(stderr, "Composite\n"); - // Draw it on screen. + // Get a bitmap + BBitmap* bmp = NULL; + bool free_bmp = false; + if (_cairo_surface_is_image(src_surface)) { cairo_image_surface_t* img_surface = reinterpret_cast(src_surface); - BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface); - surface->view->PushState(); - - // If our image rect is only a subrect of the desired size, and we - // aren't using B_OP_ALPHA, then we need to fill the rect first. - if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) { - rgb_color black = { 0, 0, 0, 0 }; - - surface->view->SetDrawingMode(mode); - surface->view->SetHighColor(black); - surface->view->FillRect(dstRect); - } - - if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) { - mode = B_OP_COPY; - - } - surface->view->SetDrawingMode(mode); - - if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32) - surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); - else - surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - - surface->view->DrawBitmap(bmp, srcRect, dstRect); - - surface->view->PopState(); - delete bmp; - - return CAIRO_INT_STATUS_SUCCESS; + bmp = _cairo_image_surface_to_bitmap(img_surface); + free_bmp = true; + } else if (src_surface->backend == surface->base.backend) { + cairo_beos_surface_t *beos_surface = + reinterpret_cast(src_surface); + if (beos_surface->bitmap) { + AutoLockView locker(beos_surface->view); + if (locker) + beos_surface->view->Sync(); + bmp = beos_surface->bitmap; + } else { + _cairo_beos_view_to_bitmap(surface->view, &bmp); + free_bmp = true; + } } - return CAIRO_INT_STATUS_UNSUPPORTED; + if (!bmp) + return CAIRO_INT_STATUS_UNSUPPORTED; + + // So, BeOS seems to screw up painting an opaque bitmap onto a + // translucent one (it makes them partly transparent). Just return + // unsupported. + if (bmp->ColorSpace() == B_RGB32 && surface->bitmap && + surface->bitmap->ColorSpace() == B_RGBA32 && + (mode == B_OP_COPY || mode == B_OP_ALPHA)) + { + if (free_bmp) + delete bmp; + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + fprintf(stderr, "Composite\n"); + + // Draw it on screen. + surface->view->PushState(); + + // If our image rect is only a subrect of the desired size, and we + // aren't using B_OP_ALPHA, then we need to fill the rect first. + if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) { + rgb_color black = { 0, 0, 0, 0 }; + + surface->view->SetDrawingMode(mode); + surface->view->SetHighColor(black); + surface->view->FillRect(dstRect); + } + + if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) { + mode = B_OP_COPY; + } + surface->view->SetDrawingMode(mode); + + if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32) + surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); + else + surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + + surface->view->DrawBitmap(bmp, srcRect, dstRect); + + surface->view->PopState(); + + if (free_bmp) + delete bmp; + + return CAIRO_INT_STATUS_SUCCESS; } @@ -778,7 +883,7 @@ _cairo_beos_surface_get_extents (void *abstract_surface, static const struct _cairo_surface_backend cairo_beos_surface_backend = { CAIRO_SURFACE_TYPE_BEOS, - NULL, /* create_similar */ + _cairo_beos_surface_create_similar, _cairo_beos_surface_finish, _cairo_beos_surface_acquire_source_image, _cairo_beos_surface_release_source_image, @@ -807,6 +912,28 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = { NULL /* show_glyphs */ }; +static cairo_surface_t * +_cairo_beos_surface_create_internal (BView* view, + BBitmap* bmp, + bool owns_bitmap_view) +{ + // Must use malloc, because cairo code will use free() on the surface + cairo_beos_surface_t *surface = static_cast( + malloc(sizeof(cairo_beos_surface_t))); + if (surface == NULL) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return const_cast(&_cairo_surface_nil); + } + + _cairo_surface_init(&surface->base, &cairo_beos_surface_backend); + + surface->view = view; + surface->bitmap = bmp; + surface->owns_bitmap_view = owns_bitmap_view; + + return (cairo_surface_t *) surface; +} + /** * cairo_beos_surface_create: * @view: The view to draw on @@ -843,20 +970,7 @@ cairo_surface_t * cairo_beos_surface_create_for_bitmap (BView* view, BBitmap* bmp) { - // Must use malloc, because cairo code will use free() on the surface - cairo_beos_surface_t *surface = static_cast( - malloc(sizeof(cairo_beos_surface_t))); - if (surface == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return const_cast(&_cairo_surface_nil); - } - - _cairo_surface_init(&surface->base, &cairo_beos_surface_backend); - - surface->view = view; - surface->bitmap = bmp; - - return (cairo_surface_t *) surface; + return _cairo_beos_surface_create_internal(view, bmp); } // --------------------------------------------------------------------------- From 6a430478f508361767bff91132c3978234b76e95 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Tue, 14 Mar 2006 13:25:51 +0100 Subject: [PATCH 078/155] Add an assert for the unsupported image surface formats --- src/cairo-beos-surface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp index dfb0217a2..312bd88ff 100644 --- a/src/cairo-beos-surface.cpp +++ b/src/cairo-beos-surface.cpp @@ -367,6 +367,7 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface) return data; } default: + assert(0); return NULL; } } From 03eb1b85a906fac4acfbf3ee2839d13ccac97668 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 10 Mar 2006 11:57:41 -0800 Subject: [PATCH 079/155] [win32] Add missing depth-16 format check (cherry picked from 969d624db8d32d35361bbcc89dbcc354f3d48eaa commit) --- src/cairo-win32-surface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 3e88ec55e..310561a82 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -996,6 +996,8 @@ cairo_win32_surface_create (HDC hdc) format = CAIRO_FORMAT_ARGB32; else if (depth == 24) format = CAIRO_FORMAT_RGB24; + else if (depth == 16) + format = CAIRO_FORMAT_RGB24; else if (depth == 8) format = CAIRO_FORMAT_A8; else if (depth == 1) From 9bdb4f6ff713db0d101a0c0735dbb27e54fd7846 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Sun, 2 Apr 2006 15:55:27 +0200 Subject: [PATCH 080/155] Use more portable shell syntax Reported by Dave Yeo in http://lists.freedesktop.org/archives/cairo/2006-April/006600.html Fixed for the other tests in 0883155111ab9597d335c7d43ae47c163b5c0e4d --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 44783bd29..020b394d1 100644 --- a/configure.in +++ b/configure.in @@ -810,6 +810,6 @@ if test x"$use_beos" = "xyes" ; then echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/BeOS/' fi -if test x"$use_directfb" == "xyes" ; then +if test x"$use_directfb" = "xyes" ; then echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/DirectFB/' fi From 57fe9b17b0a1a36acf0d8d524df05215ea48361f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 3 Apr 2006 15:26:17 -0700 Subject: [PATCH 081/155] Move base85 code out of cairo-output-stream.c into new cairo-base85-stream.c --- src/Makefile.am | 1 + src/cairo-base85-stream.c | 98 +++++++++++++++++++++++++++++++++++++++ src/cairo-output-stream.c | 63 ------------------------- 3 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 src/cairo-base85-stream.c diff --git a/src/Makefile.am b/src/Makefile.am index ad1856866..5b3d75f97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -134,6 +134,7 @@ libcairo_la_SOURCES = \ cairo-arc.c \ cairo-arc-private.h \ cairo-array.c \ + cairo-base85-stream.c \ cairo-cache.c \ cairo-cache-private.h \ cairo-clip.c \ diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c new file mode 100644 index 000000000..0bb6f320f --- /dev/null +++ b/src/cairo-base85-stream.c @@ -0,0 +1,98 @@ +/* cairo_output_stream.c: Output stream abstraction + * + * 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 cairo_output_stream.c as distributed with the + * cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Author(s): + * Kristian Høgsberg + */ + +#include "cairoint.h" + +static cairo_bool_t +_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5]) +{ + cairo_bool_t all_zero; + uint32_t value; + int digit, i; + + value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3]; + all_zero = TRUE; + for (i = 0; i < 5; i++) { + digit = value % 85; + if (digit != 0) + all_zero = FALSE; + five_tuple[4-i] = digit + 33; + value = value / 85; + } + return all_zero; +} + +void +_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, + const char *data, + size_t length) +{ + unsigned char *ptr; + unsigned char four_tuple[4]; + char five_tuple[5]; + int column; + + ptr = (unsigned char *)data; + column = 0; + while (length > 0) { + if (length >= 4) { + if (_convert_four_tuple (ptr, five_tuple)) { + column += 1; + _cairo_output_stream_write (stream, "z", 1); + } else { + column += 5; + _cairo_output_stream_write (stream, five_tuple, 5); + } + length -= 4; + ptr += 4; + } else { /* length < 4 */ + memset (four_tuple, 0, 4); + memcpy (four_tuple, ptr, length); + _convert_four_tuple (four_tuple, five_tuple); + column += length + 1; + _cairo_output_stream_write (stream, five_tuple, length + 1); + length = 0; + } + if (column >= 72) { + _cairo_output_stream_write (stream, "\n", 1); + column = 0; + } + } + + if (column > 0) { + _cairo_output_stream_write (stream, "\n", 1); + } +} diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 6fd61813a..b07423c10 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -114,69 +114,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, } } -static cairo_bool_t -convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5]) -{ - cairo_bool_t all_zero; - uint32_t value; - int digit, i; - - value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3]; - all_zero = TRUE; - for (i = 0; i < 5; i++) { - digit = value % 85; - if (digit != 0) - all_zero = FALSE; - five_tuple[4-i] = digit + 33; - value = value / 85; - } - return all_zero; -} - -void -_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, - const char *data, - size_t length) -{ - unsigned char *ptr; - unsigned char four_tuple[4]; - char five_tuple[5]; - int column; - - ptr = (unsigned char *)data; - column = 0; - while (length > 0) { - if (length >= 4) { - if (convert_four_tuple (ptr, five_tuple)) { - column += 1; - _cairo_output_stream_write (stream, "z", 1); - } else { - column += 5; - _cairo_output_stream_write (stream, five_tuple, 5); - } - length -= 4; - ptr += 4; - } else { /* length < 4 */ - memset (four_tuple, 0, 4); - memcpy (four_tuple, ptr, length); - convert_four_tuple (four_tuple, five_tuple); - column += length + 1; - _cairo_output_stream_write (stream, five_tuple, length + 1); - length = 0; - } - if (column >= 72) { - _cairo_output_stream_write (stream, "\n", 1); - column = 0; - } - } - - if (column > 0) { - _cairo_output_stream_write (stream, "\n", 1); - } -} - - - /* Format a double in a locale independent way and trim trailing * zeros. Based on code from Alex Larson . * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html From 5a06133eb2e13a4c0354dad7f7da414c85733c4e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 3 Apr 2006 23:44:51 -0700 Subject: [PATCH 082/155] Implement cairo-base85-stream as a filtering output stream not just a write function. Now _cairo_output_stream_create accepts a new close callback, (which the base85 stream uses to write its trailer). This eliminates the former kludge used to fclose the stdio output streams, and required a bit of touchup to the pdf, ps, and svg-surface usage of streams. --- src/cairo-base85-stream.c | 144 +++++++++++++++++++++++++++----------- src/cairo-output-stream.c | 52 ++++++++------ src/cairo-pdf-surface.c | 2 +- src/cairo-ps-surface.c | 22 ++++-- src/cairo-svg-surface.c | 2 +- src/cairoint.h | 23 ++++-- 6 files changed, 170 insertions(+), 75 deletions(-) diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c index 0bb6f320f..6adfa1668 100644 --- a/src/cairo-base85-stream.c +++ b/src/cairo-base85-stream.c @@ -36,63 +36,125 @@ #include "cairoint.h" -static cairo_bool_t -_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5]) +typedef struct _cairo_base85_stream { + cairo_output_stream_t *output; + unsigned char four_tuple[4]; + int pending; + int column; +} cairo_base85_stream_t; + +static void +_expand_four_tuple_to_five (unsigned char four_tuple[4], + unsigned char five_tuple[5], + cairo_bool_t *all_zero) { - cairo_bool_t all_zero; uint32_t value; int digit, i; value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3]; - all_zero = TRUE; + if (all_zero) + *all_zero = TRUE; for (i = 0; i < 5; i++) { digit = value % 85; - if (digit != 0) - all_zero = FALSE; + if (digit != 0 && all_zero) + *all_zero = FALSE; five_tuple[4-i] = digit + 33; value = value / 85; } - return all_zero; } -void -_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, - const char *data, - size_t length) +static cairo_status_t +_cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream) { - unsigned char *ptr; - unsigned char four_tuple[4]; - char five_tuple[5]; - int column; - - ptr = (unsigned char *)data; - column = 0; - while (length > 0) { - if (length >= 4) { - if (_convert_four_tuple (ptr, five_tuple)) { - column += 1; - _cairo_output_stream_write (stream, "z", 1); + cairo_status_t status; + + if (stream->column >= 72) { + status = _cairo_output_stream_write (stream->output, "\n", 1); + if (status) + return status; + stream->column = 0; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_base85_stream_write_data (void *closure, + const unsigned char *data, + unsigned int length) +{ + cairo_status_t status; + cairo_base85_stream_t *stream = closure; + const unsigned char *ptr = data; + unsigned char five_tuple[5]; + cairo_bool_t is_zero; + + while (length) { + stream->four_tuple[stream->pending++] = *ptr++; + length--; + if (stream->pending == 4) { + _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero); + if (is_zero) { + status = _cairo_output_stream_write (stream->output, "z", 1); + stream->column += 1; } else { - column += 5; - _cairo_output_stream_write (stream, five_tuple, 5); + status = _cairo_output_stream_write (stream->output, five_tuple, 5); + stream->column += 5; } - length -= 4; - ptr += 4; - } else { /* length < 4 */ - memset (four_tuple, 0, 4); - memcpy (four_tuple, ptr, length); - _convert_four_tuple (four_tuple, five_tuple); - column += length + 1; - _cairo_output_stream_write (stream, five_tuple, length + 1); - length = 0; - } - if (column >= 72) { - _cairo_output_stream_write (stream, "\n", 1); - column = 0; + if (status) + return status; + status = _cairo_base85_wrap_perhaps (stream); + if (status) + return status; + stream->pending = 0; } } - if (column > 0) { - _cairo_output_stream_write (stream, "\n", 1); - } + return CAIRO_STATUS_SUCCESS; } + +static cairo_status_t +_cairo_base85_stream_close (void *closure) +{ + cairo_status_t status; + cairo_base85_stream_t *stream = closure; + unsigned char five_tuple[5]; + + if (stream->pending) { + memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending); + _expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL); + status = _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1); + if (status) + return status; + stream->column += stream->pending + 1; + status = _cairo_base85_wrap_perhaps (stream); + if (status) + return status; + } + + /* Mark end of base85 data */ + status = _cairo_output_stream_printf (stream->output, "~>\n"); + if (status) + return status; + + return CAIRO_STATUS_SUCCESS; +} + +cairo_output_stream_t * +_cairo_base85_stream_create (cairo_output_stream_t *output) +{ + cairo_base85_stream_t *stream; + + stream = malloc (sizeof (cairo_base85_stream_t)); + if (stream == NULL) + return NULL; + + stream->output = output; + stream->pending = 0; + stream->column = 0; + + return _cairo_output_stream_create (_cairo_base85_stream_write_data, + _cairo_base85_stream_close, + stream); +} + diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index b07423c10..1ed569c96 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -45,14 +45,15 @@ struct _cairo_output_stream { cairo_write_func_t write_data; + cairo_close_func_t close_func; void *closure; - cairo_bool_t owns_closure_is_file; unsigned long position; cairo_status_t status; }; cairo_output_stream_t * _cairo_output_stream_create (cairo_write_func_t write_data, + cairo_close_func_t close_func, void *closure) { cairo_output_stream_t *stream; @@ -62,23 +63,25 @@ _cairo_output_stream_create (cairo_write_func_t write_data, return NULL; stream->write_data = write_data; + stream->close_func = close_func; stream->closure = closure; - stream->owns_closure_is_file = FALSE; stream->position = 0; stream->status = CAIRO_STATUS_SUCCESS; return stream; } -void +cairo_status_t _cairo_output_stream_destroy (cairo_output_stream_t *stream) { - if (stream->owns_closure_is_file) { - FILE *file = stream->closure; - fflush (file); - fclose (file); - } + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + if (stream->close_func) + status = stream->close_func (stream->closure); + free (stream); + + return status; } cairo_status_t @@ -286,30 +289,39 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream) static cairo_status_t stdio_write (void *closure, const unsigned char *data, unsigned int length) { - FILE *fp = closure; + FILE *file = closure; - if (fwrite (data, 1, length, fp) == length) - return CAIRO_STATUS_SUCCESS; + if (fwrite (data, 1, length, file) != length) + return CAIRO_STATUS_WRITE_ERROR; - return CAIRO_STATUS_WRITE_ERROR; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +stdio_close (void *closure) +{ + FILE *file = closure; + + fflush (file); + fclose (file); + + return CAIRO_STATUS_SUCCESS; } cairo_output_stream_t * _cairo_output_stream_create_for_file (const char *filename) { - FILE *fp; + FILE *file; cairo_output_stream_t *stream; - fp = fopen (filename, "wb"); - if (fp == NULL) + file = fopen (filename, "wb"); + if (file == NULL) return NULL; - stream = _cairo_output_stream_create (stdio_write, fp); + stream = _cairo_output_stream_create (stdio_write, stdio_close, file); - if (stream) - stream->owns_closure_is_file = TRUE; - else - fclose (fp); + if (stream == NULL) + fclose (file); return stream; } diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 6d18196b5..4a783b59f 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -335,7 +335,7 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write, { cairo_output_stream_t *stream; - stream = _cairo_output_stream_create (write, closure); + stream = _cairo_output_stream_create (write, NULL, closure); if (stream == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index a646d45ba..4242a1eb6 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -218,7 +218,7 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, { cairo_output_stream_t *stream; - stream = _cairo_output_stream_create (write_func, closure); + stream = _cairo_output_stream_create (write_func, NULL, closure); if (stream == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; @@ -667,6 +667,7 @@ emit_image (cairo_ps_surface_t *surface, cairo_pattern_union_t pattern; cairo_matrix_t d2i; int x, y, i; + cairo_output_stream_t *base85_stream; /* PostScript can not represent the alpha channel, so we blend the current image over a white RGB surface to eliminate it. */ @@ -756,12 +757,21 @@ emit_image (cairo_ps_surface_t *surface, d2i.x0, d2i.y0); /* Compressed image data (Base85 encoded) */ - _cairo_output_stream_write_base85_string (surface->stream, (char *)compressed, compressed_size); - status = CAIRO_STATUS_SUCCESS; + base85_stream = _cairo_base85_stream_create (surface->stream); + if (base85_stream == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + goto bail3; + } - /* Mark end of base85 data */ - _cairo_output_stream_printf (surface->stream, - "~>\n"); + status = _cairo_output_stream_write (base85_stream, compressed, compressed_size); + if (status) { + _cairo_output_stream_destroy (base85_stream); + goto bail3; + } + + status = _cairo_output_stream_destroy (base85_stream); + + bail3: free (compressed); bail2: free (rgb); diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index d4134084a..7c3846425 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -145,7 +145,7 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write, { cairo_output_stream_t *stream; - stream = _cairo_output_stream_create (write, closure); + stream = _cairo_output_stream_create (write, NULL, closure); if (stream == NULL) return NULL; diff --git a/src/cairoint.h b/src/cairoint.h index 3dc0f7e5e..4203599c1 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2124,11 +2124,23 @@ _cairo_utf8_to_utf16 (const unsigned char *str, typedef struct _cairo_output_stream cairo_output_stream_t; +/* We already have the following declared in cairo.h: + +typedef cairo_status_t (*cairo_write_func_t) (void *closure, + const unsigned char *data, + unsigned int length); +*/ +typedef cairo_status_t (*cairo_close_func_t) (void *closure); + cairo_private cairo_output_stream_t * _cairo_output_stream_create (cairo_write_func_t write_func, + cairo_close_func_t close_func, void *closure); -cairo_private void +/* Most cairo destroy functions don't return a status, but we do here + * to allow the return status from the close_func callback to be + * captured. */ +cairo_private cairo_status_t _cairo_output_stream_destroy (cairo_output_stream_t *stream); cairo_private cairo_status_t @@ -2140,11 +2152,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, const char *data, size_t length); -cairo_private void -_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream, - const char *data, - size_t length); - unsigned char * _cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out); @@ -2165,6 +2172,10 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream); cairo_private cairo_output_stream_t * _cairo_output_stream_create_for_file (const char *filename); +/* cairo_base85_stream.c */ +cairo_output_stream_t * +_cairo_base85_stream_create (cairo_output_stream_t *output); + cairo_private void _cairo_error (cairo_status_t status); From dd67cf6616c2e819e7e8e4452c1e14e68b4a66bd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 4 Apr 2006 10:45:38 -0700 Subject: [PATCH 083/155] Implement proper cairo-style error-handling for cairo_output_stream_t. The cairo_output_stream_t object already had an internal status value, but it was annoyingly returning status values from various functions. It also was missing proper shutdown-on-error as well as nil-create semantics. This fixes those shortcomings and adjusts all callers for the new semantics, (leading to simpler and more correct calling code---particularly in the case of cairo-base85-stream.c). --- src/cairo-base85-stream.c | 40 +++++-------------- src/cairo-output-stream.c | 84 +++++++++++++++++++++++++-------------- src/cairo-pdf-surface.c | 12 ++++-- src/cairo-ps-surface.c | 27 ++++++------- src/cairo-svg-surface.c | 16 ++++++-- src/cairoint.h | 35 ++++++++++++---- 6 files changed, 126 insertions(+), 88 deletions(-) diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c index 6adfa1668..4ea94ead9 100644 --- a/src/cairo-base85-stream.c +++ b/src/cairo-base85-stream.c @@ -63,19 +63,13 @@ _expand_four_tuple_to_five (unsigned char four_tuple[4], } } -static cairo_status_t +static void _cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream) { - cairo_status_t status; - if (stream->column >= 72) { - status = _cairo_output_stream_write (stream->output, "\n", 1); - if (status) - return status; + _cairo_output_stream_write (stream->output, "\n", 1); stream->column = 0; } - - return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -83,7 +77,6 @@ _cairo_base85_stream_write_data (void *closure, const unsigned char *data, unsigned int length) { - cairo_status_t status; cairo_base85_stream_t *stream = closure; const unsigned char *ptr = data; unsigned char five_tuple[5]; @@ -95,49 +88,38 @@ _cairo_base85_stream_write_data (void *closure, if (stream->pending == 4) { _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero); if (is_zero) { - status = _cairo_output_stream_write (stream->output, "z", 1); + _cairo_output_stream_write (stream->output, "z", 1); stream->column += 1; } else { - status = _cairo_output_stream_write (stream->output, five_tuple, 5); + _cairo_output_stream_write (stream->output, five_tuple, 5); stream->column += 5; } - if (status) - return status; - status = _cairo_base85_wrap_perhaps (stream); - if (status) - return status; + _cairo_base85_wrap_perhaps (stream); stream->pending = 0; } } - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (stream->output); } static cairo_status_t _cairo_base85_stream_close (void *closure) { - cairo_status_t status; cairo_base85_stream_t *stream = closure; unsigned char five_tuple[5]; if (stream->pending) { memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending); _expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL); - status = _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1); - if (status) - return status; + _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1); stream->column += stream->pending + 1; - status = _cairo_base85_wrap_perhaps (stream); - if (status) - return status; + _cairo_base85_wrap_perhaps (stream); } /* Mark end of base85 data */ - status = _cairo_output_stream_printf (stream->output, "~>\n"); - if (status) - return status; + _cairo_output_stream_printf (stream->output, "~>\n"); - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (stream->output); } cairo_output_stream_t * @@ -147,7 +129,7 @@ _cairo_base85_stream_create (cairo_output_stream_t *output) stream = malloc (sizeof (cairo_base85_stream_t)); if (stream == NULL) - return NULL; + return (cairo_output_stream_t *) &cairo_output_stream_nil; stream->output = output; stream->pending = 0; diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 1ed569c96..adc00b86a 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -49,6 +49,25 @@ struct _cairo_output_stream { void *closure; unsigned long position; cairo_status_t status; + cairo_bool_t closed; +}; + +const cairo_output_stream_t cairo_output_stream_nil = { + NULL, /* write_data */ + NULL, /* close_func */ + NULL, /* closure */ + 0, /* position */ + CAIRO_STATUS_NO_MEMORY, + FALSE /* closed */ +}; + +static const cairo_output_stream_t cairo_output_stream_nil_write_error = { + NULL, /* write_data */ + NULL, /* close_func */ + NULL, /* closure */ + 0, /* position */ + CAIRO_STATUS_WRITE_ERROR, + FALSE /* closed */ }; cairo_output_stream_t * @@ -60,41 +79,54 @@ _cairo_output_stream_create (cairo_write_func_t write_data, stream = malloc (sizeof (cairo_output_stream_t)); if (stream == NULL) - return NULL; + return (cairo_output_stream_t *) &cairo_output_stream_nil; stream->write_data = write_data; stream->close_func = close_func; stream->closure = closure; stream->position = 0; stream->status = CAIRO_STATUS_SUCCESS; + stream->closed = FALSE; return stream; } -cairo_status_t -_cairo_output_stream_destroy (cairo_output_stream_t *stream) +void +_cairo_output_stream_close (cairo_output_stream_t *stream) { - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status; - if (stream->close_func) + if (stream->closed) + return; + + if (stream->close_func) { status = stream->close_func (stream->closure); + if (status) + stream->status = status; + } - free (stream); - - return status; + stream->closed = TRUE; } -cairo_status_t +void +_cairo_output_stream_destroy (cairo_output_stream_t *stream) +{ + _cairo_output_stream_close (stream); + free (stream); +} + +void _cairo_output_stream_write (cairo_output_stream_t *stream, const void *data, size_t length) { if (length == 0) - return CAIRO_STATUS_SUCCESS; + return; + + if (stream->status) + return; stream->status = stream->write_data (stream->closure, data, length); stream->position += length; - - return stream->status; } void @@ -106,6 +138,9 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, char buffer[2]; int i, column; + if (stream->status) + return; + for (i = 0, column = 0; i < length; i++, column++) { if (column == 38) { _cairo_output_stream_write (stream, "\n", 1); @@ -178,8 +213,7 @@ enum { * formatting. This functionality is only for internal use and we * only implement the formats we actually use. */ - -cairo_status_t +void _cairo_output_stream_vprintf (cairo_output_stream_t *stream, const char *fmt, va_list ap) { @@ -188,6 +222,9 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream, const char *f; int length_modifier; + if (stream->status) + return; + f = fmt; p = buffer; while (*f != '\0') { @@ -250,24 +287,19 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream, } _cairo_output_stream_write (stream, buffer, p - buffer); - - return stream->status; } -cairo_status_t +void _cairo_output_stream_printf (cairo_output_stream_t *stream, const char *fmt, ...) { va_list ap; - cairo_status_t status; va_start (ap, fmt); - status = _cairo_output_stream_vprintf (stream, fmt, ap); + _cairo_output_stream_vprintf (stream, fmt, ap); va_end (ap); - - return status; } long @@ -312,16 +344,10 @@ cairo_output_stream_t * _cairo_output_stream_create_for_file (const char *filename) { FILE *file; - cairo_output_stream_t *stream; file = fopen (filename, "wb"); if (file == NULL) - return NULL; + return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error; - stream = _cairo_output_stream_create (stdio_write, stdio_close, file); - - if (stream == NULL) - fclose (file); - - return stream; + return _cairo_output_stream_create (stdio_write, stdio_close, file); } diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 4a783b59f..cbccd646c 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -333,11 +333,13 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write, double width_in_points, double height_in_points) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write, NULL, closure); - if (stream == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -368,11 +370,13 @@ cairo_pdf_surface_create (const char *filename, double width_in_points, double height_in_points) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_file (filename); - if (stream == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 4242a1eb6..7689205b9 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -178,11 +178,13 @@ cairo_ps_surface_create (const char *filename, double width_in_points, double height_in_points) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_file (filename); - if (stream == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -216,11 +218,13 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, double width_in_points, double height_in_points) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write_func, NULL, closure); - if (stream == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -758,18 +762,13 @@ emit_image (cairo_ps_surface_t *surface, /* Compressed image data (Base85 encoded) */ base85_stream = _cairo_base85_stream_create (surface->stream); - if (base85_stream == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto bail3; - } - status = _cairo_output_stream_write (base85_stream, compressed, compressed_size); - if (status) { - _cairo_output_stream_destroy (base85_stream); - goto bail3; - } + _cairo_output_stream_write (base85_stream, compressed, compressed_size); + _cairo_output_stream_close (base85_stream); - status = _cairo_output_stream_destroy (base85_stream); + status = _cairo_output_stream_get_status (base85_stream); + + _cairo_output_stream_destroy (base85_stream); bail3: free (compressed); diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 7c3846425..253055aea 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -143,11 +143,15 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write, double width, double height) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write, NULL, closure); - if (stream == NULL) - return NULL; + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); + return (cairo_surface_t *) &cairo_surface_nil; + } return _cairo_svg_surface_create_for_stream_internal (stream, width, height); } @@ -157,11 +161,15 @@ cairo_svg_surface_create (const char *filename, double width, double height) { + cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_file (filename); - if (stream == NULL) - return NULL; + status = _cairo_output_stream_get_status (stream); + if (status) { + _cairo_error (status); + return (cairo_surface_t *) &cairo_surface_nil; + } return _cairo_svg_surface_create_for_stream_internal (stream, width, height); } diff --git a/src/cairoint.h b/src/cairoint.h index 4203599c1..37998b77f 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2124,6 +2124,8 @@ _cairo_utf8_to_utf16 (const unsigned char *str, typedef struct _cairo_output_stream cairo_output_stream_t; +extern const cairo_private cairo_output_stream_t cairo_output_stream_nil; + /* We already have the following declared in cairo.h: typedef cairo_status_t (*cairo_write_func_t) (void *closure, @@ -2132,18 +2134,27 @@ typedef cairo_status_t (*cairo_write_func_t) (void *closure, */ typedef cairo_status_t (*cairo_close_func_t) (void *closure); + +/* This function never returns NULL. If an error occurs (NO_MEMORY) + * while trying to create the output stream this function returns a + * valid pointer to a nil output stream. + * + * Note that even with a nil surface, the close_func callback will be + * called by a call to _cairo_output_stream_close or + * _cairo_output_stream_destroy. + */ cairo_private cairo_output_stream_t * _cairo_output_stream_create (cairo_write_func_t write_func, cairo_close_func_t close_func, void *closure); -/* Most cairo destroy functions don't return a status, but we do here - * to allow the return status from the close_func callback to be - * captured. */ -cairo_private cairo_status_t +cairo_private void +_cairo_output_stream_close (cairo_output_stream_t *stream); + +cairo_private void _cairo_output_stream_destroy (cairo_output_stream_t *stream); -cairo_private cairo_status_t +cairo_private void _cairo_output_stream_write (cairo_output_stream_t *stream, const void *data, size_t length); @@ -2152,14 +2163,14 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, const char *data, size_t length); -unsigned char * +cairo_private unsigned char * _cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out); -cairo_private cairo_status_t +cairo_private void _cairo_output_stream_vprintf (cairo_output_stream_t *stream, const char *fmt, va_list ap); -cairo_private cairo_status_t +cairo_private void _cairo_output_stream_printf (cairo_output_stream_t *stream, const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3); @@ -2169,6 +2180,14 @@ _cairo_output_stream_get_position (cairo_output_stream_t *status); cairo_private cairo_status_t _cairo_output_stream_get_status (cairo_output_stream_t *stream); +/* This function never returns NULL. If an error occurs (NO_MEMORY or + * WRITE_ERROR) while trying to create the output stream this function + * returns a valid pointer to a nil output stream. + * + * NOTE: Even if a nil surface is returned, the caller should still + * call _cairo_output_stream_destroy (or _cairo_output_stream_close at + * least) in order to ensure that everything is properly cleaned up. + */ cairo_private cairo_output_stream_t * _cairo_output_stream_create_for_file (const char *filename); From 0114393a132471cbf87bc3abc2f298b4ca38c69c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 4 Apr 2006 11:17:25 -0700 Subject: [PATCH 084/155] Explicitly remove the output png image before creating it during testing. What was happening here is that some backends (such as the PS surface backend) directly generate an output file, and then run a conversion process to generate the png file. Some bugs were such that a broken file would successfully be generated, the conversion would fail (the failure was unnoticed), and the test suite would happily verify the old image from a previously successful run. This fix eliminates this source of false positives. --- test/cairo-test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cairo-test.c b/test/cairo-test.c index d782a92f4..928ab6363 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1440,6 +1440,7 @@ cairo_test_for_target (cairo_test_t *test, /* Skip image check for tests with no image (width,height == 0,0) */ if (test->width != 0 && test->height != 0) { int pixels_changed; + xunlink (png_name); (target->write_to_png) (surface, png_name); if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) pixels_changed = image_diff_flattened (png_name, ref_name, diff_name); From d1134cd7e25a78c70819df879336f895134bafe1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 4 Apr 2006 11:21:17 -0700 Subject: [PATCH 085/155] Emit images into PostScript output as strings rather than inline. This is a baby step toward having shared source patterns in the PostScript output. This patch is based on original work by Keith Packard in the following commit: 06b83b89fc4271060c63b284d7909162b92152f1 One problem with this approach is that it attempts to put an entire image into a PostScript string object. However, PostScript strings are typically limited to 65k bytes. So, as is, this commit causes a few failures for tests in the suite with large output images. --- src/cairo-ps-surface.c | 58 +++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 7689205b9..11e346d74 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -663,6 +663,18 @@ emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, cairo_matrix_t *matrix) { + /* Using a single name for all images is fine since we immediately + * use the image and never again reference it. Later calls will + * re-use the same name which will just store new image data under + * the same entries in the PostScript dictionaries. + * + * Eventually, we'll want to emit a shared image once into the + * PostScript output and re-use it. In order to do that, we'll + * need to support multiple images "in flight" at the same time, + * which means we'll need to have unique names here one way or + * another. + */ + const char name[] = "Fallback"; cairo_status_t status; unsigned char *rgb, *compressed; unsigned long rgb_size, compressed_size; @@ -736,6 +748,26 @@ emit_image (cairo_ps_surface_t *surface, goto bail2; } + /* First emit the image data as a base85-encoded string which will + * be used as the data source for the image operator later. */ + _cairo_output_stream_printf (surface->stream, + "/%sData\n", name); + _cairo_output_stream_printf (surface->stream, + "<~\n"); + base85_stream = _cairo_base85_stream_create (surface->stream); + + _cairo_output_stream_write (base85_stream, compressed, compressed_size); + _cairo_output_stream_close (base85_stream); + + status = _cairo_output_stream_get_status (base85_stream); + if (status) + goto bail3; + + _cairo_output_stream_destroy (base85_stream); + + _cairo_output_stream_printf (surface->stream, + " def\n"); + /* matrix transforms from user space to image space. We need to * transform from device space to image space to compensate for * postscripts coordinate system. */ @@ -743,32 +775,28 @@ emit_image (cairo_ps_surface_t *surface, cairo_matrix_multiply (&d2i, &d2i, matrix); _cairo_output_stream_printf (surface->stream, - "/DeviceRGB setcolorspace\n" - "<<\n" + "/%sImage {\n" + " /DeviceRGB setcolorspace\n" + " <<\n" " /ImageType 1\n" " /Width %d\n" " /Height %d\n" " /BitsPerComponent 8\n" " /Decode [ 0 1 0 1 0 1 ]\n" - " /DataSource currentfile /ASCII85Decode filter /LZWDecode filter \n" + " /DataSource %sData /LZWDecode filter \n" " /ImageMatrix [ %f %f %f %f %f %f ]\n" - ">>\n" - "image\n", + " >>\n" + " image\n" + "} def\n", + name, opaque_image->width, opaque_image->height, + name, d2i.xx, d2i.yx, d2i.xy, d2i.yy, d2i.x0, d2i.y0); - - /* Compressed image data (Base85 encoded) */ - base85_stream = _cairo_base85_stream_create (surface->stream); - - _cairo_output_stream_write (base85_stream, compressed, compressed_size); - _cairo_output_stream_close (base85_stream); - - status = _cairo_output_stream_get_status (base85_stream); - - _cairo_output_stream_destroy (base85_stream); + _cairo_output_stream_printf (surface->stream, + "%sImage\n", name); bail3: free (compressed); From 45bbdf94cbac736c9f854012581e8f914a6e27df Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 4 Apr 2006 12:50:44 -0700 Subject: [PATCH 086/155] Break PostScript image data into chunks that each fit into a string. This solves the problem with the previous commit that made strings longer than the "standard" 65k implementation limit for strings. It's achieved by removing the line-wrapping from the base85 stream and instead adding a new string-array stream between the base85 stream and the output stream (the string-array stream does the line wrapping and enforces the 65k characters per string limit). --- src/cairo-base85-stream.c | 30 +++------ src/cairo-ps-surface.c | 129 +++++++++++++++++++++++++++++++++----- 2 files changed, 124 insertions(+), 35 deletions(-) diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c index 4ea94ead9..bd1a7ac7e 100644 --- a/src/cairo-base85-stream.c +++ b/src/cairo-base85-stream.c @@ -40,7 +40,6 @@ typedef struct _cairo_base85_stream { cairo_output_stream_t *output; unsigned char four_tuple[4]; int pending; - int column; } cairo_base85_stream_t; static void @@ -63,15 +62,6 @@ _expand_four_tuple_to_five (unsigned char four_tuple[4], } } -static void -_cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream) -{ - if (stream->column >= 72) { - _cairo_output_stream_write (stream->output, "\n", 1); - stream->column = 0; - } -} - static cairo_status_t _cairo_base85_stream_write_data (void *closure, const unsigned char *data, @@ -87,14 +77,10 @@ _cairo_base85_stream_write_data (void *closure, length--; if (stream->pending == 4) { _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero); - if (is_zero) { + if (is_zero) _cairo_output_stream_write (stream->output, "z", 1); - stream->column += 1; - } else { + else _cairo_output_stream_write (stream->output, five_tuple, 5); - stream->column += 5; - } - _cairo_base85_wrap_perhaps (stream); stream->pending = 0; } } @@ -105,6 +91,7 @@ _cairo_base85_stream_write_data (void *closure, static cairo_status_t _cairo_base85_stream_close (void *closure) { + cairo_status_t status; cairo_base85_stream_t *stream = closure; unsigned char five_tuple[5]; @@ -112,14 +99,16 @@ _cairo_base85_stream_close (void *closure) memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending); _expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL); _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1); - stream->column += stream->pending + 1; - _cairo_base85_wrap_perhaps (stream); } /* Mark end of base85 data */ - _cairo_output_stream_printf (stream->output, "~>\n"); + _cairo_output_stream_printf (stream->output, "~>"); - return _cairo_output_stream_get_status (stream->output); + status = _cairo_output_stream_get_status (stream->output); + + free (stream); + + return status; } cairo_output_stream_t * @@ -133,7 +122,6 @@ _cairo_base85_stream_create (cairo_output_stream_t *output) stream->output = output; stream->pending = 0; - stream->column = 0; return _cairo_output_stream_create (_cairo_base85_stream_write_data, _cairo_base85_stream_close, diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 11e346d74..99a10217e 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -655,6 +655,104 @@ pattern_operation_needs_fallback (cairo_operator_t op, return pattern_is_translucent (pattern); } +/* The "standard" implementation limit for PostScript string sizes is + * 65535 characters (see PostScript Language Reference, Appendix + * B). We go one short of that because we sometimes need two + * characters in a string to represent a single ASCII85 byte, (for the + * escape sequences "\\", "\(", and "\)") and we must not split these + * across two strings. So we'd be in trouble if we went right to the + * limit and one of these escape sequences just happened to land at + * the end. + */ +#define STRING_ARRAY_MAX_STRING_SIZE (65535-1) +#define STRING_ARRAY_MAX_COLUMN 72 + +typedef struct _string_array_stream { + cairo_output_stream_t *output; + int column; + int string_size; +} string_array_stream_t; + +static cairo_status_t +_string_array_stream_write (void *closure, + const unsigned char *data, + unsigned int length) +{ + string_array_stream_t *stream = closure; + unsigned char c; + const unsigned char backslash = '\\'; + + if (length == 0) + return CAIRO_STATUS_SUCCESS; + + while (length--) { + if (stream->string_size == 0) { + _cairo_output_stream_printf (stream->output, "("); + stream->column++; + } + + c = *data++; + switch (c) { + case '\\': + case '(': + case ')': + _cairo_output_stream_write (stream->output, &backslash, 1); + stream->column++; + stream->string_size++; + break; + } + _cairo_output_stream_write (stream->output, &c, 1); + stream->column++; + stream->string_size++; + + if (stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) { + _cairo_output_stream_printf (stream->output, ")\n"); + stream->string_size = 0; + stream->column = 0; + } + if (stream->column >= STRING_ARRAY_MAX_COLUMN) { + _cairo_output_stream_printf (stream->output, "\n "); + stream->string_size += 2; + stream->column = 1; + } + } + + return _cairo_output_stream_get_status (stream->output); +} + +static cairo_status_t +_string_array_stream_close (void *closure) +{ + cairo_status_t status; + string_array_stream_t *stream = closure; + + _cairo_output_stream_printf (stream->output, ")\n"); + + status = _cairo_output_stream_get_status (stream->output); + + free (stream); + + return status; +} + +static cairo_output_stream_t * +_string_array_stream_create (cairo_output_stream_t *output) +{ + string_array_stream_t *stream; + + stream = malloc (sizeof (string_array_stream_t)); + if (stream == NULL) + return (cairo_output_stream_t *) &cairo_output_stream_nil; + + stream->output = output; + stream->column = 0; + stream->string_size = 0; + + return _cairo_output_stream_create (_string_array_stream_write, + _string_array_stream_close, + stream); +} + /* PS Output - this section handles output of the parts of the meta * surface we can render natively in PS. */ @@ -683,7 +781,7 @@ emit_image (cairo_ps_surface_t *surface, cairo_pattern_union_t pattern; cairo_matrix_t d2i; int x, y, i; - cairo_output_stream_t *base85_stream; + cairo_output_stream_t *base85_stream, *string_array_stream; /* PostScript can not represent the alpha channel, so we blend the current image over a white RGB surface to eliminate it. */ @@ -741,6 +839,8 @@ emit_image (cairo_ps_surface_t *surface, } } + /* XXX: Should fix cairo-lzw to provide a stream-based interface + * instead. */ compressed_size = rgb_size; compressed = _cairo_lzw_compress (rgb, &compressed_size); if (compressed == NULL) { @@ -751,22 +851,20 @@ emit_image (cairo_ps_surface_t *surface, /* First emit the image data as a base85-encoded string which will * be used as the data source for the image operator later. */ _cairo_output_stream_printf (surface->stream, - "/%sData\n", name); - _cairo_output_stream_printf (surface->stream, - "<~\n"); - base85_stream = _cairo_base85_stream_create (surface->stream); + "/%sData [\n", name); + + string_array_stream = _string_array_stream_create (surface->stream); + base85_stream = _cairo_base85_stream_create (string_array_stream); _cairo_output_stream_write (base85_stream, compressed, compressed_size); - _cairo_output_stream_close (base85_stream); - - status = _cairo_output_stream_get_status (base85_stream); - if (status) - goto bail3; _cairo_output_stream_destroy (base85_stream); + _cairo_output_stream_destroy (string_array_stream); _cairo_output_stream_printf (surface->stream, - " def\n"); + "] def\n"); + _cairo_output_stream_printf (surface->stream, + "/%sDataIndex 0 def\n", name); /* matrix transforms from user space to image space. We need to * transform from device space to image space to compensate for @@ -783,7 +881,11 @@ emit_image (cairo_ps_surface_t *surface, " /Height %d\n" " /BitsPerComponent 8\n" " /Decode [ 0 1 0 1 0 1 ]\n" - " /DataSource %sData /LZWDecode filter \n" + " /DataSource {\n" + " %sData %sDataIndex get\n" + " /%sDataIndex %sDataIndex 1 add def\n" + " %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n" + " } /ASCII85Decode filter /LZWDecode filter\n" " /ImageMatrix [ %f %f %f %f %f %f ]\n" " >>\n" " image\n" @@ -791,14 +893,13 @@ emit_image (cairo_ps_surface_t *surface, name, opaque_image->width, opaque_image->height, - name, + name, name, name, name, name, name, name, d2i.xx, d2i.yx, d2i.xy, d2i.yy, d2i.x0, d2i.y0); _cairo_output_stream_printf (surface->stream, "%sImage\n", name); - bail3: free (compressed); bail2: free (rgb); From a8e5a77ad496c1716acdd279d5d5bebf1bc71eee Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 23 Mar 2006 16:02:02 -0800 Subject: [PATCH 087/155] Add attribution for Bdale Garbee to the AUTHORS file. --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index e6f0863c3..ad0b97cfb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,7 @@ John Ehresman Build fixes for win32 John Ellson First font/glyph extents functions Behdad Esfahbod Release script improvements, bug fixes. Bertram Felgenhauer Fixes for subtle arithmetic errors +Bdale Garbee Provided essential support for cairo achitecture sessions J. Ali Harlow win32 backend updates Richard Henderson "slim" macros for better shared libraries James Henstridge Build fixes related to freetype From 5baae7ff21a4236ebc9eaff087eb29fd1432c7ff Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Wed, 5 Apr 2006 21:24:06 +0200 Subject: [PATCH 088/155] SVG: Fix typo and stream status handling --- src/cairo-svg-surface.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 253055aea..21d73f693 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -150,7 +150,7 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write, status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); - return (cairo_surface_t *) &cairo_surface_nil; + return (cairo_surface_t *) &_cairo_surface_nil; } return _cairo_svg_surface_create_for_stream_internal (stream, width, height); @@ -168,7 +168,7 @@ cairo_svg_surface_create (const char *filename, status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); - return (cairo_surface_t *) &cairo_surface_nil; + return (cairo_surface_t *) &_cairo_surface_nil; } return _cairo_svg_surface_create_for_stream_internal (stream, width, height); @@ -1355,13 +1355,18 @@ _cairo_svg_document_write (cairo_output_stream_t *output_stream, const char * buffer, int len) { - if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS) + cairo_status_t status; + + _cairo_output_stream_write (output_stream, buffer, len); + status = _cairo_output_stream_get_status (output_stream); + if (status) { + _cairo_error (status); return -1; + } return len; } - static cairo_status_t _cairo_svg_document_finish (cairo_svg_document_t *document) { From 341d61cda0247eebd26da1e3b71c43ee8f761833 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 5 Apr 2006 16:55:51 -0700 Subject: [PATCH 089/155] Disable show-glyphs-many test to avoid abusing ghostscript too badly. --- test/Makefile.am | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index f1fe6f512..d3e722a8a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,4 +1,4 @@ -# All test cases go here +# Here are all the tests that are run unconditionally TESTS = \ a8-mask \ caps-joins \ @@ -44,7 +44,6 @@ select-font-no-show-text \ self-copy \ self-intersecting \ set-source \ -show-glyphs-many \ show-text-current-point \ source-clip \ source-surface-scale-paint \ @@ -64,6 +63,8 @@ unbounded-operator \ user-data \ rel-path +# Then we have a collection of tests that are only run if certain +# features are compiled into cairo if HAVE_PTHREAD TESTS += pthread-show-text endif @@ -84,6 +85,23 @@ if CAIRO_HAS_MULTI_PAGE_SURFACES TESTS += multi-page endif +# XXX: Here are some existing tests that are currently disabled for +# one reason or another. +# +# show-glyphs-many - this stress test was exercising a particular bug +# in the xlib surface code (exceeding the X11 protocol request +# limit) when rendering several thousand glyphs at once. The +# original xlib-surface bug is fixed now, but the test continues +# to stress some other aspects of the test suite. For example, +# when doing text as paths, the resuilting PostScript file is one +# giant path that ghostscript has a particularly hard time +# with. I'm disabling this test for now, since I don't care about +# that performance problem in ghostscript. (But, there is a +# similar performance problem when using cairo to rasterize the +# equivalen giant path---from an SBG files say---so this might be +# a useful kind of test to bring back again for performance (not +# correctness) testing. + # All tests which have a reference image go here. # I really don't like having to repeat this list. Anyone know a good # way to avoid it? Can I use a wildcard here? From 6d5627ca2a5b96edf0b37fe6e16002726f72d86d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 5 Apr 2006 17:00:13 -0700 Subject: [PATCH 090/155] Add a call to _cairo_ps_surface_start_page in _cairo_ps_surface_intersect_clip_path. If clipping occurs before any drawing, then we still need to issue a start page call. Otherwise, the clip ends up being inverted since the scaling transformation that puts PostScript into a cairo-oriented coordinate system only happens in start_page. --- src/cairo-ps-surface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index c8f592539..a05fe40cf 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1095,6 +1095,9 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; + if (surface->need_start_page) + _cairo_ps_surface_start_page (surface); + _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_intersect_clip_path\n"); From 3b873c66be54522d6cc3f025572a78bbef0efba7 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 5 Apr 2006 17:03:23 -0700 Subject: [PATCH 091/155] Use ghostscript's pngalpha rather than png16m target for PS->PNG This target allows the output files to actually be transparent where there is no PostScript "ink", which allows for much better testing. --- test/cairo-test.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/cairo-test.c b/test/cairo-test.c index 0d8a9619d..f946b3e98 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1185,7 +1185,7 @@ ps_surface_write_to_png (cairo_surface_t *surface, const char *filename) } cairo_surface_finish (surface); - sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -sOutputFile=%s %s", + sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=%s %s", ptc->width, ptc->height, filename, ptc->filename); if (system (command) == 0) return CAIRO_STATUS_SUCCESS; @@ -1414,11 +1414,14 @@ cairo_test_for_target (cairo_test_t *test, /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ - cairo_save (cr); - cairo_set_source_rgba (cr, 0, 0, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_restore (cr); + /* XXX: We're cheating by not clearing the PostScript surface. */ + if (strcmp (target->name, "ps")) { + cairo_save (cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_restore (cr); + } status = (draw) (cr, test->width, test->height); From e01047a76a5c44302c24e2ab285cf1b1cd490677 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 5 Apr 2006 17:15:48 -0700 Subject: [PATCH 092/155] Build fix for typo from recent commit. --- test/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Makefile.am b/test/Makefile.am index d3e722a8a..b951b4392 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -350,7 +350,6 @@ select_font_no_show_text_LDADD = $(LDADDS) self_copy_LDADD = $(LDADDS) self_intersecting_LDADD = $(LDADDS) set_source_LDADD = $(LDADDS) -show_glyphs_many_LDADD = $(LDADDS) show_text_current_point_LDADD = $(LDADDS) source_clip_LDADD = $(LDADDS) source_surface_scale_paint_LDADD = $(LDADDS) From c4fc7b06b53c811ddc20def91aaccd756c28a924 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 6 Apr 2006 08:54:59 -0700 Subject: [PATCH 093/155] Revert "Use ghostscript's pngalpha rather than png16m target for PS->PNG" This reverts 3b873c66be54522d6cc3f025572a78bbef0efba7 commit. It seemed like a good idea at the time, but... The pngalpha target only gets the fully transparent regions correct. But we still need to get the partially translucent regions correct. The pngalpha target doesn't help here---instead we were already flattening the reference image during testing. And in that case, having anything other than alpha==1 in the output png doesn't really help, (and meanwhile it was tripping up the current buffer_diff code). --- test/cairo-test.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/cairo-test.c b/test/cairo-test.c index f946b3e98..0d8a9619d 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1185,7 +1185,7 @@ ps_surface_write_to_png (cairo_surface_t *surface, const char *filename) } cairo_surface_finish (surface); - sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=%s %s", + sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -sOutputFile=%s %s", ptc->width, ptc->height, filename, ptc->filename); if (system (command) == 0) return CAIRO_STATUS_SUCCESS; @@ -1414,14 +1414,11 @@ cairo_test_for_target (cairo_test_t *test, /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ - /* XXX: We're cheating by not clearing the PostScript surface. */ - if (strcmp (target->name, "ps")) { - cairo_save (cr); - cairo_set_source_rgba (cr, 0, 0, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_restore (cr); - } + cairo_save (cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_restore (cr); status = (draw) (cr, test->width, test->height); From b87726ee2aa0220b66ee4d97513c0ac89ffc4621 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 6 Apr 2006 09:43:39 -0700 Subject: [PATCH 094/155] Tweak initial erase so it doesn't trigger fallbacks for every PS test case. Add an optimization to cairo-ps-surface.c so that it ignores any CAIRO_OPERATOR_CLEAR drawing operation that occurs on a blank page. Also change the test suite to erase with OPERATOR_CLEAR instead of OPERATOR_SOURCE with an all-0 source pattern. With this change, 32 of the 61 test cases change from all-fallback to all-native for the ps backend. Of these 32 test cases, 13 pass the test suite with the original reference images. Another 18 cases differ only in the single-pixel boundary of objects due to cairo vs. ghostscript rasterization differences. We ignore these by adding new ps-specific reference images, (included in this commit). Finally, there appears to be one genuine failure, (dash-caps-joins), in which the PostScript dashes (at least as rendered by ghostscript) differ significantly from the cairo-rendered dashes. --- src/cairo-ps-surface.c | 69 +++++++++++++----- test/cairo-test.c | 3 +- test/caps-joins-ps-argb32-ref.png | Bin 0 -> 995 bytes test/caps-sub-paths-ps-argb32-ref.png | Bin 0 -> 170 bytes test/clip-fill-rule-ps-argb32-ref.png | Bin 0 -> 280 bytes test/clip-nesting-ps-argb32-ref.png | Bin 0 -> 488 bytes test/clip-twice-ps-argb32-ref.png | Bin 0 -> 460 bytes test/dash-offset-negative-ps-argb32-ref.png | Bin 0 -> 170 bytes test/fill-and-stroke-ps-argb32-ref.png | Bin 0 -> 243 bytes test/fill-rule-ps-argb32-ref.png | Bin 0 -> 1078 bytes test/leaky-polygon-ps-argb32-ref.png | Bin 0 -> 233 bytes test/line-width-ps-argb32-ref.png | Bin 0 -> 201 bytes test/path-data-ps-argb32-ref.png | Bin 0 -> 322 bytes ...rectangle-rounding-error-ps-argb32-ref.png | Bin 0 -> 258 bytes .../show-text-current-point-ps-argb32-ref.png | Bin 0 -> 638 bytes test/text-antialias-gray-ps-argb32-ref.png | Bin 0 -> 305 bytes test/text-antialias-none-ps-argb32-ref.png | Bin 0 -> 305 bytes .../text-antialias-subpixel-ps-argb32-ref.png | Bin 0 -> 305 bytes test/transforms-ps-argb32-ref.png | Bin 0 -> 287 bytes test/unantialiased-shapes-ps-argb32-ref.png | Bin 0 -> 4076 bytes 20 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 test/caps-joins-ps-argb32-ref.png create mode 100644 test/caps-sub-paths-ps-argb32-ref.png create mode 100644 test/clip-fill-rule-ps-argb32-ref.png create mode 100644 test/clip-nesting-ps-argb32-ref.png create mode 100644 test/clip-twice-ps-argb32-ref.png create mode 100644 test/dash-offset-negative-ps-argb32-ref.png create mode 100644 test/fill-and-stroke-ps-argb32-ref.png create mode 100644 test/fill-rule-ps-argb32-ref.png create mode 100644 test/leaky-polygon-ps-argb32-ref.png create mode 100644 test/line-width-ps-argb32-ref.png create mode 100644 test/path-data-ps-argb32-ref.png create mode 100644 test/rectangle-rounding-error-ps-argb32-ref.png create mode 100644 test/show-text-current-point-ps-argb32-ref.png create mode 100644 test/text-antialias-gray-ps-argb32-ref.png create mode 100644 test/text-antialias-none-ps-argb32-ref.png create mode 100644 test/text-antialias-subpixel-ps-argb32-ref.png create mode 100644 test/transforms-ps-argb32-ref.png create mode 100644 test/unantialiased-shapes-ps-argb32-ref.png diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index a05fe40cf..8a3786871 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -624,7 +624,7 @@ operator_always_translucent (cairo_operator_t op) } static cairo_bool_t -pattern_surface_supported (const cairo_surface_pattern_t *pattern) +surface_pattern_supported (const cairo_surface_pattern_t *pattern) { if (pattern->surface->backend->acquire_source_image != NULL) return TRUE; @@ -637,29 +637,38 @@ pattern_supported (const cairo_pattern_t *pattern) if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) return TRUE; if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - return pattern_surface_supported ((const cairo_surface_pattern_t *) pattern); + return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern); return FALSE; } -static cairo_bool_t -pattern_operation_supported (cairo_operator_t op, - const cairo_pattern_t *pattern) +static cairo_int_status_t +operation_supported (cairo_ps_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern) { + /* As a special-case, (see all drawing operations below), we + * optimize away any erasing where nothing has been drawn yet. */ + if (surface->need_start_page && op == CAIRO_OPERATOR_CLEAR) + return TRUE; + if (! pattern_supported (pattern)) return FALSE; + if (operator_always_opaque (op)) return TRUE; if (operator_always_translucent (op)) return FALSE; + return pattern_is_opaque (pattern); } static cairo_int_status_t -pattern_operation_analyze (cairo_operator_t op, - const cairo_pattern_t *pattern) +_analyze_operation (cairo_ps_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern) { - if (pattern_operation_supported (op, pattern)) + if (operation_supported (surface, op, pattern)) return CAIRO_STATUS_SUCCESS; else return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1177,8 +1186,12 @@ _cairo_ps_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, if (surface->fallback) return CAIRO_STATUS_SUCCESS; - if (surface->need_start_page) + if (surface->need_start_page) { + /* Optimize away erasing of nothing. */ + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; _cairo_ps_surface_start_page (surface); + } /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */ if (! _cairo_scaled_font_is_ft (scaled_font)) @@ -1237,7 +1250,7 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_ps_surface_path_info_t info; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return pattern_operation_analyze (op, source); + return _analyze_operation (surface, op, source); /* XXX: It would be nice to be able to assert this condition * here. But, we actually allow one 'cheat' that is used when @@ -1249,8 +1262,12 @@ _cairo_ps_surface_paint (void *abstract_surface, assert (pattern_operation_supported (op, source)); */ - if (surface->need_start_page) + if (surface->need_start_page) { + /* Optimize away erasing of nothing. */ + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; _cairo_ps_surface_start_page (surface); + } _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_paint\n"); @@ -1318,12 +1335,16 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_ps_surface_path_info_t info; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return pattern_operation_analyze (op, source); + return _analyze_operation (surface, op, source); - assert (pattern_operation_supported (op, source)); + assert (operation_supported (surface, op, source)); - if (surface->need_start_page) + if (surface->need_start_page) { + /* Optimize away erasing of nothing. */ + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; _cairo_ps_surface_start_page (surface); + } _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_stroke\n"); @@ -1394,12 +1415,16 @@ _cairo_ps_surface_fill (void *abstract_surface, const char *ps_operator; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return pattern_operation_analyze (op, source); + return _analyze_operation (surface, op, source); - assert (pattern_operation_supported (op, source)); + assert (operation_supported (surface, op, source)); - if (surface->need_start_page) + if (surface->need_start_page) { + /* Optimize away erasing of nothing. */ + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; _cairo_ps_surface_start_page (surface); + } _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_fill\n"); @@ -1448,12 +1473,16 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_path_fixed_t *path; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return pattern_operation_analyze (op, source); + return _analyze_operation (surface, op, source); - assert (pattern_operation_supported (op, source)); + assert (operation_supported (surface, op, source)); - if (surface->need_start_page) + if (surface->need_start_page) { + /* Optimize away erasing of nothing. */ + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; _cairo_ps_surface_start_page (surface); + } _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_show_glyphs\n"); diff --git a/test/cairo-test.c b/test/cairo-test.c index 0d8a9619d..b937fe6db 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1415,8 +1415,7 @@ cairo_test_for_target (cairo_test_t *test, /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); - cairo_set_source_rgba (cr, 0, 0, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); diff --git a/test/caps-joins-ps-argb32-ref.png b/test/caps-joins-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..d6742957a9915c29d64bbaeea7cbc8b2481bba87 GIT binary patch literal 995 zcmeAS@N?(olHy`uVBq!ia0vp^&wx0Jg9%6~Gwgi?q&N#aB8wRqxP?HN@zUM8KR`kG z64!{5;QX|b^2DN42G`&K1^0~n;*#RzqRfI41q(w{Jp)6&`ZH@77?`s>T^vIy=DeMI zGw-&80Lyg8fB&b?WIxQL99Mnz+?NHf3^yEkc~9uzgzU=O-}f@S_;9?Mp}{Ob?1)38 z0CTD%&lFZe7-#dw+}Ynbwk^nUDvIvjWa*isduo~L>a7~HXHL1cD5vOCWcQ|@o@sC6 z*E7%lc4OD#Pc}Y(t=EVws$TwLTdwK)uakCbUZ1l$XUqA*%Qn;PV}9~=H}}iv-I6Lb zUh?LfcjxsJJBru8e;_28Z9Vnxj9*{-4}U(BQZp~3^O)y^6}~qgXMTOh-sV1w^V+;X zf0O@xjaAC&9wJGj`{k%NB{CupM-nU=Be;$9RyXLD`%6HB=Gcu0KG4DM8QCp=b<>EGpg>G7k6UASb z6|FQ0;_r-!*!44D(L^*?(zUU?gQvLPDy(d9APb7iDL7hKqBX_#RDFTH}*HlbdaMgoXWz*~@Q(gV{ zw@9sQaVeW@v-w@)S}*0V6Heq!VxRWTa6-lsPN2@B%I25Yflm2(=xy|#!)BLwfo#i1KaYMkl$LA+Dz7Q{{phFsx7zjRcRq-=IW}{W zhR8*spZ_cS8|FWD1i8C&K@R7&6CxlcN2>P{w=}~^FCK2~6Bly4rqQ)Y)kj%)X5QN0 zt@$mcS-T_ZCV4A=VRUxCLv#&5|>o& zY@bEdO-a`n57VSa_ySmYC_x_%r z*_DXfHPfbU2ut$V@#N~QdECuDPA5_)O7Cb+&$eElYAmWg#WmxKqud(NAFtROlr!H; kIE29xKT1x(%K5>*XZQT(GZ8a(0W&Crr>mdKI;Vst0Ns(t4FCWD literal 0 HcmV?d00001 diff --git a/test/caps-sub-paths-ps-argb32-ref.png b/test/caps-sub-paths-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..a7bc1acb4a417b3e307209d27a1534835c51f87f GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oArNM~bhqvgP*A?a zHKHUqKdq!Zu_%?nH8?=QJtM!kq&T@Kv!F!5!q8ODz>u&0%o?ClLr)jS5R2aAKmY&R zGw*EZ%$du>!=oe6HF2V#9!nv&p_0f=n^lz|pI4-1Wv9t(n8d;m#LllQe*6(5P&0$4 LtDnm{r-UW|^ja^` literal 0 HcmV?d00001 diff --git a/test/clip-fill-rule-ps-argb32-ref.png b/test/clip-fill-rule-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..6d97e04defa270947f87e5645eafd1784da80cba GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^T0ktu!2~2NC1>6OQk(@Ik;M!Q+(IDCc{h2jDrSm;q978-h&xS?w zH7M{TANd`>vrd9j@15s~8`JxzmWfJnI;>uuw?{q8<>yn~9j^O#`Yn^+_w-Ns0sndX zCe5=H`+A>Uf8IO>ow+%zcI>mvYOQ|AJz(0?zglHGi@7+?FYi!vnIE&ICn?Vgj% ztrWal^Kbv$*IfQ~(R9t{R=Qt(PF6V!tef@zM6c_P9J||xFD86A$olL4y8we9azSs` bKjU@0=qtFxu&0%o+v;#(Yl~$B>FSZ*N`9 zbPnWUx%m3a{mqx1+7^gLrEwWN+YlcA{`23u`G42We`{Z$xzQo1@d#5Vs}Q$}n1{}U zhy{*o&ZocIUOp=}Z07YJ#yOupr8Npgm_FvxU42;lI}i7sJ&_AEu6-?BI=%E(_Cv{g zUxD&v8~XZAr=l36fW_Q>=NH6^Wr(fLiFtfF>ywwwVJZE5F^!h1hU@NZ;@Y$5{D)oB z&AF!>v$9>+ntJ!^t;)9lUvB*hdGzXR)W=<2U(NRLB|qKWD=K$Acg^&#R{dX_;&>xA zdTlUztaY$TaJ}3b^Y@{xrm@o3UhKHF!A%(I9SnDX1^kk7Yom&UvRAK;(0&Xxd+!dQ z!3EDZPI?SATmNZj)6|vh+6L<&W`Awli_PF)tZdoZM@#fC83AL7!PC{xWt~$(696@7 B%&q_c literal 0 HcmV?d00001 diff --git a/test/clip-twice-ps-argb32-ref.png b/test/clip-twice-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec76b4efdfe36e2beaef2f32806ad5ba8d5dd0d GIT binary patch literal 460 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$&H|6fVg?3oArNM~bhqvgP*A?a zHKHUqKdq!Zu_%?nH8?=QJtM!kq&T@Kv!F!5!q8ODz>u&0%o+v;#$Znu$B>N1w=*wp zI;6nkvi9-zSLQFzKWdJ8-P3wjO(pe&-Cg!wH=Q4dy$SNN>|Ik_!mw6IA&OIAElWoj zlZ!UvqEf@c$Z5x4_Xn-p)_gnf)Zsg`(pK+HS#&Uif%m|Dht=Coewg@(N5;WcK%KAo z<`LUVm$xM~_`S?5mUOuOC8qP?edZ=#o^!sM+gF{GHFh*N;c8g2-u-`Rc5(wxnm32P zzHE#*%Y`|0N&%k*3yw;aG|cmxY?r|}Mez%dK*Pz6fm;2(Ih)v~sA)753x6m&yuXu` zAqdoM)_Y znElv9aOuyE?{g!LBp7|qUmaN&_H)YjALUb)U#zu^;asA6ME1oghZ)A+D}krMJ-=s~#!TMJ&bI;<7E>86O36Lozopr07^8v AN&o-= literal 0 HcmV?d00001 diff --git a/test/dash-offset-negative-ps-argb32-ref.png b/test/dash-offset-negative-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..518e1c925d0d81dc6c29a2ac82a9fe817bf41c83 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1SJ0&Eu0OcI14-?iy0WWg+Q3`(%rg0KtcHu z*NBqf{Irtt#G+IN*WdsJ_l*4FlH%l|%z_dH3qw;q14F+0Gi!iK4Lw~PLo9mVPTI)J zV8C<8=imREwu(a8j~jU(Hm(TanXu%{h2jDrB$9Tjv*GkXG5a- z8Wec4dB5*3`g@>fm2+!`QoQ%~SKHXU4&7eQz)&f_<9+S9g8xRRn$B2SL`Zej@H>_F zz3Or)dTf2n89y|mtUOv+jl9h mnYU&6y7^Nl<@D*>O%b)_)slYD-Kzz31%s!npUXO@geCy}Ra>V3 literal 0 HcmV?d00001 diff --git a/test/fill-rule-ps-argb32-ref.png b/test/fill-rule-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..b5487e683db25afe3310936e46546c8d04205120 GIT binary patch literal 1078 zcmV-61j+k}P)+m53!5JW>X|NqO(1EYuu#htO{WKU)5z)KK%f8ZG|_;&!Obmj!?@;7|Dp~D!}O~!09R&I{nxzt=CjXl8l(H0-UabmD9vDwNe5PCK)kZ z1vp&=6Q_p~)EWsqo@B&y72tFg^qrnaP1zH8NXdxlD!}O~C_6o!l=3FjuPd3bnq)?pD`47RRR8LP z6=HLJjR@ZEwIq{!LsJB|Y$ex{JkswST)9T|=;su?y3R!h*Y}Q@)>I$CRU}XSmK7?v zZ7P#r^6amcL6loogSkD4_q7AmDIHdF#}vlX5m<(<*$AQggYFZOaVZSd_8 zt)uE%A7%~3Pj~{^Tbiijz2US1A?IZY?U!YlSA)EPQzTQWDs`SG5Yw7qm8wF7SvOQ7 zd)vPfyC?7o$;=IVL-czC3f{XYq36U9*Zu%@OuN+Hw+khwWT%)exXZk^WRG^b;CAx? zB%3?k6uGw9F(mW8vWBvdREN>f3B^e(*(#=qRa_~!gGn}VdPvL~X2+AvaGIEQCS(wc z*uTMMmaO@e#h==m?gK2aWVP(=JDJ#p*pg?R?mv2F6AvweKDlJ+?5#JoHEbqNB3U$h z8_aHvMjpviPB))5uaW&Wv7TSDME16y+UlOk6H3Nh%OqEK7;|!dxE$}e<&S_%NM^*e w`zw-t1u{#XYNy==e=uvd^Gg;Q*$=|=3tGRoWP-cm+W-In07*qoM6N<$f_EqS#sB~S literal 0 HcmV?d00001 diff --git a/test/leaky-polygon-ps-argb32-ref.png b/test/leaky-polygon-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..23af504ece3051bd6a59ba45ee91dfc96000396c GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1SHi;jSd1S&H|6fVg?3oArNM~bhqvgP*A?a zHKHUqKdq!Zu_%?nH8?=QJtM!kq&T@Kv!F!5!q8ODz>u&0%o?E50#6sm5R2ZWQ#`pC z3^`a9|Nmcn-ch2hGdeqdlf%@`MvjKf9k&#ewB-)?EPS7{?85t`1sAHjgZ@;0vz+tm zimuGOpdWjdF6OArc3FAiRk?^{z0~=@56fSro{d&=?e>?txK>_sSIrWI3UirydB{h2jDr2(EUjv*Gk$$$R; zw`cy!AS`+|DIp=DF`%cXr$WTB#$k%otEy=%*C!^(7&b^~M|y0X-!PR~tnA2&g+;p- tZz@#Qy36}+g~VCWC(VMXGE{h2jDr6)aI977^n-%dNo z*KEM!9DU^f|4ro#3srR$uLgC@sAU$c;LW?kwLs;&2KYvUZ1F{>}J6deNMURK4Sohoh!g z7yW-%yE2BR0prCw- zYeY$Kep*R+Vo@rCYjA*qdq#e7NpW&fW+-l)oE8nQ@+R(1B>0&uuoidPO zBdJu;+7fKpK4wZ4NP(5TM5MvhBgd6U9M{d=^10#zG3zM@ZFf@m?h4yzY>r)=Y-_$? z?_zn-a$W2S0xB0wm34d3Ng2KtK+jgcii{cAC)s!PN6B@8-Yb|gFwH2v!X@pS#%@)^ zjSl~?_NM}LaruA6P$mZ6hFV7AQCbuzvuON?=a)a(J=!q|*EizLsWFb-Z z(YXt>8XVna-pT?qxC9w79U_->e(p+tlw8-0`eiop!0qCa;z2Gkxw1^E4rMFB_Cb`d z6SBO4nY!se-x#DZFX>Pf2o(M36eZUZCL3j;z#x4RdlvN{ABBQO?TSJ{<6kzoLg7~Y Y0X1CtBan=fq5uE@07*qoM6N<$f>((uZ~y=R literal 0 HcmV?d00001 diff --git a/test/text-antialias-gray-ps-argb32-ref.png b/test/text-antialias-gray-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..acb273cb740598d35d8e95efde566293c31fb5a2 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%c!2~3?AHJ{*NO2Z;L>4nJa0`Jj)ku8P4pwr+c+Z=dM<~^zlUtdgrb*G33hL;(wteH)j7?rImFI zJAQ|~5A62n4omp2{NYCZ1CN`H0c*bc8`$dY$}y|wjSc6$>Dn@-`R+v>-xBU8_Kn%6 zrkYiq@Z*}WJ^I$nN3Hd1{Wp4?ySaJCZ(*CK>wJp()=2CE`hmgI)z4*}Q$iB}P-}Wn literal 0 HcmV?d00001 diff --git a/test/text-antialias-none-ps-argb32-ref.png b/test/text-antialias-none-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..acb273cb740598d35d8e95efde566293c31fb5a2 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%c!2~3?AHJ{*NO2Z;L>4nJa0`Jj)ku8P4pwr+c+Z=dM<~^zlUtdgrb*G33hL;(wteH)j7?rImFI zJAQ|~5A62n4omp2{NYCZ1CN`H0c*bc8`$dY$}y|wjSc6$>Dn@-`R+v>-xBU8_Kn%6 zrkYiq@Z*}WJ^I$nN3Hd1{Wp4?ySaJCZ(*CK>wJp()=2CE`hmgI)z4*}Q$iB}P-}Wn literal 0 HcmV?d00001 diff --git a/test/text-antialias-subpixel-ps-argb32-ref.png b/test/text-antialias-subpixel-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..acb273cb740598d35d8e95efde566293c31fb5a2 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%c!2~3?AHJ{*NO2Z;L>4nJa0`Jj)ku8P4pwr+c+Z=dM<~^zlUtdgrb*G33hL;(wteH)j7?rImFI zJAQ|~5A62n4omp2{NYCZ1CN`H0c*bc8`$dY$}y|wjSc6$>Dn@-`R+v>-xBU8_Kn%6 zrkYiq@Z*}WJ^I$nN3Hd1{Wp4?ySaJCZ(*CK>wJp()=2CE`hmgI)z4*}Q$iB}P-}Wn literal 0 HcmV?d00001 diff --git a/test/transforms-ps-argb32-ref.png b/test/transforms-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..4858364f6840dcf0463dba3cde98f4f0031eb2ae GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0vp^x{h2jDrOP~B978-h-%h{F z*Py`Rw)E$}^*-We;{R$SC3n5t>HD_D!RyQ$wFeTq1siQu;%p~(d}s)tss6~(C86|> z$Y+ai`F@A>MYC1yuYEgF?E3!TnO#pfggU!QZ63XzoNw@Tg=a+d6_uEc^>@nG{l33r z+k@+N%O+^N>pOq^uU6n;4f{n$M7}ab?8xiBQQ43%qbi}trodp%qW;FmvEIKWBe&}= gkGl2U^5C}#b3V>?ayi!A0rEJ5r>mdKI;Vst0Bc%w#Q*>R literal 0 HcmV?d00001 diff --git a/test/unantialiased-shapes-ps-argb32-ref.png b/test/unantialiased-shapes-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..dc64e36164edc65d3573e8895205ed3890950c65 GIT binary patch literal 4076 zcmb7Hc{~&T{~u%S5pvIwBCHyjbMB)YLxefPY>0(9LJ>xpBg)5-Ns)5JVva01Hgn|a zK;?=#b0kOQDDhqY|Ni;CACLF-dcGd7_v`U`z8>$_`<>=scR_$xiWdL?2v}V-cLV^~ zj9KeVZg$pqXs?Q3O+5IEZV>YaoEK0b+0nq17_fN*`CjT!Gl zP*DM9Lte>FTP;hPvYxjmOE$JSH9=ux-oY-ip625Y4WF4YchA8+1kV-)Z!Z7Cz8?gP z<>&Cmr?5Fd8dPV=BzxWJaU6cW`N-x#mw8YO#oGqX97&~POVsZC&3(CV2zRa=Uvt`b zd{8|%a$tbf+5=}tTz>83)$sX3c(i@!7k{N<75qU9YSsp;@NzY4GFtDp_V12>52&K~ z!ZyRSd+zFvAK{Yhy$(xBsI2IZWpcNyxTwZViF$7?N#^s|ZaKq7LkFg_wAr>7hh#w( ziBtRjplhpeVa=)o@_5kBP4AvnUeTM*S5~Gc2!8?GGM1$?H-$kiC>~7g$mu6NLOORv zJ2p;oRO%a6mTz6258{>qafAeCw9wLPhd$)yaA^d7Z4tNcu)r*9yN) zX`ofNmPJ}lxu=EwBCt0Y3%vL7t#2p3VA+@G=Nr5kG2|ZV?dE0oNHc|| zE-HfBDOC{+O_;2mU2HGzi77Ekxy$a9e}gkRT5~$ZfKvC#%q;VrDAjrWmvsMb>#Y)R zt9l;%hEP4}`Tju^x}^vG5U17y!U?j%!C8Y8eF-Ne&HnkWaW~yf;_cbEFdcQFJqVp+ ztZ8gm_x(Z+XNYrbaBt+ELA#LOw32tki!#dkjL|uSJu6j4e318sit_?);Oa}Yu12_K zWYz#I6IznU*YM_p1YRb3iBgZGe$v6*T|B^(7s zZkSpdh)&8^=gbH`g?> zF6&5@x$*iE#M#d=f9;?S;`HjEBv-Q3Opd9P8iA&KV$)i2{dsSi-Fpf4(5!3OuO5V) zUC-apMEg8cp+@lk%E-#yz8T%5f@{Dc9;f-XA`ls;SjIvo)a!cVX_PZ&_%-Z|H; z*Fxgkkmd`oFlIV&=R{4_@TUXokHJr&NM-LJ07A2cR^tw;ss85a^ku*;^fh3n!lq%W zGGj?`p+NbBt>q}0+9O0o)RQXqZ(U(fG;y?RFT%!>trhesHL@Srcn&Yu%RIeX)}~CG zx0#wkn;f``X=O%nl{LMkUN)ej|nJ~kJ6cw zZq*1iP@KG2`Q19vkDe;X23_^rg(cKKn%kNAg%4 zO8<6mc6IAIWU*-hq+`n?))<->b0Jq!@yA}Oz5I^!9Tt@9m|mel&G!wZpmzMaW&pY_hA1`kdaGxrY>^8Aufwm^q6V`dm@!~+c03;w6yY@%1X%PsOv zgik4B#GY%b2C7FrcOB4cI9*ZzoD7;m5I@xtHx0#7EgIyizt0OCWXePmRoIe6Lr#dl zX@z9Rs^(m)To@!&?B?*pLkLPn_m1PunT+QKd2Z3Z248aWe0>LXF5OoHXoxGv*!#^r zLN%NH6;V6e-Bl1)3cUitzUb?`^wA4S`ZM@{@u!AAZuw`{9yekGe zS-v$lB5US1m9S~J(y&G@+X8umy0Ep!_{5&zroMMz=n8PT4sY+5^az!pw`~s%bHn}q zfRi9!$jUrT7~F?N7YIYIdZ%1f?DbJ_Z>VB;Vvzbbw|_3gXibYF9|K1q@xgh9b}v<* zN%Cr3WNhF1kP+qkW$pR!>`Fy#cCL@Fet)@f*vqMZy7!c6wbk!`XS$_0iz+35l9~lM zk_GZuQGpU;FZhrVli(EfMnl=(?aKuMd58Lx!emBn;%6UUL>oK@WTNsPVzPu70V6Py zi)W0=qPtq-I~Sa+ezjj!AH*OaTH^&xo|p3nfbKYrCJKQL0*k*Bg3mr zWR35$z_69(4o>V@*UC7^jhFAzQ}5xz(ED$zD8U2rk`}ubHVNlygZfReWNpjiv0;S_@`7Cr+Y;*vdc0MW8|b7&4rb$s z@AjCd{aF3FscB2n2=0H@G-u3YD~s~|wM-J(sMEnstE!RxMDld3V*62v4hECy3YozPl8OBEc&5t=Vkshb4(Sr`b*PfpfE5$#G=ttO&m9;!OXrY5g=7UF`;)N}r zT6dm3eri!$HZ^+)og-!ni&n~`aXpXC_CL1v_UF>(+68a*t~}MDRn0aVp0PdQnZ0VH zl?q;QN+yJZ*sK07X6s7niCxmm*7wZ^j*;OBv5O;jrs!u=(-vHj!>NXl|jz*A8m_Sgp|kXr=4pT_RU?!BFf(OQ*$Y+|M+(l z@-=8Y9@u9RU3!^Q_DIa_dW=-Lt;(Bs_LlbHJF0?Z93htX_6B6MB<(7c^UhT1<>V9w zq;B`WHUX#&o~)M2K3Wk!az>er=Wr1J-gtgo5jI-p6wLjX9t1rjA%W3p`(m=@cyNt0 zIvc1z4>j>sF+4tOPfj%ZW)zEB2${dOAW2U3fWV5}GdEzq@cf52|1&AjQTLfH;Z z_TBFcA3wcm zFy94R@W?Ga4&)Mv@rG+1`H z=u=PvNl`AGN?sy!dT~K2O8p>Z105@-WxmrAOwCUm<=%;o$U;2rGO4`=9kT9AUrRvH zJDk)PMp>K?Z6SPnM>L^=PBbef@t750emQb9saUD#me`}!I_N2Z`3Z^r86JiGTqm_n z$PYcJjn%zgBi=3}xy#`%X+J;C&qJa<@`E$zr1=iABP@T(pNyIPb7JecHJgqB8Lo5i zV6hhGHBE3YGPr$6yER|K^wt(_722BN`H|dkozVn#WqSSnl%89m+-JhsKI=}jp-hn$ zAprRPA|k);3y_~@#y79driv!l!c_yWK=uxo@Jg5(`HWNlprjHD>r#3rGs{elI}r4_ zt<_{evpzdow_`DB68wqBs8jwl^nD3W90wEjhIfgEU6w|q(gBqwWhDw!U0Z&TF`Ft( zfIc*vqQ^gFlF3XwB7puQWMuHjfJn5wZZ2@LCbM3cjmTChuw#_W;d9)bO9o^^ue4+9 z>G6SA(s-F?0E=|2MB)Su4G04M(~|*}XyGNglANz{F=46f(WW)@A+!*;Y8`x2EOFaM zgWouq2?I0{7=Td_80a9a!#_n+jTFU8{2xDNkwdO{BWN_tI&0t`YGq+({=(EJ>3_@+ BjSBz( literal 0 HcmV?d00001 From bfd467453c5213341ae2c396ac3d32ba76df8de9 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 7 Apr 2006 17:40:30 +0200 Subject: [PATCH 095/155] * Fix build * Add shortcut to cairo-atsui-font.c for the common case. --- src/cairo-atsui-font.c | 142 +++++++++++++++++++++---------------- src/cairo-quartz-surface.c | 1 + 2 files changed, 81 insertions(+), 62 deletions(-) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index cab7843a4..7aae7c82a 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -563,86 +563,103 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, int num_glyphs) { cairo_atsui_font_t *font = abstract_font; - CGContextRef myBitmapContext; - CGColorSpaceRef colorSpace; + CGContextRef myBitmapContext = 0, drawingContext; + CGColorSpaceRef colorSpace = 0;; cairo_image_surface_t *destImageSurface; int i; void *extra = NULL; + cairo_bool_t can_draw_directly; + cairo_rectangle_t rect; - cairo_rectangle_t rect = {dest_x, dest_y, width, height}; - _cairo_surface_acquire_dest_image(generic_surface, - &rect, - &destImageSurface, - &rect, - &extra); + /* Check if we can draw directly to the destination surface */ + can_draw_directly = _cairo_surface_is_quartz (generic_surface) && + _cairo_pattern_is_opaque_solid (pattern) && + op == CAIRO_OPERATOR_OVER; - /* Create a CGBitmapContext for the dest surface for drawing into */ - colorSpace = CGColorSpaceCreateDeviceRGB(); + if (!can_draw_directly) { + rect.x = dest_x; + rect.y = dest_y; + rect.width = width; + rect.height = height; - myBitmapContext = CGBitmapContextCreate(destImageSurface->data, - destImageSurface->width, - destImageSurface->height, - destImageSurface->depth / 4, - destImageSurface->stride, - colorSpace, - kCGImageAlphaPremultipliedFirst); - CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); - CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); + _cairo_surface_acquire_dest_image(generic_surface, + &rect, + &destImageSurface, + &rect, + &extra); + + /* Create a CGBitmapContext for the dest surface for drawing into */ + colorSpace = CGColorSpaceCreateDeviceRGB(); + + myBitmapContext = CGBitmapContextCreate(destImageSurface->data, + destImageSurface->width, + destImageSurface->height, + destImageSurface->depth / 4, + destImageSurface->stride, + colorSpace, + kCGImageAlphaPremultipliedFirst); + CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); + CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); + + drawingContext = myBitmapContext; + } else { + drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context; + } ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont); - CGContextSetFont(myBitmapContext, cgFont); + CGContextSetFont(drawingContext, cgFont); CGAffineTransform textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale); textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); - CGContextSetFontSize(myBitmapContext, 1.0); - CGContextSetTextMatrix(myBitmapContext, textTransform); + CGContextSetFontSize(drawingContext, 1.0); + CGContextSetTextMatrix(drawingContext, textTransform); if (pattern->type == CAIRO_PATTERN_TYPE_SOLID && _cairo_pattern_is_opaque_solid(pattern)) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; - CGContextSetRGBFillColor(myBitmapContext, + CGContextSetRGBFillColor(drawingContext, solid->color.red, solid->color.green, solid->color.blue, 1.0f); } else { - CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f); + CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f); } - if (_cairo_surface_is_quartz (generic_surface)) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; - if (surface->clip_region) { - pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); - int num_boxes = pixman_region_num_rects (surface->clip_region); - CGRect stack_rects[10]; - CGRect *rects; - int i; - - if (num_boxes > 10) - rects = malloc (sizeof (CGRect) * num_boxes); - else - rects = stack_rects; - - for (i = 0; i < num_boxes; i++) { - rects[i].origin.x = boxes[i].x1; - rects[i].origin.y = boxes[i].y1; - rects[i].size.width = boxes[i].x2 - boxes[i].x1; - rects[i].size.height = boxes[i].y2 - boxes[i].y1; - } - - CGContextClipToRects (myBitmapContext, rects, num_boxes); - - if (rects != stack_rects) - free(rects); - } - } else { - /* XXX: Need to get the text clipped */ + if (_cairo_surface_is_quartz (generic_surface)) { + cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; + if (surface->clip_region) { + pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); + int num_boxes = pixman_region_num_rects (surface->clip_region); + CGRect stack_rects[10]; + CGRect *rects; + int i; + + if (num_boxes > 10) + rects = malloc (sizeof (CGRect) * num_boxes); + else + rects = stack_rects; + + for (i = 0; i < num_boxes; i++) { + rects[i].origin.x = boxes[i].x1; + rects[i].origin.y = boxes[i].y1; + rects[i].size.width = boxes[i].x2 - boxes[i].x1; + rects[i].size.height = boxes[i].y2 - boxes[i].y1; + } + + CGContextClipToRects (drawingContext, rects, num_boxes); + + if (rects != stack_rects) + free(rects); } + } else { + /* XXX: Need to get the text clipped */ + } /* TODO - bold and italic text * @@ -655,21 +672,22 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, for (i = 0; i < num_glyphs; i++) { CGGlyph theGlyph = glyphs[i].index; - CGContextShowGlyphsAtPoint(myBitmapContext, + CGContextShowGlyphsAtPoint(drawingContext, glyphs[i].x, glyphs[i].y, &theGlyph, 1); } - - CGColorSpaceRelease(colorSpace); - CGContextRelease(myBitmapContext); - - _cairo_surface_release_dest_image(generic_surface, - &rect, - destImageSurface, - &rect, - extra); + if (!can_draw_directly) { + CGColorSpaceRelease(colorSpace); + CGContextRelease(myBitmapContext); + + _cairo_surface_release_dest_image(generic_surface, + &rect, + destImageSurface, + &rect, + extra); + } return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index c65ca46d7..5bf01bb12 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -217,6 +217,7 @@ _cairo_quartz_surface_get_extents (void *abstract_surface, } static const struct _cairo_surface_backend cairo_quartz_surface_backend = { + CAIRO_SURFACE_TYPE_QUARTZ, NULL, /* create_similar */ _cairo_quartz_surface_finish, _cairo_quartz_surface_acquire_source_image, From 732e06258c81427cf7fedfca98107e21244264eb Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 7 Apr 2006 15:46:32 -0700 Subject: [PATCH 096/155] Rename write_data to write_func in cairo_output_stream_t. --- src/cairo-base85-stream.c | 8 ++++---- src/cairo-output-stream.c | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c index bd1a7ac7e..1d4535a9f 100644 --- a/src/cairo-base85-stream.c +++ b/src/cairo-base85-stream.c @@ -63,9 +63,9 @@ _expand_four_tuple_to_five (unsigned char four_tuple[4], } static cairo_status_t -_cairo_base85_stream_write_data (void *closure, - const unsigned char *data, - unsigned int length) +_cairo_base85_stream_write (void *closure, + const unsigned char *data, + unsigned int length) { cairo_base85_stream_t *stream = closure; const unsigned char *ptr = data; @@ -123,7 +123,7 @@ _cairo_base85_stream_create (cairo_output_stream_t *output) stream->output = output; stream->pending = 0; - return _cairo_output_stream_create (_cairo_base85_stream_write_data, + return _cairo_output_stream_create (_cairo_base85_stream_write, _cairo_base85_stream_close, stream); } diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index adc00b86a..16d937172 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -44,7 +44,7 @@ #endif /* _MSC_VER */ struct _cairo_output_stream { - cairo_write_func_t write_data; + cairo_write_func_t write_func; cairo_close_func_t close_func; void *closure; unsigned long position; @@ -53,7 +53,7 @@ struct _cairo_output_stream { }; const cairo_output_stream_t cairo_output_stream_nil = { - NULL, /* write_data */ + NULL, /* write_func */ NULL, /* close_func */ NULL, /* closure */ 0, /* position */ @@ -62,7 +62,7 @@ const cairo_output_stream_t cairo_output_stream_nil = { }; static const cairo_output_stream_t cairo_output_stream_nil_write_error = { - NULL, /* write_data */ + NULL, /* write_func */ NULL, /* close_func */ NULL, /* closure */ 0, /* position */ @@ -71,7 +71,7 @@ static const cairo_output_stream_t cairo_output_stream_nil_write_error = { }; cairo_output_stream_t * -_cairo_output_stream_create (cairo_write_func_t write_data, +_cairo_output_stream_create (cairo_write_func_t write_func, cairo_close_func_t close_func, void *closure) { @@ -81,7 +81,7 @@ _cairo_output_stream_create (cairo_write_func_t write_data, if (stream == NULL) return (cairo_output_stream_t *) &cairo_output_stream_nil; - stream->write_data = write_data; + stream->write_func = write_func; stream->close_func = close_func; stream->closure = closure; stream->position = 0; @@ -125,7 +125,7 @@ _cairo_output_stream_write (cairo_output_stream_t *stream, if (stream->status) return; - stream->status = stream->write_data (stream->closure, data, length); + stream->status = stream->write_func (stream->closure, data, length); stream->position += length; } From ade195cdba5b0d13c121e44709151bfbb0c44085 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Apr 2006 21:29:14 -0700 Subject: [PATCH 097/155] Save PS output in temp file so we can prepend global data (like fonts) --- src/cairo-output-stream.c | 20 +++++++++++-- src/cairo-pdf-surface.c | 2 +- src/cairo-ps-surface.c | 59 +++++++++++++++++++++++++++++++-------- src/cairo-svg-surface.c | 2 +- src/cairoint.h | 5 +++- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 16d937172..d84b5c3f5 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -329,6 +329,16 @@ stdio_write (void *closure, const unsigned char *data, unsigned int length) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +stdio_flush (void *closure) +{ + FILE *file = closure; + + fflush (file); + + return CAIRO_STATUS_SUCCESS; /* XXX errors */ +} + static cairo_status_t stdio_close (void *closure) { @@ -337,11 +347,17 @@ stdio_close (void *closure) fflush (file); fclose (file); - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; /* XXX errors */ } cairo_output_stream_t * -_cairo_output_stream_create_for_file (const char *filename) +_cairo_output_stream_create_for_file (FILE *file) +{ + return _cairo_output_stream_create (stdio_write, stdio_flush, file); +} + +cairo_output_stream_t * +_cairo_output_stream_create_for_filename (const char *filename) { FILE *file; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index b01fcd970..03d161c95 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -380,7 +380,7 @@ cairo_pdf_surface_create (const char *filename, cairo_status_t status; cairo_output_stream_t *stream; - stream = _cairo_output_stream_create_for_file (filename); + stream = _cairo_output_stream_create_for_filename (filename); status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 8a3786871..756b774e4 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -65,7 +65,10 @@ typedef struct cairo_ps_surface { /* PS-specific fields */ cairo_output_stream_t *stream; + cairo_output_stream_t *final_stream; + FILE *tmpfile; + double width; double height; double x_dpi; @@ -95,32 +98,47 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) now = time (NULL); - _cairo_output_stream_printf (surface->stream, + _cairo_output_stream_printf (surface->final_stream, "%%!PS-Adobe-3.0\n" "%%%%Creator: cairo (http://cairographics.org)\n" "%%%%CreationDate: %s" - "%%%%Pages: (atend)\n" + "%%%%Pages: %d\n" "%%%%BoundingBox: %f %f %f %f\n", ctime (&now), + surface->num_pages, 0.0, 0.0, surface->width, surface->height); - _cairo_output_stream_printf (surface->stream, + _cairo_output_stream_printf (surface->final_stream, "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: 2\n" "%%%%Orientation: Portrait\n" "%%%%EndComments\n"); } +static void +_cairo_ps_surface_emit_fonts (cairo_ps_surface_t *surface) +{ +} + +static void +_cairo_ps_surface_emit_body (cairo_ps_surface_t *surface) +{ + char buf[4096]; + int n; + + rewind (surface->tmpfile); + while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0) + _cairo_output_stream_write (surface->final_stream, buf, n); +} + static void _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface) { - _cairo_output_stream_printf (surface->stream, + _cairo_output_stream_printf (surface->final_stream, "%%%%Trailer\n" - "%%%%Pages: %d\n" - "%%%%EOF\n", - surface->num_pages); + "%%%%EOF\n"); } static cairo_surface_t * @@ -138,7 +156,21 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_surface_init (&surface->base, &cairo_ps_surface_backend); - surface->stream = stream; + surface->final_stream = stream; + surface->tmpfile = tmpfile (); + + if (!surface->tmpfile) { + free (surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } + surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile); + if (!surface->stream) { + fclose (surface->tmpfile); + free (surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } surface->width = width; surface->height = height; @@ -157,8 +189,6 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_array_init (&surface->fonts, sizeof (cairo_font_subset_t *)); #endif - _cairo_ps_surface_emit_header (surface); - return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height, @@ -190,7 +220,7 @@ cairo_ps_surface_create (const char *filename, cairo_status_t status; cairo_output_stream_t *stream; - stream = _cairo_output_stream_create_for_file (filename); + stream = _cairo_output_stream_create_for_filename (filename); status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); @@ -297,9 +327,12 @@ _cairo_ps_surface_finish (void *abstract_surface) { cairo_ps_surface_t *surface = abstract_surface; + _cairo_ps_surface_emit_header (surface); + #if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED _cairo_ps_surface_write_font_subsets (surface); #endif + _cairo_ps_surface_emit_body (surface); _cairo_ps_surface_emit_footer (surface); @@ -313,6 +346,10 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_output_stream_destroy (surface->stream); + fclose (surface->tmpfile); + + _cairo_output_stream_destroy (surface->final_stream); + return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 21d73f693..d5c45eb5d 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -164,7 +164,7 @@ cairo_svg_surface_create (const char *filename, cairo_status_t status; cairo_output_stream_t *stream; - stream = _cairo_output_stream_create_for_file (filename); + stream = _cairo_output_stream_create_for_filename (filename); status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); diff --git a/src/cairoint.h b/src/cairoint.h index 6cd8bfbef..4cfa94840 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2190,7 +2190,10 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream); * least) in order to ensure that everything is properly cleaned up. */ cairo_private cairo_output_stream_t * -_cairo_output_stream_create_for_file (const char *filename); +_cairo_output_stream_create_for_filename (const char *filename); + +cairo_private cairo_output_stream_t * +_cairo_output_stream_create_for_file (FILE *file); /* cairo_base85_stream.c */ cairo_output_stream_t * From da2c5e44abd98f1f1aed4f716b7e9bc97a667058 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Apr 2006 00:37:58 -0700 Subject: [PATCH 098/155] Allow hash entry deletion during cairo_hash_foreach --- src/cairo-hash.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/cairo-hash.c b/src/cairo-hash.c index e44ab3025..9ea5909c8 100644 --- a/src/cairo-hash.c +++ b/src/cairo-hash.c @@ -124,6 +124,7 @@ struct _cairo_hash_table { cairo_hash_entry_t **entries; unsigned long live_entries; + unsigned long locked; /* don't resize array */ }; /** @@ -163,6 +164,7 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal) } hash_table->live_entries = 0; + hash_table->locked = 0; return hash_table; } @@ -188,6 +190,8 @@ _cairo_hash_table_destroy (cairo_hash_table_t *hash_table) /* The hash table must be empty. Otherwise, halt. */ assert (hash_table->live_entries == 0); + /* The hash table must be unlocked. Otherwise, halt. */ + assert (hash_table->locked == 0); free (hash_table->entries); hash_table->entries = NULL; @@ -298,6 +302,9 @@ _cairo_hash_table_resize (cairo_hash_table_t *hash_table) unsigned long high = hash_table->arrangement->high_water_mark; unsigned long low = high >> 2; + /* The hash table must be unlocked. Otherwise, halt. */ + assert (hash_table->locked == 0); + if (hash_table->live_entries >= low && hash_table->live_entries <= high) return CAIRO_STATUS_SUCCESS; @@ -502,7 +509,8 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table, * memory to shrink the hash table. It does leave the table in a * consistent state, and we've already succeeded in removing the * entry, so we don't examine the failure status of this call. */ - _cairo_hash_table_resize (hash_table); + if (hash_table->locked == 0) + _cairo_hash_table_resize (hash_table); } /** @@ -525,9 +533,13 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table, if (hash_table == NULL) return; + /* Lock while walking to avoid missing entries on delete */ + ++hash_table->locked; for (i = 0; i < hash_table->arrangement->size; i++) { entry = hash_table->entries[i]; if (ENTRY_IS_LIVE(entry)) hash_callback (entry, closure); } + if (--hash_table->locked == 0) + _cairo_hash_table_resize (hash_table); } From 0727e3c1a980f57d48f3dfaee801f05e5395a71a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Apr 2006 00:38:43 -0700 Subject: [PATCH 099/155] Use Type3 fonts for PostScript output. No bitmap support yet. --- src/cairo-ps-surface.c | 737 ++++++++++++++++++++++++----------------- 1 file changed, 440 insertions(+), 297 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 756b774e4..24e31111d 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -60,6 +60,27 @@ static void _cairo_ps_set_paginated_mode (cairo_surface_t *target, cairo_paginated_mode_t mode); +/* + * Type1 and Type3 PS fonts can hold only 256 glyphs. + * + * XXX Work around this by placing each set of 256 glyphs in a separate + * font. No separate data structure is kept for this; the font name is + * generated from all but the low 8 bits of the output glyph id. + */ + +typedef struct cairo_ps_glyph { + cairo_hash_entry_t base; /* font glyph index */ + unsigned int output_glyph; /* PS sub-font glyph index */ +} cairo_ps_glyph_t; + +typedef struct cairo_ps_font { + cairo_hash_entry_t base; + cairo_scaled_font_t *scaled_font; + unsigned int output_font; + cairo_hash_table_t *glyphs; + unsigned int max_glyph; +} cairo_ps_font_t; + typedef struct cairo_ps_surface { cairo_surface_t base; @@ -79,17 +100,86 @@ typedef struct cairo_ps_surface { cairo_paginated_mode_t paginated_mode; -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED - cairo_array_t fonts; -#endif + cairo_hash_table_t *fonts; + unsigned int max_font; + } cairo_ps_surface_t; #define PS_SURFACE_DPI_DEFAULT 300.0 -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED -static cairo_int_status_t -_cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface); -#endif +typedef struct +{ + cairo_output_stream_t *output_stream; + cairo_bool_t has_current_point; +} cairo_ps_surface_path_info_t; + +static cairo_status_t +_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point) +{ + cairo_ps_surface_path_info_t *info = closure; + + _cairo_output_stream_printf (info->output_stream, + "%f %f moveto ", + _cairo_fixed_to_double (point->x), + _cairo_fixed_to_double (point->y)); + info->has_current_point = TRUE; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point) +{ + cairo_ps_surface_path_info_t *info = closure; + const char *ps_operator; + + if (info->has_current_point) + ps_operator = "lineto"; + else + ps_operator = "moveto"; + + _cairo_output_stream_printf (info->output_stream, + "%f %f %s ", + _cairo_fixed_to_double (point->x), + _cairo_fixed_to_double (point->y), + ps_operator); + info->has_current_point = TRUE; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_ps_surface_path_curve_to (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d) +{ + cairo_ps_surface_path_info_t *info = closure; + + _cairo_output_stream_printf (info->output_stream, + "%f %f %f %f %f %f curveto ", + _cairo_fixed_to_double (b->x), + _cairo_fixed_to_double (b->y), + _cairo_fixed_to_double (c->x), + _cairo_fixed_to_double (c->y), + _cairo_fixed_to_double (d->x), + _cairo_fixed_to_double (d->y)); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_ps_surface_path_close_path (void *closure) +{ + cairo_ps_surface_path_info_t *info = closure; + + if (info->has_current_point) + _cairo_output_stream_printf (info->output_stream, + "closepath\n"); + info->has_current_point = FALSE; + + return CAIRO_STATUS_SUCCESS; +} static void _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) @@ -117,9 +207,295 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "%%%%EndComments\n"); } +static cairo_bool_t +_cairo_ps_glyph_equal (const void *key_a, const void *key_b) +{ + const cairo_ps_glyph_t *ps_glyph_a = key_a; + const cairo_ps_glyph_t *ps_glyph_b = key_b; + + return ps_glyph_a->base.hash == ps_glyph_b->base.hash; +} + +static void +_cairo_ps_glyph_key_init (cairo_ps_glyph_t *ps_glyph, + unsigned long index) +{ + ps_glyph->base.hash = index; +} + +static cairo_ps_glyph_t * +_cairo_ps_glyph_create (cairo_ps_font_t *ps_font, + unsigned long index) +{ + cairo_ps_glyph_t *ps_glyph = malloc (sizeof (cairo_ps_glyph_t)); + + if (!ps_glyph) + return NULL; + _cairo_ps_glyph_key_init (ps_glyph, index); + ps_glyph->output_glyph = ps_font->max_glyph++; + return ps_glyph; +} + +static void +_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph) +{ + free (ps_glyph); +} + +static cairo_status_t +_cairo_ps_glyph_find (cairo_ps_font_t *font, + cairo_scaled_font_t *scaled_font, + unsigned long index, + cairo_ps_glyph_t **result) +{ + cairo_ps_glyph_t key; + cairo_ps_glyph_t *ps_glyph; + cairo_status_t status; + + _cairo_ps_glyph_key_init (&key, index); + if (!_cairo_hash_table_lookup (font->glyphs, + &key.base, + (cairo_hash_entry_t **) &ps_glyph)) { + ps_glyph = _cairo_ps_glyph_create (font, index); + if (!ps_glyph) + return CAIRO_STATUS_NO_MEMORY; + status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base); + if (status) + return status; + } + *result = ps_glyph; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_bool_t +_cairo_ps_font_equal (const void *key_a, const void *key_b) +{ + const cairo_ps_font_t *ps_font_a = key_a; + const cairo_ps_font_t *ps_font_b = key_b; + + return ps_font_a->scaled_font == ps_font_b->scaled_font; +} + +static void +_cairo_ps_font_key_init (cairo_ps_font_t *ps_font, + cairo_scaled_font_t *scaled_font) +{ + ps_font->base.hash = (unsigned long) scaled_font; + ps_font->scaled_font = scaled_font; +} + +static cairo_ps_font_t * +_cairo_ps_font_create (cairo_ps_surface_t *surface, + cairo_scaled_font_t *scaled_font) +{ + cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t)); + if (!ps_font) + return NULL; + _cairo_ps_font_key_init (ps_font, scaled_font); + ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal); + if (!ps_font->glyphs) { + free (ps_font); + return NULL; + } + ps_font->max_glyph = 0; + ps_font->output_font = surface->max_font++; + cairo_scaled_font_reference (ps_font->scaled_font); + return ps_font; +} + +static void +_cairo_ps_font_destroy_glyph (void *entry, void *closure) +{ + cairo_ps_glyph_t *ps_glyph = entry; + cairo_ps_font_t *ps_font = closure; + + _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base); + _cairo_ps_glyph_destroy (ps_glyph); +} + +static void +_cairo_ps_font_destroy (cairo_ps_font_t *ps_font) +{ + _cairo_hash_table_foreach (ps_font->glyphs, + _cairo_ps_font_destroy_glyph, + ps_font); + _cairo_hash_table_destroy (ps_font->glyphs); + cairo_scaled_font_destroy (ps_font->scaled_font); + free (ps_font); +} + +static void +_cairo_ps_surface_destroy_font (cairo_ps_surface_t *surface, + cairo_ps_font_t *ps_font) +{ + _cairo_hash_table_remove (surface->fonts, &ps_font->base); + _cairo_ps_font_destroy (ps_font); +} + +static cairo_status_t +_cairo_ps_font_find (cairo_ps_surface_t *surface, + cairo_scaled_font_t *scaled_font, + cairo_ps_font_t **result) +{ + cairo_ps_font_t key; + cairo_ps_font_t *ps_font; + cairo_status_t status; + + _cairo_ps_font_key_init (&key, scaled_font); + if (!_cairo_hash_table_lookup (surface->fonts, &key.base, + (cairo_hash_entry_t **) &ps_font)) + { + ps_font = _cairo_ps_font_create (surface, scaled_font); + if (!ps_font) + return CAIRO_STATUS_NO_MEMORY; + status = _cairo_hash_table_insert (surface->fonts, + &ps_font->base); + if (status) + return status; + } + *result = ps_font; + return CAIRO_STATUS_SUCCESS; +} + +typedef struct _cairo_ps_font_glyph_select { + cairo_ps_glyph_t **glyphs; + int subfont; + int numglyph; +} cairo_ps_font_glyph_select_t; + +static void +_cairo_ps_font_select_glyphs (void *entry, void *closure) +{ + cairo_ps_glyph_t *ps_glyph = entry; + cairo_ps_font_glyph_select_t *ps_glyph_select = closure; + + if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) { + unsigned long sub_glyph = ps_glyph->output_glyph & 0xff; + ps_glyph_select->glyphs[sub_glyph] = ps_glyph; + if (sub_glyph >= ps_glyph_select->numglyph) + ps_glyph_select->numglyph = sub_glyph + 1; + } +} + +static cairo_status_t +_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, + cairo_ps_font_t *ps_font, + cairo_ps_glyph_t *ps_glyph) +{ + cairo_scaled_glyph_t *scaled_glyph; + cairo_status_t status; + cairo_ps_surface_path_info_t info; + + _cairo_output_stream_printf (surface->final_stream, + "\t\t{ %% %d\n", ps_glyph->output_glyph); + status = _cairo_scaled_glyph_lookup (ps_font->scaled_font, + ps_glyph->base.hash, + CAIRO_SCALED_GLYPH_INFO_METRICS| + CAIRO_SCALED_GLYPH_INFO_PATH, + &scaled_glyph); + /* + * If that fails, try again but ask for an image instead + */ + if (status) + status = _cairo_scaled_glyph_lookup (ps_font->scaled_font, + ps_glyph->base.hash, + CAIRO_SCALED_GLYPH_INFO_METRICS| + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + if (status) { + _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); + return status; + } + _cairo_output_stream_printf (surface->final_stream, + "%f %f %f %f 0 0 setcachedevice\n", + _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), + -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y), + _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), + -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); + + info.output_stream = surface->final_stream; + info.has_current_point = FALSE; + + status = _cairo_path_fixed_interpret (scaled_glyph->path, + CAIRO_DIRECTION_FORWARD, + _cairo_ps_surface_path_move_to, + _cairo_ps_surface_path_line_to, + _cairo_ps_surface_path_curve_to, + _cairo_ps_surface_path_close_path, + &info); + + _cairo_output_stream_printf (surface->final_stream, + "fill\n"); + + _cairo_output_stream_printf (surface->final_stream, + "\t\t}\n"); + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_ps_surface_emit_font (void *entry, void *closure) +{ + cairo_ps_font_t *ps_font = entry; + cairo_ps_surface_t *surface = closure; + cairo_ps_font_glyph_select_t glyph_select; + cairo_ps_glyph_t *ps_glyphs[256], *ps_glyph; + int glyph, numglyph; + int subfont, nsubfont; + + _cairo_output_stream_printf (surface->final_stream, + "%% _cairo_ps_surface_emit_font\n"); + nsubfont = (ps_font->max_glyph >> 8) + 1; + for (subfont = 0; subfont < nsubfont; subfont++) { + _cairo_output_stream_printf (surface->final_stream, + "/CairoFont-%d-%d <<\n", + ps_font->output_font, + subfont); + memset (ps_glyphs, '\0', sizeof (ps_glyphs)); + glyph_select.glyphs = ps_glyphs; + glyph_select.numglyph = 0; + glyph_select.subfont = subfont; + _cairo_hash_table_foreach (ps_font->glyphs, + _cairo_ps_font_select_glyphs, + &glyph_select); + _cairo_output_stream_printf (surface->final_stream, + "\t/FontType\t3\n" + "\t/FontMatrix\t[1 0 0 1 0 0]\n" + "\t/Encoding\t[0]\n" + "\t/FontBBox\t[0 0 10 10]\n" + "\t/Glyphs [\n"); + numglyph = glyph_select.numglyph; + for (glyph = 0; glyph < numglyph; glyph++) { + ps_glyph = ps_glyphs[glyph]; + if (ps_glyph) { + _cairo_ps_surface_emit_glyph (surface, + ps_font, + ps_glyph); + } else { + _cairo_output_stream_printf (surface->final_stream, + "\t\t{ } %% %d\n", glyph); + } + _cairo_ps_font_destroy_glyph (ps_glyph, ps_font); + } + _cairo_output_stream_printf (surface->final_stream, + "\t]\n" + "\t/BuildChar {\n" + "\t\texch /Glyphs get\n" + "\t\texch get exec\n" + "\t}\n" + ">> definefont pop\n"); + } + _cairo_ps_surface_destroy_font (surface, ps_font); +} + + static void _cairo_ps_surface_emit_fonts (cairo_ps_surface_t *surface) { + _cairo_hash_table_foreach (surface->fonts, + _cairo_ps_surface_emit_font, + surface); + _cairo_hash_table_destroy (surface->fonts); + surface->fonts = NULL; } static void @@ -172,23 +548,25 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, return (cairo_surface_t*) &_cairo_surface_nil; } + surface->fonts = _cairo_hash_table_create (_cairo_ps_font_equal); + if (!surface->fonts) { + _cairo_output_stream_destroy (surface->stream); + fclose (surface->tmpfile); + free (surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } + surface->max_font = 0; + surface->width = width; surface->height = height; surface->x_dpi = PS_SURFACE_DPI_DEFAULT; surface->y_dpi = PS_SURFACE_DPI_DEFAULT; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; -#if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED - surface->base.device_x_scale = surface->x_dpi / 72.0; - surface->base.device_y_scale = surface->y_dpi / 72.0; -#endif surface->need_start_page = TRUE; surface->num_pages = 0; -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED - _cairo_array_init (&surface->fonts, sizeof (cairo_font_subset_t *)); -#endif - return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height, @@ -315,10 +693,6 @@ cairo_ps_surface_set_dpi (cairo_surface_t *surface, ps_surface->x_dpi = x_dpi; ps_surface->y_dpi = y_dpi; -#if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED - ps_surface->base.device_x_scale = ps_surface->x_dpi / 72.0; - ps_surface->base.device_y_scale = ps_surface->y_dpi / 72.0; -#endif } /* XXX */ @@ -329,21 +703,12 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_ps_surface_emit_header (surface); -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED - _cairo_ps_surface_write_font_subsets (surface); -#endif + _cairo_ps_surface_emit_fonts (surface); + _cairo_ps_surface_emit_body (surface); _cairo_ps_surface_emit_footer (surface); -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED - for (i = 0; i < surface->fonts.num_elements; i++) { - _cairo_array_copy_element (&surface->fonts, i, &subset); - _cairo_font_subset_destroy (subset); - } - _cairo_array_fini (&surface->fonts); -#endif - _cairo_output_stream_destroy (surface->stream); fclose (surface->tmpfile); @@ -405,119 +770,6 @@ _cairo_ps_surface_show_page (void *abstract_surface) return CAIRO_STATUS_SUCCESS; } -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED -static cairo_font_subset_t * -_cairo_ps_surface_get_font (cairo_ps_surface_t *surface, - cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_unscaled_font_t *unscaled_font; - cairo_font_subset_t *subset; - unsigned int num_fonts, i; - - /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */ - if (! _cairo_scaled_font_is_ft (scaled_font)) - return NULL; - - /* XXX Why is this an ft specific function? */ - unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font); - - num_fonts = _cairo_array_num_elements (&surface->fonts); - for (i = 0; i < num_fonts; i++) { - _cairo_array_copy_element (&surface->fonts, i, &subset); - if (subset->unscaled_font == unscaled_font) - return subset; - } - - subset = _cairo_font_subset_create (unscaled_font); - if (subset == NULL) - return NULL; - - subset->font_id = surface->fonts.num_elements; - - status = _cairo_array_append (&surface->fonts, &subset); - if (status) { - _cairo_font_subset_destroy (subset); - return NULL; - } - - return subset; -} - -static cairo_int_status_t -_cairo_ps_surface_write_type42_dict (cairo_ps_surface_t *surface, - cairo_font_subset_t *subset) -{ - const char *data; - unsigned long data_size; - cairo_status_t status; - int i; - - status = CAIRO_STATUS_SUCCESS; - - /* FIXME: Figure out document structure convention for fonts */ - - _cairo_output_stream_printf (surface->stream, - "11 dict begin\n" - "/FontType 42 def\n" - "/FontName /f%d def\n" - "/PaintType 0 def\n" - "/FontMatrix [ 1 0 0 1 0 0 ] def\n" - "/FontBBox [ 0 0 0 0 ] def\n" - "/Encoding 256 array def\n" - "0 1 255 { Encoding exch /.notdef put } for\n", - subset->font_id); - - /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */ - - for (i = 1; i < subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->stream, - "Encoding %d /g%d put\n", i, i); - - _cairo_output_stream_printf (surface->stream, - "/CharStrings %d dict dup begin\n" - "/.notdef 0 def\n", - subset->num_glyphs); - - for (i = 1; i < subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->stream, - "/g%d %d def\n", i, i); - - _cairo_output_stream_printf (surface->stream, - "end readonly def\n"); - - status = _cairo_font_subset_generate (subset, &data, &data_size); - - /* FIXME: We need to break up fonts bigger than 64k so we don't - * exceed string size limitation. At glyph boundaries. Stupid - * postscript. */ - _cairo_output_stream_printf (surface->stream, - "/sfnts [<"); - - _cairo_output_stream_write_hex_string (surface->stream, data, data_size); - - _cairo_output_stream_printf (surface->stream, - ">] def\n" - "FontName currentdict end definefont pop\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface) -{ - cairo_font_subset_t *subset; - int i; - - for (i = 0; i < surface->fonts.num_elements; i++) { - _cairo_array_copy_element (&surface->fonts, i, &subset); - _cairo_ps_surface_write_type42_dict (surface, subset); - } - - return CAIRO_STATUS_SUCCESS; -} -#endif - static cairo_bool_t color_is_gray (cairo_color_t *color) { @@ -1052,79 +1304,6 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) } } -typedef struct -{ - cairo_output_stream_t *output_stream; - cairo_bool_t has_current_point; -} cairo_ps_surface_path_info_t; - -static cairo_status_t -_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point) -{ - cairo_ps_surface_path_info_t *info = closure; - - _cairo_output_stream_printf (info->output_stream, - "%f %f moveto ", - _cairo_fixed_to_double (point->x), - _cairo_fixed_to_double (point->y)); - info->has_current_point = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point) -{ - cairo_ps_surface_path_info_t *info = closure; - const char *ps_operator; - - if (info->has_current_point) - ps_operator = "lineto"; - else - ps_operator = "moveto"; - - _cairo_output_stream_printf (info->output_stream, - "%f %f %s ", - _cairo_fixed_to_double (point->x), - _cairo_fixed_to_double (point->y), - ps_operator); - info->has_current_point = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_path_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - cairo_ps_surface_path_info_t *info = closure; - - _cairo_output_stream_printf (info->output_stream, - "%f %f %f %f %f %f curveto ", - _cairo_fixed_to_double (b->x), - _cairo_fixed_to_double (b->y), - _cairo_fixed_to_double (c->x), - _cairo_fixed_to_double (c->y), - _cairo_fixed_to_double (d->x), - _cairo_fixed_to_double (d->y)); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_path_close_path (void *closure) -{ - cairo_ps_surface_path_info_t *info = closure; - - _cairo_output_stream_printf (info->output_stream, - "closepath\n"); - info->has_current_point = FALSE; - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _cairo_ps_surface_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, @@ -1200,83 +1379,6 @@ _cairo_ps_surface_get_extents (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED -static cairo_int_status_t -_cairo_ps_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_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) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_output_stream_t *stream = surface->stream; - cairo_font_subset_t *subset; - int i, subset_index; - - if (surface->fallback) - return CAIRO_STATUS_SUCCESS; - - if (surface->need_start_page) { - /* Optimize away erasing of nothing. */ - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - _cairo_ps_surface_start_page (surface); - } - - /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */ - if (! _cairo_scaled_font_is_ft (scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->fallback) - return CAIRO_STATUS_SUCCESS; - - if (pattern_operation_needs_fallback (op, pattern)) - return _cairo_ps_surface_add_fallback_area (surface, dest_x, dest_y, width, height); - - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_old_show_glyphs\n"); - - emit_pattern (surface, pattern); - - /* FIXME: Need to optimize this so we only do this sequence if the - * font isn't already set. */ - - subset = _cairo_ps_surface_get_font (surface, scaled_font); - _cairo_output_stream_printf (stream, - "/f%d findfont\n" - "[ %f %f %f %f 0 0 ] makefont\n" - "setfont\n", - subset->font_id, - scaled_font->scale.xx, - scaled_font->scale.yx, - scaled_font->scale.xy, - -scaled_font->scale.yy); - - /* FIXME: Need to optimize per glyph code. Should detect when - * glyphs share the same baseline and when the spacing corresponds - * to the glyph widths. */ - - for (i = 0; i < num_glyphs; i++) { - subset_index = _cairo_font_subset_use_glyph (subset, glyphs[i].index); - _cairo_output_stream_printf (stream, - "%f %f moveto (\\%o) show\n", - glyphs[i].x, - glyphs[i].y, - subset_index); - - } - - return CAIRO_STATUS_SUCCESS; -} -#endif - static cairo_int_status_t _cairo_ps_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -1496,6 +1598,14 @@ _cairo_ps_surface_fill (void *abstract_surface, return status; } +static char +hex_digit (int i) +{ + i &= 0xf; + if (i < 10) return '0' + i; + return 'a' + (i - 10); +} + static cairo_int_status_t _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, @@ -1508,6 +1618,10 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_int_status_t status; cairo_path_fixed_t *path; + int i; + int cur_subfont = -1, subfont; + cairo_ps_font_t *ps_font; + cairo_ps_glyph_t *ps_glyph; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1523,7 +1637,40 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_show_glyphs\n"); + status = _cairo_ps_font_find (surface, scaled_font, &ps_font); + if (status) + goto fallback; + if (num_glyphs) + emit_pattern (surface, source); + + for (i = 0; i < num_glyphs; i++) { + status = _cairo_ps_glyph_find (ps_font, scaled_font, + glyphs[i].index, &ps_glyph); + if (status) { + glyphs += i; + num_glyphs -= i; + goto fallback; + } + subfont = ps_glyph->output_glyph >> 8; + if (subfont != cur_subfont) { + _cairo_output_stream_printf (surface->stream, + "/CairoFont-%d-%d 1 selectfont\n", + ps_font->output_font, + subfont); + cur_subfont = subfont; + } + _cairo_output_stream_printf (surface->stream, + "%f %f moveto <%c%c> show\n", + glyphs[i].x, glyphs[i].y, + hex_digit (ps_glyph->output_glyph >> 4), + hex_digit (ps_glyph->output_glyph)); + } + + return CAIRO_STATUS_SUCCESS; + +fallback: + path = _cairo_path_fixed_create (); _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, path); status = _cairo_ps_surface_fill (abstract_surface, op, source, @@ -1551,11 +1698,7 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { NULL, /* set_clip_region */ _cairo_ps_surface_intersect_clip_path, _cairo_ps_surface_get_extents, -#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED - _cairo_ps_surface_old_show_glyphs, -#else NULL, /* old_show_glyphs */ -#endif NULL, /* get_font_options */ NULL, /* flush */ NULL, /* mark_dirty_rectangle */ From 5ee26e3b0eec85ac2e9c07d828eae0c8e1a57364 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 10 Apr 2006 19:18:36 +0200 Subject: [PATCH 100/155] * Save and restore state when drawing glyphs using the short circuit. --- src/cairo-atsui-font.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 7aae7c82a..6c9f715c5 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -576,6 +576,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, _cairo_pattern_is_opaque_solid (pattern) && op == CAIRO_OPERATOR_OVER; + can_draw_directly = FALSE; if (!can_draw_directly) { rect.x = dest_x; rect.y = dest_y; @@ -604,6 +605,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, drawingContext = myBitmapContext; } else { drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context; + CGContextSaveGState (drawingContext); } ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); @@ -687,6 +689,8 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, destImageSurface, &rect, extra); + } else { + CGContextRestoreGState (drawingContext); } return CAIRO_STATUS_SUCCESS; From f02aacbb5f8068f6b0101b3200bd3a0d73746dd4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 10 Apr 2006 10:54:24 -0700 Subject: [PATCH 101/155] Update dash-caps-joins test cases to show independent dashing of sub-paths. We would like to be compatible with PostScript/PDF dash semantics. And according to the description of the setdash operator in section 8.2 of the PostScript Language Reference Manual, (as well as the description of the line dash pattern in section 4.3.2 of the PDF Reference), each sub-path should be treated independently with respect to dashing. With this change, this test now fails for most backends for which it previously passed. --- test/dash-caps-joins-ref.png | Bin 3219 -> 2583 bytes test/dash-caps-joins-rgb24-ref.png | Bin 2946 -> 2465 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/dash-caps-joins-ref.png b/test/dash-caps-joins-ref.png index 5c887c5c97dba33fb5941de70702e03c12f476d3..9218ae49954e67791f2f8426543a4da18ce206bf 100644 GIT binary patch delta 2548 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 Kt9pye$^Qn6RI-l% From 65e706ee14b9bfbc2ce0e83b35a813d51d97592f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:13:36 -0400 Subject: [PATCH 102/155] Reset dashing for new subpaths. Fixes the bug mentioned in b87726ee2aa0220b66ee4d97513c0ac89ffc4621 by reseting the dash pattern for each new subpath. This is correct behaviour according to the end of PDF Reference v1.6 section 4.3.2. This commit now makes the dash-caps-joins test case pass for all backends except for the PostScript backend. --- src/cairo-path-stroke.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 96664ceeb..a02a3aaa4 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -615,6 +615,16 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_cairo_stroker_move_to_dashed (void *closure, cairo_point_t *point) +{ + /* reset the dash pattern for new sub paths */ + cairo_stroker_t *stroker = closure; + _cairo_stroker_start_dash (stroker); + + return _cairo_stroker_move_to (closure, point); +} + static cairo_status_t _cairo_stroker_line_to (void *closure, cairo_point_t *point) { @@ -954,7 +964,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, if (stroker.style->dash) status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, - _cairo_stroker_move_to, + _cairo_stroker_move_to_dashed, _cairo_stroker_line_to_dashed, _cairo_stroker_curve_to_dashed, _cairo_stroker_close_path, From 08b109fb9a8c54f4764fe7a94ce7833e832bc157 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 10 Apr 2006 11:00:26 -0700 Subject: [PATCH 103/155] Add new ps-specific reference image for dash-caps-joins test. With the recent fix to the treatment of sub-paths with respect to dashing, this test is now correct except for slight difference in ghostscript vs. cairo rasterization. This commit records the ghostscript output as the new reference image against which the ps output should be tested. --- test/dash-caps-joins-ps-argb32-ref.png | Bin 0 -> 1247 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/dash-caps-joins-ps-argb32-ref.png diff --git a/test/dash-caps-joins-ps-argb32-ref.png b/test/dash-caps-joins-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..629b97b34740b4b212f0e4d0a8ac583083c60088 GIT binary patch literal 1247 zcmeAS@N?(olHy`uVBq!ia0vp^&wx0Jg9%6~Gwgi?q&N#aB8wRqxP?HN@zUM8KR`kG z64!{5;QX|b^2DN42G`&K1^0~n;*#RzqRfI41q(w{Jp)6&`ZH@77+BIgT^vIy=DeMA zanfxC9@n>i|Nl?F+kU1h<~Um;%bnGGpRYWtB5^R1Y1@>)7Ja@Pa{t!6YY@owh;(e5 zBAS9m-OPFOd*3eZXU?_ufLTOn}(WW4Vc$E7w`g5Dfijv)CEDq;@5d0>fkft$;gvfZ6F?u)1ReyfdAHCyC( z`|JUmU#&cW*Czis!|m$Axu!Q9$mH>8vfOu2?&5^U(+$t9@czC1+tud2zLaFg=-m4D$Yh^p z&On#RllU(l`WEcBEb)lk#anx9mR5Xs)_tM8UG~uI_0R36^)yV8^{CLg#^RTKdf&YN zbL9oMY&s@*@XLd@oUCd2>-T&WP*J+$H0wOW#Cd0L8voyau#+Ps@=p{Se~F;uRU-wh z*=x)`Onmoy!RPOy#}3Xnb1yixYT85Q$G%%Ei(5*iRvhbznVgbu_C%<5`n%nCp7ln7xf^o&z=1ZRR#PWBJ@pII>;Fr19-VqV^MPt>`_rhl z8~cMU?0sWWaLM6(_dOx~o%4)BYHMqjcIKSgbmpV-mB^gqg%LHn`|}j1Zo2NZYpX41 zyWt|o{f2k8P3OI%?whgdy*YpM>@3+|%T8%koB#Ut_-Ets3Cpa$ZCx35Q@T+*_<{JG z<>5NnZ!hfGbLP~sd40_Ng7cPXtdX5%>%3m)s7RNQ@8lC}*VOnn*J|yYs=L5lr9@(F zZm`%{<}Lp?)Wx!Ahew)tOLQ-HZCth0R=U~8sUqv#uHy$Uhb%i-zc?rNd7Rnh1C?3l ztd4<%67_>m{rzFPSfOabx4y;`U6{EaYmopE{KM?X;cIToB~T75oESV^{an^LB{Ts5 Df%H;w literal 0 HcmV?d00001 From baa3436e9d8ea37c1204f752cac78a8cbc891f18 Mon Sep 17 00:00:00 2001 From: Laxmi Harikumar Date: Mon, 10 Apr 2006 12:04:01 -0700 Subject: [PATCH 104/155] Simple fix for build failure on DEC/OSF1. Apparently this platform also requires inttypes.h rather than stdint.h. This should fix the bug reported here: https://bugzilla.mozilla.org/show_bug.cgi?id=331428 --- pixman/src/pixman.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h index ecba78a55..00884e7ce 100644 --- a/pixman/src/pixman.h +++ b/pixman/src/pixman.h @@ -81,7 +81,7 @@ SOFTWARE. #if defined (__SVR4) && defined (__sun) # include -#elif defined (__OpenBSD__) || defined (_AIX) +#elif defined (__OpenBSD__) || defined (_AIX) || defined (__osf__) # include #elif defined (_MSC_VER) typedef __int8 int8_t; From df3c02c9ca0c704df3960416fbe689af0cedf2fa Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 10 Apr 2006 22:23:39 +0200 Subject: [PATCH 105/155] Don't set can_draw_directly to FALSE. --- src/cairo-atsui-font.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 6c9f715c5..76b5a3c86 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -576,7 +576,6 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, _cairo_pattern_is_opaque_solid (pattern) && op == CAIRO_OPERATOR_OVER; - can_draw_directly = FALSE; if (!can_draw_directly) { rect.x = dest_x; rect.y = dest_y; From 8ba59b0336ddc581c8f43b4aa5cf9acdb2c001ad Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 10 Apr 2006 22:24:02 +0200 Subject: [PATCH 106/155] Rework the quartz backend to not always hold an image but instead to create it on demand.# --- src/cairo-quartz-private.h | 8 +- src/cairo-quartz-surface.c | 220 ++++++++++++++++++------------------- 2 files changed, 111 insertions(+), 117 deletions(-) diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h index d291c7666..a57e0786f 100644 --- a/src/cairo-quartz-private.h +++ b/src/cairo-quartz-private.h @@ -46,13 +46,9 @@ typedef struct cairo_quartz_surface { cairo_bool_t flipped; - int width; - int height; + cairo_rectangle_t extents; - cairo_image_surface_t *image; - pixman_region16_t *clip_region; - - CGImageRef cgImage; + pixman_region16_t *clip_region; } cairo_quartz_surface_t; cairo_bool_t diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 5bf01bb12..0f8466106 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -50,14 +50,8 @@ _cairo_quartz_surface_finish(void *abstract_surface) { cairo_quartz_surface_t *surface = abstract_surface; - if (surface->image) - cairo_surface_destroy(&surface->image->base); - - if (surface->cgImage) - CGImageRelease(surface->cgImage); - - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); return CAIRO_STATUS_SUCCESS; } @@ -67,64 +61,13 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { - cairo_quartz_surface_t *surface = abstract_surface; - CGColorSpaceRef colorSpace; - void *imageData; - UInt32 imageDataSize, rowBytes; - CGDataProviderRef dataProvider; + cairo_quartz_surface_t *surface = abstract_surface; - /* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t - * struct. If the window is ever drawn to without going through Cairo, then - * we would need to refetch the pixel data from the window into the cached - * image surface. - */ - if (surface->image) { - cairo_surface_reference(&surface->image->base); + if (CGBitmapContextGetBitmapInfo (surface->context) != 0) { + /* XXX: We can create an image out of the bitmap here */ + } - *image_out = surface->image; - return CAIRO_STATUS_SUCCESS; - } - - colorSpace = CGColorSpaceCreateDeviceRGB(); - - - rowBytes = surface->width * 4; - imageDataSize = rowBytes * surface->height; - imageData = malloc(imageDataSize); - - dataProvider = - CGDataProviderCreateWithData(NULL, imageData, imageDataSize, - ImageDataReleaseFunc); - - surface->cgImage = CGImageCreate(surface->width, - surface->height, - 8, - 32, - rowBytes, - colorSpace, - kCGImageAlphaPremultipliedFirst, - dataProvider, - NULL, - false, kCGRenderingIntentDefault); - - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(dataProvider); - - surface->image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data(imageData, - CAIRO_FORMAT_ARGB32, - surface->width, - surface->height, rowBytes); - if (surface->image->base.status) { - if (surface->cgImage) - CGImageRelease(surface->cgImage); - return CAIRO_STATUS_NO_MEMORY; - } - - *image_out = surface->image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_UNSUPPORTED; } static cairo_status_t @@ -136,19 +79,79 @@ _cairo_quartz_surface_acquire_dest_image(void *abstract_surface, void **image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + cairo_surface_t *image_surface; + unsigned char *data; + int x1, y1, x2, y2; - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = surface->image->width; - image_rect->height = surface->image->height; + x1 = surface->extents.x; + x2 = surface->extents.x + surface->extents.width; + y1 = surface->extents.y; + y2 = surface->extents.y + surface->extents.height; - *image_out = surface->image; - if (image_extra) + if (interest_rect->x > x1) + x1 = interest_rect->x; + if (interest_rect->y > y1) + y1 = interest_rect->y; + if (interest_rect->x + interest_rect->width < x2) + x2 = interest_rect->x + interest_rect->width; + if (interest_rect->y + interest_rect->height < y2) + y2 = interest_rect->y + interest_rect->height; + + if (x1 >= x2 || y1 >= y2) { + *image_out = NULL; *image_extra = NULL; + + return CAIRO_STATUS_SUCCESS; + } + + image_rect->x = x1; + image_rect->y = y1; + image_rect->width = x2 - x1; + image_rect->height = y2 - y1; + + data = calloc (image_rect->width * image_rect->height * 4, 1); + image_surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + image_rect->width, + image_rect->height, + image_rect->width * 4); + + *image_out = (cairo_image_surface_t *)image_surface; + *image_extra = data; return CAIRO_STATUS_SUCCESS; + + return CAIRO_INT_STATUS_UNSUPPORTED; } +static CGImageRef +create_image_from_surface (cairo_image_surface_t *image_surface, void *data) +{ + CGImageRef image; + CGColorSpaceRef color_space; + CGDataProviderRef data_provider; + int width, height; + + width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface); + height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface); + + color_space = CGColorSpaceCreateDeviceRGB(); + data_provider = CGDataProviderCreateWithData (NULL, data, + width * height * 4, NULL); + image = CGImageCreate (width, height, + 8, 32, + width * 4, + color_space, + kCGImageAlphaPremultipliedFirst, + data_provider, + NULL, + FALSE, kCGRenderingIntentDefault); + + CGColorSpaceRelease (color_space); + CGDataProviderRelease (data_provider); + + return image; +} static void _cairo_quartz_surface_release_dest_image(void *abstract_surface, @@ -159,25 +162,28 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface, void *image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + CGImageRef image_ref; + CGRect rect; + + image_ref = create_image_from_surface (image, image_extra); - if (surface->image == image) { - CGRect rect; + rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); - rect = CGRectMake(0, 0, surface->width, surface->height); - - if (surface->flipped) { - CGContextSaveGState (surface->context); - CGContextTranslateCTM (surface->context, 0, surface->height); - CGContextScaleCTM (surface->context, 1, -1); - } - - CGContextDrawImage(surface->context, rect, surface->cgImage); - - if (surface->flipped) - CGContextRestoreGState (surface->context); - - memset(surface->image->data, 0, surface->width * surface->height * 4); + if (surface->flipped) { + CGContextSaveGState (surface->context); + CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); + CGContextScaleCTM (surface->context, 1, -1); } + + CGContextDrawImage(surface->context, rect, image_ref); + CFRelease (image_ref); + + if (surface->flipped) { + CGContextRestoreGState (surface->context); + } + + cairo_surface_destroy ((cairo_surface_t *)image); + free (image_extra); } static cairo_int_status_t @@ -185,21 +191,17 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface, pixman_region16_t * region) { cairo_quartz_surface_t *surface = abstract_surface; - unsigned int serial; - serial = _cairo_surface_allocate_clip_serial (&surface->image->base); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); + + if (region) { + surface->clip_region = pixman_region_create (); + pixman_region_copy (surface->clip_region, region); + } else + surface->clip_region = NULL; - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); - - if (region) { - surface->clip_region = pixman_region_create (); - pixman_region_copy (surface->clip_region, region); - } else - surface->clip_region = NULL; - - return _cairo_surface_set_clip_region(&surface->image->base, - region, serial); + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -208,10 +210,7 @@ _cairo_quartz_surface_get_extents (void *abstract_surface, { cairo_quartz_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; + *rectangle = surface->extents; return CAIRO_STATUS_SUCCESS; } @@ -242,6 +241,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, int width, int height) { cairo_quartz_surface_t *surface; + CGRect clip_box; surface = malloc(sizeof(cairo_quartz_surface_t)); if (surface == NULL) { @@ -252,16 +252,14 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend); surface->context = context; - surface->width = width; - surface->height = height; - surface->image = NULL; - surface->cgImage = NULL; - surface->clip_region = NULL; + surface->clip_region = NULL; surface->flipped = flipped; - /* Set up the image surface which Cairo draws into and we blit to & from. */ - void *foo; - _cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo); + 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; return (cairo_surface_t *) surface; } From 3ed576522df8a4e41e856a500539ca3e6f69e2da Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 10 Apr 2006 22:29:51 +0200 Subject: [PATCH 107/155] Remove unused function --- src/cairo-quartz-surface.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 0f8466106..ed6a825e0 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -37,14 +37,6 @@ #include "cairo-private.h" #include "cairo-quartz-private.h" -static void -ImageDataReleaseFunc(void *info, const void *data, size_t size) -{ - if (data != NULL) { - free((void *) data); - } -} - static cairo_status_t _cairo_quartz_surface_finish(void *abstract_surface) { From 1e5f5aed07137d3a823c2d22e29eb0e53e359fef Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 11 Apr 2006 01:07:33 +0200 Subject: [PATCH 108/155] Make the API more like Vlad's new API.# --- src/cairo-quartz-private.h | 2 +- src/cairo-quartz-surface.c | 11 ++++++----- src/cairo-quartz.h | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h index a57e0786f..8b901352b 100644 --- a/src/cairo-quartz-private.h +++ b/src/cairo-quartz-private.h @@ -44,7 +44,7 @@ typedef struct cairo_quartz_surface { CGContextRef context; - cairo_bool_t flipped; + cairo_bool_t y_grows_down; cairo_rectangle_t extents; diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index ed6a825e0..e5b683ac4 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -161,7 +161,7 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface, rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); - if (surface->flipped) { + if (surface->y_grows_down) { CGContextSaveGState (surface->context); CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); CGContextScaleCTM (surface->context, 1, -1); @@ -170,7 +170,7 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface, CGContextDrawImage(surface->context, rect, image_ref); CFRelease (image_ref); - if (surface->flipped) { + if (surface->y_grows_down) { CGContextRestoreGState (surface->context); } @@ -229,8 +229,9 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, - cairo_bool_t flipped, - int width, int height) + int width, + int height, + cairo_bool_t y_grows_down) { cairo_quartz_surface_t *surface; CGRect clip_box; @@ -245,7 +246,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, surface->context = context; surface->clip_region = NULL; - surface->flipped = flipped; + surface->y_grows_down = y_grows_down; clip_box = CGContextGetClipBoundingBox (context); surface->extents.x = clip_box.origin.x; diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h index 9ef537ed3..b3072df76 100644 --- a/src/cairo-quartz.h +++ b/src/cairo-quartz.h @@ -47,9 +47,9 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * cairo_quartz_surface_create (CGContextRef context, - cairo_bool_t flipped, int width, - int height); + int height, + cairo_bool_t y_grows_down); CAIRO_END_DECLS From 6e77a0e248c337bf3f39c0de239a7743c6969efe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Apr 2006 12:28:41 -0700 Subject: [PATCH 109/155] Allow hash entry deletion during cairo_hash_foreach I discovered that _cairo_hash_table_foreach walks over the hash table without preventing it from being resized as a result of deletions occuring from the callback. Kinda nasty when you're trying to free everything from a hash table. It was also easy to fix; just prevent the table from being resized while iterating and clean it up after the iteration is completed. --- src/cairo-hash.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/cairo-hash.c b/src/cairo-hash.c index e44ab3025..bfaac57ff 100644 --- a/src/cairo-hash.c +++ b/src/cairo-hash.c @@ -124,6 +124,7 @@ struct _cairo_hash_table { cairo_hash_entry_t **entries; unsigned long live_entries; + unsigned long iterating; /* Iterating, no insert, no resize */ }; /** @@ -163,6 +164,7 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal) } hash_table->live_entries = 0; + hash_table->iterating = 0; return hash_table; } @@ -179,6 +181,10 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal) * and this function will halt. The rationale for this behavior is to * avoid memory leaks and to avoid needless complication of the API * with destroy notifiy callbacks. + * + * WARNING: The hash_table must have no running iterators in it when + * _cairo_hash_table_destroy is called. It is a fatal error otherwise, + * and this function will halt. **/ void _cairo_hash_table_destroy (cairo_hash_table_t *hash_table) @@ -188,6 +194,8 @@ _cairo_hash_table_destroy (cairo_hash_table_t *hash_table) /* The hash table must be empty. Otherwise, halt. */ assert (hash_table->live_entries == 0); + /* No iterators can be running. Otherwise, halt. */ + assert (hash_table->iterating == 0); free (hash_table->entries); hash_table->entries = NULL; @@ -440,6 +448,9 @@ _cairo_hash_table_random_entry (cairo_hash_table_t *hash_table, * WARNING: It is a fatal error if an entry exists in the hash table * with a matching key, (this function will halt). * + * WARNING: It is a fatal error to insert an element while + * an iterator is running + * * Instead of using insert to replace an entry, consider just editing * the entry obtained with _cairo_hash_table_lookup. Or if absolutely * necessary, use _cairo_hash_table_remove first. @@ -454,6 +465,9 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table, cairo_status_t status; cairo_hash_entry_t **entry; + /* Insert is illegal while an iterator is running. */ + assert (hash_table->iterating == 0); + entry = _cairo_hash_table_lookup_internal (hash_table, key_and_value, FALSE); @@ -498,11 +512,16 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table, *entry = DEAD_ENTRY; hash_table->live_entries--; - /* This call _can_ fail, but only in failing to allocate new - * memory to shrink the hash table. It does leave the table in a - * consistent state, and we've already succeeded in removing the - * entry, so we don't examine the failure status of this call. */ - _cairo_hash_table_resize (hash_table); + /* Check for table resize. Don't do this when iterating as this will + * reorder elements of the table and cause the iteration to potentially + * skip some elements. */ + if (hash_table->iterating == 0) { + /* This call _can_ fail, but only in failing to allocate new + * memory to shrink the hash table. It does leave the table in a + * consistent state, and we've already succeeded in removing the + * entry, so we don't examine the failure status of this call. */ + _cairo_hash_table_resize (hash_table); + } } /** @@ -513,6 +532,12 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table, * * Call @hash_callback for each live entry in the hash table, in a * non-specified order. + * + * Entries in @hash_table may be removed by code executed from @hash_callback. + * + * Entries may not be inserted to @hash_table, nor may @hash_table + * be destroyed by code executed from @hash_callback. The relevant + * functions will halt in these cases. **/ void _cairo_hash_table_foreach (cairo_hash_table_t *hash_table, @@ -525,9 +550,17 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table, if (hash_table == NULL) return; + /* Mark the table for iteration */ + ++hash_table->iterating; for (i = 0; i < hash_table->arrangement->size; i++) { entry = hash_table->entries[i]; if (ENTRY_IS_LIVE(entry)) hash_callback (entry, closure); } + /* If some elements were deleted during the iteration, + * the table may need resizing. Just do this every time + * as the check is inexpensive. + */ + if (--hash_table->iterating == 0) + _cairo_hash_table_resize (hash_table); } From 523f9e46d87392a539c26ade18d99a3db7ed833d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 11 Apr 2006 20:49:55 -0400 Subject: [PATCH 110/155] Make cairo_t and cairo_output_stream_t destructors handle NULL. All other cairo destructors and reference functions accept and ignore NULL, so fix up cairo_destroy(), cairo_reference(), and cairo_output_stream_destroy() to do so too. --- src/cairo-output-stream.c | 3 +++ src/cairo.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 16d937172..54bc81f18 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -111,6 +111,9 @@ _cairo_output_stream_close (cairo_output_stream_t *stream) void _cairo_output_stream_destroy (cairo_output_stream_t *stream) { + if (stream == NULL) + return; + _cairo_output_stream_close (stream); free (stream); } diff --git a/src/cairo.c b/src/cairo.c index d0dd4ecfb..60166f554 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -220,6 +220,9 @@ cairo_create (cairo_surface_t *target) cairo_t * cairo_reference (cairo_t *cr) { + if (cr == NULL) + return NULL; + if (cr->ref_count == (unsigned int)-1) return cr; @@ -241,6 +244,9 @@ cairo_reference (cairo_t *cr) void cairo_destroy (cairo_t *cr) { + if (cr == NULL) + return; + if (cr->ref_count == (unsigned int)-1) return; From 39592788b38a8e8db5335d836a8eaa7ace08fc1c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 10:56:42 -0700 Subject: [PATCH 111/155] Print both page label and number in PostScript %%Page headers. --- src/cairo-ps-surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 8a3786871..badadb18a 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -320,7 +320,7 @@ static void _cairo_ps_surface_start_page (cairo_ps_surface_t *surface) { _cairo_output_stream_printf (surface->stream, - "%%%%Page: %d\n", + "%%%%Page: %d %d\n", ++surface->num_pages); From 0386a728957bdb3549da8e772c31b86295175a4b Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 11:06:06 -0700 Subject: [PATCH 112/155] Add some documentation to string_array_stream --- src/cairo-ps-surface.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index badadb18a..c8f1f9ad7 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -754,6 +754,20 @@ _string_array_stream_close (void *closure) return status; } +/* A string_array_stream wraps an existing output stream. It takes the + * data provided to it and output one or more consecutive string + * objects, each within the standard PostScript implementation limit + * of 65k characters. + * + * The strings are each separated by a space character for easy + * inclusion within an array object, (but the array delimiters are not + * added by the string_array_stream). + * + * The string array stream is also careful to wrap the output within + * STRING_ARRAY_MAX_COLUMN columns (+/- 1). The stream also adds + * necessary escaping for special characters within a string, + * (specifically '\', '(', and ')'). + */ static cairo_output_stream_t * _string_array_stream_create (cairo_output_stream_t *output) { From 5444aa55b35aff7d6cff8b5e8a5ab020711562ac Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 13:34:03 -0700 Subject: [PATCH 113/155] Clean up output_stream error handling in _cairo_ps_surface_create. We teach the output stream to catch a NULL file error here, which allows for less checking in ps_surface_create. We also fix the ps surface code to look for the status of a nil stream rather than checking for NULL. --- src/cairo-output-stream.c | 3 +++ src/cairo-ps-surface.c | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index a03131a9a..3b53aa930 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -356,6 +356,9 @@ stdio_close (void *closure) cairo_output_stream_t * _cairo_output_stream_create_for_file (FILE *file) { + if (file == NULL) + return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error; + return _cairo_output_stream_create (stdio_write, stdio_flush, file); } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 6bebd9164..70e13ed4a 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -63,12 +63,16 @@ _cairo_ps_set_paginated_mode (cairo_surface_t *target, typedef struct cairo_ps_surface { cairo_surface_t base; - /* PS-specific fields */ - cairo_output_stream_t *stream; + /* Here final_stream corresponds to the stream/file passed to + * cairo_ps_surface_create surface is built. Meanwhile stream is a + * temporary stream in which the file output is built, (so that + * the header can be built and inserted into the target stream + * before the contents of the temporary stream are copied). */ cairo_output_stream_t *final_stream; FILE *tmpfile; - + cairo_output_stream_t *stream; + double width; double height; double x_dpi; @@ -146,6 +150,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, double width, double height) { + cairo_status_t status; cairo_ps_surface_t *surface; surface = malloc (sizeof (cairo_ps_surface_t)); @@ -157,18 +162,14 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_surface_init (&surface->base, &cairo_ps_surface_backend); surface->final_stream = stream; + surface->tmpfile = tmpfile (); - - if (!surface->tmpfile) { - free (surface); - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile); - if (!surface->stream) { + status = _cairo_output_stream_get_status (surface->stream); + if (status) { fclose (surface->tmpfile); free (surface); - _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } From 32994379db92ef8208ba11b825b1246e2b442566 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 13:40:05 -0700 Subject: [PATCH 114/155] Fix missing argument to printf in _cairo_ps_surface_stat_page --- src/cairo-ps-surface.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 70e13ed4a..ef4b89c4d 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -359,8 +359,9 @@ _cairo_ps_surface_start_page (cairo_ps_surface_t *surface) { _cairo_output_stream_printf (surface->stream, "%%%%Page: %d %d\n", - ++surface->num_pages); - + surface->num_pages, + surface->num_pages); + surface->num_pages++; _cairo_output_stream_printf (surface->stream, "gsave %f %f translate %f %f scale \n", From d9137e56b6a8f1ddb44a01bf34301117b0696f0b Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 13:44:14 -0700 Subject: [PATCH 115/155] Use ferror to get error checking for stdio-based output streams. --- src/cairo-output-stream.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 3b53aa930..e9b572786 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -339,18 +339,23 @@ stdio_flush (void *closure) fflush (file); - return CAIRO_STATUS_SUCCESS; /* XXX errors */ + if (ferror (file)) + return CAIRO_STATUS_WRITE_ERROR; + else + return CAIRO_STATUS_SUCCESS; } static cairo_status_t stdio_close (void *closure) { + cairo_status_t status; FILE *file = closure; - fflush (file); + status = stdio_flush (closure); + fclose (file); - return CAIRO_STATUS_SUCCESS; /* XXX errors */ + return status; } cairo_output_stream_t * From 193b43001de11945b0ae7ca4ee685590d9f79137 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 14:06:26 -0700 Subject: [PATCH 116/155] Propagate stream status values through _cairo_ps_surface_finish --- src/cairo-ps-surface.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index ef4b89c4d..278753883 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -322,10 +322,10 @@ cairo_ps_surface_set_dpi (cairo_surface_t *surface, #endif } -/* XXX */ static cairo_status_t _cairo_ps_surface_finish (void *abstract_surface) { + cairo_status_t status; cairo_ps_surface_t *surface = abstract_surface; _cairo_ps_surface_emit_header (surface); @@ -345,13 +345,18 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->fonts); #endif + _cairo_output_stream_close (surface->stream); + status = _cairo_output_stream_get_status (surface->stream); _cairo_output_stream_destroy (surface->stream); fclose (surface->tmpfile); + _cairo_output_stream_close (surface->final_stream); + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_output_stream_get_status (surface->final_stream); _cairo_output_stream_destroy (surface->final_stream); - return CAIRO_STATUS_SUCCESS; + return status; } static void From b30e281627d86f3c0d0f4d5008bbbf7e77c09350 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 13:55:24 -0700 Subject: [PATCH 117/155] Add documentation for _cairo_output_stream_create_for_file. --- src/cairoint.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cairoint.h b/src/cairoint.h index 4cfa94840..13880cb85 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2192,6 +2192,13 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream); cairo_private cairo_output_stream_t * _cairo_output_stream_create_for_filename (const char *filename); +/* This function never returns NULL. If an error occurs (NO_MEMORY or + * WRITE_ERROR) while trying to create the output stream this function + * returns a valid pointer to a nil output stream. + * + * The caller still "owns" file and is responsible for calling fclose + * on it when finished. The stream will not do this itself. + */ cairo_private cairo_output_stream_t * _cairo_output_stream_create_for_file (FILE *file); From d60eaab222fb1ce19ef7bbbf496ad444f07aa703 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 15:48:59 -0700 Subject: [PATCH 118/155] Add simple word wrapping to keep PostScript output within 80 columns or less. --- src/cairo-ps-surface.c | 109 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 93a3e9348..e19182dde 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -696,12 +696,117 @@ cairo_ps_surface_set_dpi (cairo_surface_t *surface, } +/* A word wrap stream can be used as a filter to do word wrapping on + * top of an existing output stream. The word wrapping is quite + * simple, using isspace to determine characters that separate + * words. Any word that will cause the column count exceeed the given + * max_column will have a '\n' character emitted before it. + * + * The stream is careful to maintain integrity for words that cross + * the boundary from one call to write to the next. + * + * Note: This stream does not guarantee that the output will never + * exceed max_column. In particular, if a single word is larger than + * max_column it will not be broken up. + */ +typedef struct _word_wrap_stream { + cairo_output_stream_t *output; + int max_column; + int column; + cairo_bool_t last_write_was_space; +} word_wrap_stream_t; + +static int +_count_word_up_to (const unsigned char *s, int length) +{ + int word = 0; + + while (length--) { + if (! isspace (*s++)) + word++; + else + return word; + } + + return word; +} + +static cairo_status_t +_word_wrap_stream_write (void *closure, + const unsigned char *data, + unsigned int length) +{ + word_wrap_stream_t *stream = closure; + cairo_bool_t newline; + int word; + + while (length) { + if (isspace (*data)) { + newline = (*data == '\n' || *data == '\r'); + if (! newline && stream->column >= stream->max_column) { + _cairo_output_stream_printf (stream->output, "\n"); + stream->column = 0; + } + _cairo_output_stream_write (stream->output, data, 1); + data++; + length--; + if (newline) + stream->column = 0; + else + stream->column++; + stream->last_write_was_space = TRUE; + } else { + word = _count_word_up_to (data, length); + /* Don't wrap if this word is a continuation of a word + * from a previous call to write. */ + if (stream->column + word >= stream->max_column && + stream->last_write_was_space) + { + _cairo_output_stream_printf (stream->output, "\n"); + stream->column = 0; + } + _cairo_output_stream_write (stream->output, data, word); + data += word; + length -= word; + stream->column += word; + stream->last_write_was_space = FALSE; + } + } + + return _cairo_output_stream_get_status (stream->output); +} + +static cairo_output_stream_t * +_word_wrap_stream_create (cairo_output_stream_t *output, int max_column) +{ + word_wrap_stream_t *stream; + + stream = malloc (sizeof (word_wrap_stream_t)); + if (stream == NULL) + return (cairo_output_stream_t *) &cairo_output_stream_nil; + + stream->output = output; + stream->max_column = max_column; + stream->column = 0; + stream->last_write_was_space = FALSE; + + return _cairo_output_stream_create (_word_wrap_stream_write, + NULL, stream); +} + static cairo_status_t _cairo_ps_surface_finish (void *abstract_surface) { cairo_status_t status; cairo_ps_surface_t *surface = abstract_surface; + cairo_output_stream_t *final_stream, *word_wrap; + /* Save final_stream to be restored later. */ + final_stream = surface->final_stream; + + word_wrap = _word_wrap_stream_create (final_stream, 79); + surface->final_stream = word_wrap; + _cairo_ps_surface_emit_header (surface); _cairo_ps_surface_emit_fonts (surface); @@ -716,6 +821,10 @@ _cairo_ps_surface_finish (void *abstract_surface) fclose (surface->tmpfile); + /* Restore final stream before final cleanup. */ + _cairo_output_stream_destroy (word_wrap); + surface->final_stream = final_stream; + _cairo_output_stream_close (surface->final_stream); if (status == CAIRO_STATUS_SUCCESS) status = _cairo_output_stream_get_status (surface->final_stream); From 6beababd47aabfb4896a878de09d729f287aa714 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 12 Apr 2006 16:19:08 -0700 Subject: [PATCH 119/155] Optimize PostScript file size with procedures instead of builtin operators. This is based on a suggestion by Michael Sweet. --- src/cairo-ps-surface.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index e19182dde..d02eacf01 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -123,7 +123,7 @@ _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point) cairo_ps_surface_path_info_t *info = closure; _cairo_output_stream_printf (info->output_stream, - "%f %f moveto ", + "%f %f M ", _cairo_fixed_to_double (point->x), _cairo_fixed_to_double (point->y)); info->has_current_point = TRUE; @@ -138,9 +138,9 @@ _cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point) const char *ps_operator; if (info->has_current_point) - ps_operator = "lineto"; + ps_operator = "L"; else - ps_operator = "moveto"; + ps_operator = "M"; _cairo_output_stream_printf (info->output_stream, "%f %f %s ", @@ -161,7 +161,7 @@ _cairo_ps_surface_path_curve_to (void *closure, cairo_ps_surface_path_info_t *info = closure; _cairo_output_stream_printf (info->output_stream, - "%f %f %f %f %f %f curveto ", + "%f %f %f %f %f %f C ", _cairo_fixed_to_double (b->x), _cairo_fixed_to_double (b->y), _cairo_fixed_to_double (c->x), @@ -179,7 +179,7 @@ _cairo_ps_surface_path_close_path (void *closure) if (info->has_current_point) _cairo_output_stream_printf (info->output_stream, - "closepath\n"); + "P\n"); info->has_current_point = FALSE; return CAIRO_STATUS_SUCCESS; @@ -209,6 +209,18 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "%%%%LanguageLevel: 2\n" "%%%%Orientation: Portrait\n" "%%%%EndComments\n"); + + _cairo_output_stream_printf (surface->final_stream, + "%%%%BeginProlog\n" + "/C{curveto}bind def\n" + "/F{fill}bind def\n" + "/G{setgray}bind def\n" + "/L{lineto}bind def\n" + "/M{moveto}bind def\n" + "/P{closepath}bind def\n" + "/R{setrgbcolor}bind def\n" + "/S{show}bind def\n" + "%%%%EndProlog\n"); } static cairo_bool_t @@ -429,7 +441,7 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, &info); _cairo_output_stream_printf (surface->final_stream, - "fill\n"); + "F\n"); _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); @@ -1343,11 +1355,11 @@ emit_solid_pattern (cairo_ps_surface_t *surface, { if (color_is_gray (&pattern->color)) _cairo_output_stream_printf (surface->stream, - "%f setgray\n", + "%f G\n", pattern->color.red); else _cairo_output_stream_printf (surface->stream, - "%f %f %f setrgbcolor\n", + "%f %f %f R\n", pattern->color.red, pattern->color.green, pattern->color.blue); @@ -1546,12 +1558,12 @@ _cairo_ps_surface_paint (void *abstract_surface, info.output_stream = stream; info.has_current_point = FALSE; - _cairo_output_stream_printf (stream, "0 0 moveto\n"); - _cairo_output_stream_printf (stream, "%f 0 lineto\n", surface->width); - _cairo_output_stream_printf (stream, "%f %f lineto\n", + _cairo_output_stream_printf (stream, "0 0 M\n"); + _cairo_output_stream_printf (stream, "%f 0 L\n", surface->width); + _cairo_output_stream_printf (stream, "%f %f L\n", surface->width, surface->height); - _cairo_output_stream_printf (stream, "0 %f lineto\n", surface->height); - _cairo_output_stream_printf (stream, "closepath fill\n"); + _cairo_output_stream_printf (stream, "0 %f L\n", surface->height); + _cairo_output_stream_printf (stream, "P F\n"); return CAIRO_STATUS_SUCCESS; } @@ -1713,7 +1725,7 @@ _cairo_ps_surface_fill (void *abstract_surface, switch (fill_rule) { case CAIRO_FILL_RULE_WINDING: - ps_operator = "fill"; + ps_operator = "F"; break; case CAIRO_FILL_RULE_EVEN_ODD: ps_operator = "eofill"; @@ -1791,7 +1803,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cur_subfont = subfont; } _cairo_output_stream_printf (surface->stream, - "%f %f moveto <%c%c> show\n", + "%f %f M <%c%c> S\n", glyphs[i].x, glyphs[i].y, hex_digit (ps_glyph->output_glyph >> 4), hex_digit (ps_glyph->output_glyph)); From f17b347ab443fcc12f9098f9b601334f85d20a30 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 13 Apr 2006 07:59:52 -0700 Subject: [PATCH 120/155] Fix page numbers in PostScript output to start at 1 --- src/cairo-ps-surface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index d02eacf01..b5062d4b5 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -848,11 +848,12 @@ _cairo_ps_surface_finish (void *abstract_surface) static void _cairo_ps_surface_start_page (cairo_ps_surface_t *surface) { + /* Increment before print so page numbers start at 1. */ + surface->num_pages++; _cairo_output_stream_printf (surface->stream, "%%%%Page: %d %d\n", surface->num_pages, surface->num_pages); - surface->num_pages++; _cairo_output_stream_printf (surface->stream, "gsave %f %f translate %f %f scale \n", From 584109d5e6160c1e74da0e79b6e024701a354293 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:11:47 -0400 Subject: [PATCH 121/155] Add test case for dashed lines. The new test case tests a variety of circumstances involved with zero length dashing. --- test/Makefile.am | 4 ++ test/dash-zero-length-ps-argb32-ref.png | Bin 0 -> 222 bytes test/dash-zero-length-ref.png | Bin 0 -> 235 bytes test/dash-zero-length-rgb24-ref.png | Bin 0 -> 222 bytes test/dash-zero-length.c | 88 ++++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 test/dash-zero-length-ps-argb32-ref.png create mode 100644 test/dash-zero-length-ref.png create mode 100644 test/dash-zero-length-rgb24-ref.png create mode 100644 test/dash-zero-length.c diff --git a/test/Makefile.am b/test/Makefile.am index b951b4392..1eecbe27c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -16,6 +16,7 @@ create-from-png \ create-from-png-stream \ dash-caps-joins \ dash-offset-negative \ +dash-zero-length \ extend-reflect \ fill-and-stroke \ fill-rule \ @@ -140,6 +141,8 @@ dash-caps-joins-rgb24-ref.png \ dash-offset-negative-ref.png \ dash-offset-negative-rgb24-ref.png \ dash-offset-negative-ps-rgb24-ref.png \ +dash-zero-length-ref.png \ +dash-zero-length-rgb24-ref.png \ extend-reflect-ref.png \ extend-reflect-rgb24-ref.png \ fill-and-stroke-ref.png \ @@ -317,6 +320,7 @@ create_from_png_LDADD = $(LDADDS) create_from_png_stream_LDADD = $(LDADDS) dash_caps_joins_LDADD = $(LDADDS) dash_offset_negative_LDADD = $(LDADDS) +dash_zero_length_LDADD = $(LDADDS) extend_reflect_LDADD = $(LDADDS) fill_and_stroke_LDADD = $(LDADDS) fill_rule_LDADD = $(LDADDS) diff --git a/test/dash-zero-length-ps-argb32-ref.png b/test/dash-zero-length-ps-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..0f66648474d95b794abae4f63409c57c9774e92e GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^!ayv^!2~2@RyO?wQk(@Ik;M!Q+(IDCcJ4^_D Q0<@CB)78&qol`;+033f$s{jB1 literal 0 HcmV?d00001 diff --git a/test/dash-zero-length-ref.png b/test/dash-zero-length-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aca856f2bfe47ebd0cb75578ad4271eb7229e407 GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^!ayv^!3HERpB7yOq}Y|gW!U_%O?Xx*h@Tp zUD>a(@G*-S?|Jm@Cs3%@)5S5wqWA5T-MkG3JTCJEZLh33ptFI|+lYIO!+Dlvg(}L5 z6CE1bCdd3pnR{+Ni;)w9h)MGVk?(*1{3zu5*y+UjWm+FoHrM;stX5A)UA4!HeqNG% z-Ei&c+QK8B&f6@P$+g?uAT#0fq`A$7 gd;ZQ%4d*v7UfxqT`zopr06#fht^fc4 literal 0 HcmV?d00001 diff --git a/test/dash-zero-length-rgb24-ref.png b/test/dash-zero-length-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e40e85c892e1cf56ca0355f41151d323fc1077 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^!ayv^!2~2@RyO?wQfx`y?k)`fL2$v|<&%LT>?NMQ zuI$%X_?V?RcDPqg017pDx;Tbd^uE2ak@t{+KmdjLK3CYh~`4XAa$1_{JwcGdj4v z=*L&qRkm{i8ooTuDc;eP{`Ag*cdOoQJA0hxR1TN=AI`H`w>j?~SZu#gIFeC|&3%3J Tnp=;7Zej3r^>bP0l+XkK1{YWI literal 0 HcmV?d00001 diff --git a/test/dash-zero-length.c b/test/dash-zero-length.c new file mode 100644 index 000000000..a5d0047de --- /dev/null +++ b/test/dash-zero-length.c @@ -0,0 +1,88 @@ +/* + * Copyright © 2006 Jeff Muizelaar + * + * 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 + * Jeff Muizelaar. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Jeff Muizelaar. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * JEFF MUIZELAAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL JEFF MUIZELAAR 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. + * + * Author: Jeff Muizelaar + */ + +#include "cairo-test.h" + +#define IMAGE_WIDTH 19 +#define IMAGE_HEIGHT 25 + +/* A test of the two extremes of dashing: a solid line + * and an invisible one. Also test that capping works + * on invisible lines. + */ + +cairo_test_t test = { + "dash-zero-length", + "Tests cairo_set_dash with zero length", + IMAGE_WIDTH, IMAGE_HEIGHT +}; + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + double solid_line[] = { 4, 0 }; + double invisible_line[] = { 0, 4 }; + double dotted_line[] = { 0, 6 }; + double rounded_line[] = { 2, 6 }; + + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_set_line_width (cr, 2); + + /* draw a solid line */ + cairo_set_dash (cr, solid_line, 2, 0); + cairo_move_to (cr, 1, 2); + cairo_line_to (cr, 18, 2); + cairo_stroke (cr); + + /* draw an invisible line */ + cairo_set_dash (cr, invisible_line, 2, 0); + cairo_move_to (cr, 1, 8); + cairo_line_to (cr, 18, 8); + cairo_stroke (cr); + + /* draw a dotted line */ + cairo_set_line_width (cr, 5); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_dash (cr, dotted_line, 2, 0); + cairo_move_to (cr, 5, 13); + cairo_line_to (cr, 18, 13); + cairo_stroke (cr); + + /* draw a rounded line */ + cairo_set_line_width (cr, 5); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_dash (cr, rounded_line, 2, 2); + cairo_move_to (cr, 5, 20); + cairo_line_to (cr, 18, 20); + cairo_stroke (cr); + + return CAIRO_TEST_SUCCESS; +} + +int +main (void) +{ + return cairo_test (&test, draw); +} From 8a2ea660fb59beb4eacaf73978368c8db7a6b584 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:10:46 -0400 Subject: [PATCH 122/155] Check for zero length dashed lines. This makes line_to_dashed more like line_to by returning immediately on degenerate paths. This is needed so that we can do the slope calculation for the entire line. --- src/cairo-path-stroke.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index a02a3aaa4..ff09f308b 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -686,7 +686,15 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) if (!stroker->has_current_point) return _cairo_stroker_move_to (stroker, point); - + + if (p1->x == p2->x && p1->y == p2->y) { + /* XXX: Need to rethink how this case should be handled, (both + here and in cairo_stroker_add_sub_edge and in _compute_face). The + key behavior is that degenerate paths should draw as much + as possible. */ + return CAIRO_STATUS_SUCCESS; + } + dx = _cairo_fixed_to_double (p2->x - p1->x); dy = _cairo_fixed_to_double (p2->y - p1->y); From 20fca01a2cc539df017e442be0cc6ad35353571f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:10:59 -0400 Subject: [PATCH 123/155] Move calculation of slope outside of _cairo_stroker_add_sub_edge. This makes the slope calculation more accurate for dashed lines by computing it once for the entire line instead for each individual dash segment. It also adjusts stroker_line_to() to match the new convention for stroker_add_sub_edge(). --- src/cairo-path-stroke.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index ff09f308b..4fe7e311b 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -548,11 +548,11 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stro static cairo_status_t _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2, - cairo_stroke_face_t *start, cairo_stroke_face_t *end) + cairo_slope_t *slope, cairo_stroke_face_t *start, + cairo_stroke_face_t *end) { cairo_status_t status; cairo_polygon_t polygon; - cairo_slope_t slope; if (p1->x == p2->x && p1->y == p2->y) { /* XXX: Need to rethink how this case should be handled, (both @@ -561,13 +561,12 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_ return CAIRO_STATUS_SUCCESS; } - _cairo_slope_init (&slope, p1, p2); - _compute_face (p1, &slope, stroker, start); + _compute_face (p1, slope, stroker, start); /* XXX: This could be optimized slightly by not calling _compute_face again but rather translating the relevant fields from start. */ - _compute_face (p2, &slope, stroker, end); + _compute_face (p2, slope, stroker, end); /* XXX: I should really check the return value of the move_to/line_to functions here to catch out of memory @@ -633,6 +632,7 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point) cairo_stroke_face_t start, end; cairo_point_t *p1 = &stroker->current_point; cairo_point_t *p2 = point; + cairo_slope_t slope; if (!stroker->has_current_point) return _cairo_stroker_move_to (stroker, point); @@ -644,8 +644,10 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point) as possible. */ return CAIRO_STATUS_SUCCESS; } + + _cairo_slope_init (&slope, p1, p2); - status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &start, &end); + status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &slope, &start, &end); if (status) return status; @@ -683,6 +685,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) cairo_stroke_face_t sub_start, sub_end; cairo_point_t *p1 = &stroker->current_point; cairo_point_t *p2 = point; + cairo_slope_t slope; if (!stroker->has_current_point) return _cairo_stroker_move_to (stroker, point); @@ -695,6 +698,8 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) return CAIRO_STATUS_SUCCESS; } + _cairo_slope_init (&slope, p1, p2); + dx = _cairo_fixed_to_double (p2->x - p1->x); dy = _cairo_fixed_to_double (p2->y - p1->y); @@ -719,7 +724,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) * XXX simplify this case analysis */ if (stroker->dash_on) { - status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &sub_start, &sub_end); + status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end); if (status) return status; if (!first) { From 5eaf71e77bd975f5865cc059b4aa4d57c096688e Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:11:11 -0400 Subject: [PATCH 124/155] Move the test for zero length sub edges below the computation of faces. Face computation still works if a line has zero length, all that is needed is a slope and a point. This patch fixes bug #5561 because the faces are initialized even if the segment has zero length as expected by _cairo_stroker_line_to_dashed. --- src/cairo-path-stroke.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 4fe7e311b..870dc5042 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -554,13 +554,6 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_ cairo_status_t status; cairo_polygon_t polygon; - if (p1->x == p2->x && p1->y == p2->y) { - /* XXX: Need to rethink how this case should be handled, (both - here and in _compute_face). The key behavior is that - degenerate paths should draw as much as possible. */ - return CAIRO_STATUS_SUCCESS; - } - _compute_face (p1, slope, stroker, start); /* XXX: This could be optimized slightly by not calling @@ -568,6 +561,13 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_ fields from start. */ _compute_face (p2, slope, stroker, end); + if (p1->x == p2->x && p1->y == p2->y) { + /* XXX: Need to rethink how this case should be handled, (both + here and in _compute_face). The key behavior is that + degenerate paths should draw as much as possible. */ + 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 From 2078557c5c9e10cf8ae16fb3fa8a225f908ab528 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 9 Apr 2006 23:11:27 -0400 Subject: [PATCH 125/155] Fix skipping zero length dash segments in dash_start. The extra check makes sure zero length segments are not skipped when computing the dash start state. This is needed so that we get proper line capping if, for example, the first dash segment has zero length and we have a dash offset of zero. --- src/cairo-path-stroke.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 870dc5042..d6044a39a 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -116,7 +116,11 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker) int i = 0; offset = stroker->style->dash_offset; - while (offset >= stroker->style->dash[i]) { + + /* We stop searching for a starting point as soon as the + offset reaches zero. Otherwise when an initial dash + segment shrinks to zero it will be skipped over. */ + while (offset > 0.0 && offset >= stroker->style->dash[i]) { offset -= stroker->style->dash[i]; on = 1-on; if (++i == stroker->style->num_dashes) From 11b4d24671a0527a45971e9fdf245ac28facc822 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 13 Apr 2006 12:56:58 -0700 Subject: [PATCH 126/155] Move cairo_pdf_surface_backend to file end so it's easier to find. --- src/cairo-pdf-surface.c | 66 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 03d161c95..7ab8856fe 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1671,39 +1671,6 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface, cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); } -static const cairo_surface_backend_t cairo_pdf_surface_backend = { - CAIRO_SURFACE_TYPE_PDF, - _cairo_pdf_surface_create_similar, - _cairo_pdf_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - _cairo_pdf_surface_composite, - _cairo_pdf_surface_fill_rectangles, - _cairo_pdf_surface_composite_trapezoids, - _cairo_pdf_surface_copy_page, - _cairo_pdf_surface_show_page, - NULL, /* set_clip_region */ - _cairo_pdf_surface_intersect_clip_path, - _cairo_pdf_surface_get_extents, - _cairo_pdf_surface_old_show_glyphs, - _cairo_pdf_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - /* Here are the drawing functions */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - _cairo_pdf_surface_fill, - NULL /* show_glyphs */ -}; - static cairo_pdf_document_t * _cairo_pdf_document_create (cairo_output_stream_t *output_stream, double width, @@ -2135,3 +2102,36 @@ _cairo_pdf_set_paginated_mode (cairo_surface_t *target, surface->paginated_mode = paginated_mode; } + +static const cairo_surface_backend_t cairo_pdf_surface_backend = { + CAIRO_SURFACE_TYPE_PDF, + _cairo_pdf_surface_create_similar, + _cairo_pdf_surface_finish, + NULL, /* acquire_source_image */ + NULL, /* release_source_image */ + NULL, /* acquire_dest_image */ + NULL, /* release_dest_image */ + NULL, /* clone_similar */ + _cairo_pdf_surface_composite, + _cairo_pdf_surface_fill_rectangles, + _cairo_pdf_surface_composite_trapezoids, + _cairo_pdf_surface_copy_page, + _cairo_pdf_surface_show_page, + NULL, /* set_clip_region */ + _cairo_pdf_surface_intersect_clip_path, + _cairo_pdf_surface_get_extents, + _cairo_pdf_surface_old_show_glyphs, + _cairo_pdf_surface_get_font_options, + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + + /* Here are the drawing functions */ + + NULL, /* paint */ + NULL, /* mask */ + NULL, /* stroke */ + _cairo_pdf_surface_fill, + NULL /* show_glyphs */ +}; From 41dc06d7111d246d4b5802c700a83e4be9091449 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 10:08:31 -0700 Subject: [PATCH 127/155] Add new PS-specific image for dash-zero-length test. This reference image demonstrates the bug that occurs when we emit zero-length dash segments into a PostScript file with butt caps. --- test/dash-zero-length-ps-argb32-ref.png | Bin 222 -> 214 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/dash-zero-length-ps-argb32-ref.png b/test/dash-zero-length-ps-argb32-ref.png index 0f66648474d95b794abae4f63409c57c9774e92e..5c7fab579cc18400819fd9d8777575793de2a6ef 100644 GIT binary patch delta 166 zcmV;X09pUu0oDPKBo78+OGiWi{{a60|De66laV19e+P6)O+^RR1P&1fAKO~zRR910 zV@X6oR5;7+RLc&)APfT2|Nmun@L=LAiu15!JrZdZp_Bxx0szQuo|NEL{mO`vkMq&-2ozKIR4WGg`&{wtXu9zh!bd`JMwlQCDSAOLIoMj>} UvAw(O3;+NC07*qoM6N<$f_Y0v7XSbN delta 194 zcmV;z06qWK0p0(O`VPc6wq;NtinKNVlm&>A?D$2b^UhFF=r0 Date: Fri, 14 Apr 2006 10:38:11 -0700 Subject: [PATCH 128/155] Flesh test-paginated-surface out into a complete surface. This adds an aactual test_paginated_surface_backend rather than just having this test surface create a paginated surface around an image surface. This is a more realistic test of what a paginated surface is and should be more useful as an example of how to use the paginated surface, (and in particular the analysis portions). --- src/cairo-image-surface.c | 2 +- src/cairoint.h | 13 +++ src/test-paginated-surface.c | 219 ++++++++++++++++++++++++++++++++--- test/cairo-test.c | 4 +- 4 files changed, 222 insertions(+), 16 deletions(-) diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 06219464c..e095aa04d 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -861,7 +861,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, return status; } -static cairo_int_status_t +cairo_int_status_t _cairo_image_surface_set_clip_region (void *abstract_surface, pixman_region16_t *region) { diff --git a/src/cairoint.h b/src/cairoint.h index 13880cb85..51829c9a7 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1862,6 +1862,19 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data, cairo_private void _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface); +/* XXX: It's a nasty kludge that this appears here. Backend functions + * like this should really be static. But we're doing this to work + * around some general defects in the backend clipping interfaces, + * (see some notes in test-paginated-surface.c). + * + * I want to fix the real defects, but it's "hard" as they touch many + * backends, so doing that will require synchronizing several backend + * maintainers. + */ +cairo_private cairo_int_status_t +_cairo_image_surface_set_clip_region (void *abstract_surface, + pixman_region16_t *region); + cairo_private cairo_bool_t _cairo_surface_is_image (const cairo_surface_t *surface); diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c index d07ac37e7..e42f6a732 100644 --- a/src/test-paginated-surface.c +++ b/src/test-paginated-surface.c @@ -51,20 +51,21 @@ #include "cairo-paginated-surface-private.h" +typedef struct _test_paginated_surface { + cairo_surface_t base; + cairo_surface_t *target; + cairo_paginated_mode_t paginated_mode; +} test_paginated_surface_t; + +static const cairo_surface_backend_t test_paginated_surface_backend; + static void -_test_paginated_surface_set_paginated_mode (cairo_surface_t *target, +_test_paginated_surface_set_paginated_mode (cairo_surface_t *abstract_surface, cairo_paginated_mode_t mode) { - /* XXX: We don't do anything to save the paginated mode here. This - * means that all the rendering will hit the image surface - * twice. This will work (but less efficiently) for all tests that - * explicitly initialize all pixels. Tests that expect the - * background to initially be transparent and leave it that way in - * spots will likely fail. - * - * If we see this as worth fixing, it will just require shoving - * some set_paginated_mode support into cairo_image_surface_t. - */ + test_paginated_surface_t *surface = (test_paginated_surface_t *) abstract_surface; + + surface->paginated_mode = mode; } cairo_surface_t * @@ -74,12 +75,204 @@ _test_paginated_surface_create_for_data (unsigned char *data, int height, int stride) { + cairo_status_t status; cairo_surface_t *target; + test_paginated_surface_t *surface; - target = _cairo_image_surface_create_for_data_with_content (data, content, + target = _cairo_image_surface_create_for_data_with_content (data, content, width, height, stride); + status = cairo_surface_status (target); + if (status) { + _cairo_error (status); + return (cairo_surface_t *) &_cairo_surface_nil; + } - return _cairo_paginated_surface_create (target, content, width, height, + surface = malloc (sizeof (test_paginated_surface_t)); + if (surface == NULL) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + _cairo_surface_init (&surface->base, &test_paginated_surface_backend); + + surface->target = target; + + return _cairo_paginated_surface_create (&surface->base, content, width, height, _test_paginated_surface_set_paginated_mode); } + +static cairo_int_status_t +_test_paginated_surface_set_clip_region (void *abstract_surface, + pixman_region16_t *region) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + /* XXX: The whole surface backend clipping interface is a giant + * disaster right now. In particular, its uncleanness shows up + * when trying to implement one surface that wraps another one (as + * we are doing here). + * + * Here are two of the problems that show up: + * + * 1. The most critical piece of information in all this stuff, + * the "clip" isn't getting passed to the backend + * functions. Instead the generic surface layer is caching that as + * surface->clip. This is a problem for surfaces like this one + * that do wrapping. Our base surface will have the clip set, but + * our target's surface will not. + * + * 2. We're here in our backend's set_clip_region function, and we + * want to call into our target surface's set_clip_region. + * Generally, we would do this by calling an equivalent + * _cairo_surface function, but _cairo_surface_set_clip_region + * does not have the same signature/semantics, (it has the + * clip_serial stuff as well). + * + * We kludge around each of these by manually copying the clip + * object from our base surface into the target's base surface + * (yuck!) and by reaching directly into the image surface's + * set_clip_region instead of calling into the generic + * _cairo_surface_set_clip_region (double yuck!). + */ + + surface->target->clip = surface->base.clip; + + return _cairo_image_surface_set_clip_region (surface->target, region); +} + +static cairo_int_status_t +_test_paginated_surface_get_extents (void *abstract_surface, + cairo_rectangle_t *rectangle) +{ + test_paginated_surface_t *surface = abstract_surface; + + return _cairo_surface_get_extents (surface->target, rectangle); +} + +static cairo_int_status_t +_test_paginated_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + return _cairo_surface_paint (surface->target, op, source); +} + +static cairo_int_status_t +_test_paginated_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + return _cairo_surface_mask (surface->target, op, source, mask); +} + +static cairo_int_status_t +_test_paginated_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + return _cairo_surface_stroke (surface->target, op, source, + path, style, + ctm, ctm_inverse, + tolerance, antialias); +} + +static cairo_int_status_t +_test_paginated_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + return _cairo_surface_fill (surface->target, op, source, + path, fill_rule, + tolerance, antialias); +} + +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, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + test_paginated_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_STATUS_SUCCESS; + + return _cairo_surface_show_glyphs (surface->target, op, source, + glyphs, num_glyphs, scaled_font); +} + +static const cairo_surface_backend_t test_paginated_surface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, + + /* Since we are a paginated user, we get to regard most of the + * surface backend interface as historical cruft and ignore it. */ + + NULL, /* create_similar */ + NULL, /* finish */ + NULL, /* acquire_source_image */ + NULL, /* release_source_image */ + NULL, /* acquire_dest_image */ + NULL, /* release_dest_image */ + NULL, /* clone_similar */ + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ + NULL, /* copy_page */ + NULL, /* show_page */ + _test_paginated_surface_set_clip_region, + NULL, /* intersect_clip_path */ + _test_paginated_surface_get_extents, + NULL, /* old_show_glyphs */ + NULL, /* get_font_options */ + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + + /* Here is the more "modern" section of the surface backend + * interface which is mostly just drawing functions */ + + _test_paginated_surface_paint, + _test_paginated_surface_mask, + _test_paginated_surface_stroke, + _test_paginated_surface_fill, + _test_paginated_surface_show_glyphs, + NULL /* snapshot */ +}; diff --git a/test/cairo-test.c b/test/cairo-test.c index b937fe6db..c200bf768 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1502,12 +1502,12 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, CAIRO_CONTENT_COLOR, create_test_meta_surface, cairo_surface_write_to_png, NULL }, - { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE, + { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, CAIRO_CONTENT_COLOR_ALPHA, create_test_paginated_surface, test_paginated_write_to_png, cleanup_test_paginated }, - { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE, + { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, CAIRO_CONTENT_COLOR, create_test_paginated_surface, test_paginated_write_to_png, From 5461f25df9888aa5fd79e1e371cd1af2cf8964ab Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 11:01:39 -0700 Subject: [PATCH 129/155] Fix _composite_trap_region to restore the original clip when done. --- src/cairo-surface-fallback.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 9b6cfd616..a5c723f15 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -451,6 +451,10 @@ _composite_trap_region (cairo_clip_t *clip, extents->x, extents->y, extents->width, extents->height); + /* Restore the original clip if we modified it temporarily. */ + if (num_rects >1) + _cairo_surface_set_clip (dst, clip); + if (clip_surface) _cairo_pattern_fini (&mask.base); From 8f3c60096d88b3c0368970273828e7a011c5e9dd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 11:33:48 -0700 Subject: [PATCH 130/155] Add a new cairo_paginated_surface_backend_t rather than just a single function pointer. --- src/cairo-paginated-surface-private.h | 17 +++++++++------- src/cairo-paginated-surface.c | 29 ++++++++++++++------------- src/cairo-pdf-surface.c | 17 ++++++++-------- src/cairo-ps-surface.c | 27 +++++++++++++------------ src/test-paginated-surface.c | 25 ++++++++++++++--------- 5 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index cb3259617..42cb9eff0 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -43,15 +43,18 @@ typedef enum { CAIRO_PAGINATED_MODE_RENDER /* render page contents */ } cairo_paginated_mode_t; -typedef void (*cairo_set_paginated_mode_func_t) (cairo_surface_t *target, - cairo_paginated_mode_t mode); +typedef struct _cairo_paginated_surface_backend { + void + (*set_paginated_mode) (void *surface, + cairo_paginated_mode_t mode); +} cairo_paginated_surface_backend_t; cairo_private cairo_surface_t * -_cairo_paginated_surface_create (cairo_surface_t *target, - cairo_content_t content, - int width, - int height, - cairo_set_paginated_mode_func_t set_paginated_mode); +_cairo_paginated_surface_create (cairo_surface_t *target, + cairo_content_t content, + int width, + int height, + const cairo_paginated_surface_backend_t *backend); cairo_private cairo_surface_t * _cairo_paginated_surface_get_target (cairo_surface_t *surface); diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 001edf385..26be21929 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -74,6 +74,9 @@ typedef struct _cairo_paginated_surface { cairo_surface_t base; + /* The target surface to hold the final result. */ + cairo_surface_t *target; + cairo_content_t content; /* XXX: These shouldn't actually exist. We inherit this ugliness @@ -84,11 +87,8 @@ typedef struct _cairo_paginated_surface { int width; int height; - /* The target surface to hold the final result. */ - cairo_surface_t *target; - - /* Paginated-surface specific function for the target */ - cairo_set_paginated_mode_func_t set_paginated_mode; + /* Paginated-surface specific functions for the target */ + const cairo_paginated_surface_backend_t *backend; /* A cairo_meta_surface to record all operations. To be replayed * against target, and also against image surface as necessary for @@ -121,11 +121,11 @@ _cairo_paginated_surface_create_similar (void *abstract_surface, #endif cairo_surface_t * -_cairo_paginated_surface_create (cairo_surface_t *target, - cairo_content_t content, - int width, - int height, - cairo_set_paginated_mode_func_t set_paginated_mode) +_cairo_paginated_surface_create (cairo_surface_t *target, + cairo_content_t content, + int width, + int height, + const cairo_paginated_surface_backend_t *backend) { cairo_paginated_surface_t *surface; @@ -139,12 +139,13 @@ _cairo_paginated_surface_create (cairo_surface_t *target, * evidence of the paginated wrapper out to the user. */ surface->base.type = cairo_surface_get_type (target); + surface->target = target; + surface->content = content; surface->width = width; surface->height = height; - surface->target = target; - surface->set_paginated_mode = set_paginated_mode; + surface->backend = backend; surface->meta = _cairo_meta_surface_create (content, width, height); if (cairo_surface_status (surface->meta)) @@ -231,9 +232,9 @@ _paint_page (cairo_paginated_surface_t *surface) analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); - surface->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); + surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); _cairo_meta_surface_replay (surface->meta, analysis); - surface->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); + surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); if (analysis->status) { status = analysis->status; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 7ab8856fe..adf29d0c4 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -187,11 +187,8 @@ _cairo_pdf_surface_add_stream (cairo_pdf_surface_t *surface, static void _cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface); -static void -_cairo_pdf_set_paginated_mode (cairo_surface_t *target, - cairo_paginated_mode_t mode); - static const cairo_surface_backend_t cairo_pdf_surface_backend; +static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend; static unsigned int _cairo_pdf_document_new_object (cairo_pdf_document_t *document) @@ -313,7 +310,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (target, CAIRO_CONTENT_COLOR_ALPHA, width, height, - _cairo_pdf_set_paginated_mode); + &cairo_pdf_surface_paginated_backend); } /** @@ -2095,10 +2092,10 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document, } static void -_cairo_pdf_set_paginated_mode (cairo_surface_t *target, - cairo_paginated_mode_t paginated_mode) +_cairo_pdf_surface_set_paginated_mode (void *abstract_surface, + cairo_paginated_mode_t paginated_mode) { - cairo_pdf_surface_t *surface = (cairo_pdf_surface_t *) target; + cairo_pdf_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode; } @@ -2135,3 +2132,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { _cairo_pdf_surface_fill, NULL /* show_glyphs */ }; + +static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = { + _cairo_pdf_surface_set_paginated_mode +}; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index b5062d4b5..f398176bd 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -55,10 +55,7 @@ */ static const cairo_surface_backend_t cairo_ps_surface_backend; - -static void -_cairo_ps_set_paginated_mode (cairo_surface_t *target, - cairo_paginated_mode_t mode); +static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend; /* * Type1 and Type3 PS fonts can hold only 256 glyphs. @@ -583,7 +580,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height, - _cairo_ps_set_paginated_mode); + &cairo_ps_surface_paginated_backend); } /** @@ -1824,6 +1821,15 @@ fallback: return CAIRO_STATUS_SUCCESS; } +static void +_cairo_ps_surface_set_paginated_mode (void *abstract_surface, + cairo_paginated_mode_t paginated_mode) +{ + cairo_ps_surface_t *surface = abstract_surface; + + surface->paginated_mode = paginated_mode; +} + static const cairo_surface_backend_t cairo_ps_surface_backend = { CAIRO_SURFACE_TYPE_PS, NULL, /* create_similar */ @@ -1858,11 +1864,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { NULL, /* snapshot */ }; -static void -_cairo_ps_set_paginated_mode (cairo_surface_t *target, - cairo_paginated_mode_t paginated_mode) -{ - cairo_ps_surface_t *surface = (cairo_ps_surface_t *) target; - - surface->paginated_mode = paginated_mode; -} +static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = { + _cairo_ps_surface_set_paginated_mode +}; diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c index e42f6a732..6190432bd 100644 --- a/src/test-paginated-surface.c +++ b/src/test-paginated-surface.c @@ -58,15 +58,7 @@ typedef struct _test_paginated_surface { } test_paginated_surface_t; static const cairo_surface_backend_t test_paginated_surface_backend; - -static void -_test_paginated_surface_set_paginated_mode (cairo_surface_t *abstract_surface, - cairo_paginated_mode_t mode) -{ - test_paginated_surface_t *surface = (test_paginated_surface_t *) abstract_surface; - - surface->paginated_mode = mode; -} +static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend; cairo_surface_t * _test_paginated_surface_create_for_data (unsigned char *data, @@ -99,7 +91,7 @@ _test_paginated_surface_create_for_data (unsigned char *data, surface->target = target; return _cairo_paginated_surface_create (&surface->base, content, width, height, - _test_paginated_surface_set_paginated_mode); + &test_paginated_surface_paginated_backend); } static cairo_int_status_t @@ -238,6 +230,15 @@ _test_paginated_surface_show_glyphs (void *abstract_surface, glyphs, num_glyphs, scaled_font); } +static void +_test_paginated_surface_set_paginated_mode (void *abstract_surface, + cairo_paginated_mode_t mode) +{ + test_paginated_surface_t *surface = abstract_surface; + + surface->paginated_mode = mode; +} + static const cairo_surface_backend_t test_paginated_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, @@ -276,3 +277,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend = { _test_paginated_surface_show_glyphs, NULL /* snapshot */ }; + +static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = { + _test_paginated_surface_set_paginated_mode +}; From f919ba858f405aa5c1cc64e7c25c3de5ffbce88f Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Fri, 14 Apr 2006 22:06:28 +0200 Subject: [PATCH 131/155] SVG: Emulate CLEAR and SOURCE operators on paint call when no clipping region is defined. --- src/cairo-svg-surface.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index d5c45eb5d..5c1eeb68f 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -1007,6 +1007,17 @@ _cairo_svg_surface_paint (void *abstract_surface, cairo_pattern_t *source) { cairo_svg_surface_t *surface = abstract_surface; + + /* Emulation of clear and source operators, when no clipping region + * is defined. We just delete existing content of surface root node, + * and exit early if operator is clear. */ + if (surface->clip_level == 0 && + (op == CAIRO_OPERATOR_CLEAR || + op == CAIRO_OPERATOR_SOURCE)) { + xmlFreeNode (surface->xml_root_node->children); + if (op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + } emit_paint (surface->xml_node, surface, op, source); From e952e0aff89412e67fb72ba2cf3a30c3ddd332b4 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Fri, 14 Apr 2006 22:53:58 +0200 Subject: [PATCH 132/155] SVG: Add documentation for public API. Fix test filenames and add testing of CAIRO_CONTENT_COLOR --- src/cairo-svg-surface.c | 47 +++++++++++++++++++++++++++++++++++++++++ test/cairo-test.c | 6 +++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 5c1eeb68f..accbe0043 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -137,6 +137,24 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, return surface; } +/** + * cairo_svg_surface_create_for_stream: + * @write: a #cairo_write_func_t to accept the output data + * @closure: the closure argument for @write + * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) + * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) + * + * Creates a SVG surface of the specified size in points to be written + * incrementally to the stream represented by @write and @closure. + * + * Return value: a pointer to the newly created surface. The caller + * owns the surface and should call cairo_surface_destroy when done + * with it. + * + * This function always returns a valid pointer, but it will return a + * pointer to a "nil" surface if an error such as out of memory + * occurs. You can use cairo_surface_status() to check for this. + */ cairo_surface_t * cairo_svg_surface_create_for_stream (cairo_write_func_t write, void *closure, @@ -156,6 +174,23 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write, return _cairo_svg_surface_create_for_stream_internal (stream, width, height); } +/** + * cairo_svg_surface_create: + * @filename: a filename for the SVG output (must be writable) + * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) + * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) + * + * Creates a SVG surface of the specified size in points to be written + * to @filename. + * + * Return value: a pointer to the newly created surface. The caller + * owns the surface and should call cairo_surface_destroy when done + * with it. + * + * This function always returns a valid pointer, but it will return a + * pointer to a "nil" surface if an error such as out of memory + * occurs. You can use cairo_surface_status() to check for this. + **/ cairo_surface_t * cairo_svg_surface_create (const char *filename, double width, @@ -174,6 +209,18 @@ cairo_svg_surface_create (const char *filename, return _cairo_svg_surface_create_for_stream_internal (stream, width, height); } +/** + * cairo_svg_surface_set_dpi: + * @surface: a svg cairo_surface_t + * @x_dpi: horizontal dpi + * @y_dpi: vertical dpi + * + * Set the horizontal and vertical resolution for image fallbacks. + * When the svg backend needs to fall back to image overlays, it will + * use this resolution. These DPI values are not used for any other + * purpose, (in particular, they do not have any bearing on the size + * passed to cairo_svg_surface_create() nor on the CTM). + **/ void cairo_svg_surface_set_dpi (cairo_surface_t *surface, double x_dpi, diff --git a/test/cairo-test.c b/test/cairo-test.c index c200bf768..59b55f7ba 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1321,7 +1321,9 @@ create_svg_surface (cairo_test_t *test, ptc->width = width; ptc->height = height; - xasprintf (&ptc->filename, "%s-%s%s", test->name, "svg-argb32-out", ".svg"); + xasprintf (&ptc->filename, "%s-svg-%s-out.svg", + test->name, _cairo_test_content_name (content)); + surface = cairo_svg_surface_create (ptc->filename, width, height); if (cairo_surface_status (surface)) { free (ptc->filename); @@ -1591,6 +1593,8 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf }, #endif #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE + { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR, + create_svg_surface, svg_surface_write_to_png, cleanup_svg }, { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, create_svg_surface, svg_surface_write_to_png, cleanup_svg }, #endif From b9eb4f018e77a3f797116f0915f261d8453b3993 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Fri, 14 Apr 2006 22:55:48 +0200 Subject: [PATCH 133/155] PDF: Fix typo in documentation. --- src/cairo-pdf-surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index adf29d0c4..dfbae3730 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -396,7 +396,7 @@ _cairo_surface_is_pdf (cairo_surface_t *surface) } /** - * cairo__surface_set_dpi: + * cairo_pdf_surface_set_dpi: * @surface: a postscript cairo_surface_t * @x_dpi: horizontal dpi * @y_dpi: vertical dpi From d284c2b5a475ff1672dad10e7bf76763877690a3 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Fri, 14 Apr 2006 23:11:35 +0200 Subject: [PATCH 134/155] SVG: enable SVG backend API documentation in /doc --- doc/public/cairo-docs.xml | 1 + doc/public/cairo-sections.txt | 8 +++++ doc/public/tmpl/cairo-svg.sgml | 54 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 doc/public/tmpl/cairo-svg.sgml diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml index 679eb9202..b78d269f4 100644 --- a/doc/public/cairo-docs.xml +++ b/doc/public/cairo-docs.xml @@ -40,6 +40,7 @@ + +SVG Surfaces + + +Rendering SVG documents + + + + + + + + + + + + + + + + + + + + + +@filename: +@width_in_points: +@height_in_points: +@Returns: + + + + + + + +@write_func: +@closure: +@width_in_points: +@height_in_points: +@Returns: + + + + + + + +@surface: +@x_dpi: +@y_dpi: + + From 687802cca67ce4157725316d769fc28bc75f5dcd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 14:44:16 -0700 Subject: [PATCH 135/155] Obnoxious churn of gtk-doc templates. We really need to get these built files out from under version control, (or else abandon gtk-doc altogether). --- doc/public/tmpl/cairo-svg.sgml | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/public/tmpl/cairo-svg.sgml b/doc/public/tmpl/cairo-svg.sgml index 55dd6250f..31bf69257 100644 --- a/doc/public/tmpl/cairo-svg.sgml +++ b/doc/public/tmpl/cairo-svg.sgml @@ -9,13 +9,11 @@ Rendering SVG documents - - From 8d3a800b82ccd4a39bf04cc1d602eb84d90f81d1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 14:46:59 -0700 Subject: [PATCH 136/155] Add a start_page function to the paginated_surface_backend. This allows for any surface using the paginated_surface backend to easily do stuff at the beginning of each page, (such as writing out any per-page header necessary). This replaces some of the per-page state tracking that the PS surface was doing, (though it still has some left for its optimization of CLEAR on a blank page). --- src/cairo-paginated-surface-private.h | 60 ++++++++++++++++++++- src/cairo-paginated-surface.c | 19 +++++++ src/cairo-pdf-surface.c | 1 + src/cairo-ps-surface.c | 78 ++++++++++++--------------- src/test-paginated-surface.c | 1 + 5 files changed, 112 insertions(+), 47 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index 42cb9eff0..c18cb3c14 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -44,11 +44,67 @@ typedef enum { } cairo_paginated_mode_t; typedef struct _cairo_paginated_surface_backend { + /* Optional. Will be called once for each page. + * + * NOTE: With respect to the order of drawing operations as seen + * by the target, this call will occur before any drawing + * operations for the relevant page. However, with respect to the + * function calls as made by the user, this call will be *after* + * any drawing operations for the page, (that is, it will occur + * during the user's call to cairo_show_page or cairo_copy_page). + */ + cairo_int_status_t + (*start_page) (void *surface); + + /* Required. Will be called twice for each page, once with an + * argument of CAIRO_PAGINATED_MODE_ANALYZE and once with + * CAIRO_PAGINATED_MODE_RENDER. See more details in the + * documentation for _cairo_paginated_surface_create below. + */ void - (*set_paginated_mode) (void *surface, - cairo_paginated_mode_t mode); + (*set_paginated_mode) (void *surface, + cairo_paginated_mode_t mode); } cairo_paginated_surface_backend_t; +/* A cairo_paginated_surface provides a very convenient wrapper that + * is well-suited for doing the analysis common to most surfaces that + * have paginated output, (that is, things directed at printers, or + * for saving content in files such as PostScript or PDF files). + * + * What the paginated surface does is first save all drawing + * operations for a page into a meta-surface. Then when the user calls + * cairo_show_page, the paginated surface performs the following + * sequence of operations (using the backend functions passed to + * cairo_paginated_surface_create): + * + * 1. Calls start_page (if non NULL). At this point, it is appropriate + * for the target to emit any page-specific header information into + * its output. + * + * 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE + * + * 3. Replays the meta-surface to the target surface, (with an + * analysis surface inserted between which watches the return value + * from each operation). This analysis stage is used to decide which + * operations will require fallbacks. + * + * 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER + * + * 5. Replays a subset of the meta-surface operations to the target surface + * + * 6. Replays the remaining operations to an image surface, sets an + * appropriate clip on the target, then paints the resulting image + * surface to the target. + * + * So, the target will see drawing operations during two separate + * stages, (ANALYZE and RENDER). During the ANALYZE phase the target + * should not actually perform any rendering, (for example, if + * performing output to a file, no output should be generated during + * this stage). Instead the drawing functions simply need to return + * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate + * whether rendering would be supported. And it should do this as + * quickly as possible. + */ cairo_private cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, cairo_content_t content, diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 26be21929..475db3e54 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -266,11 +266,25 @@ _paint_page (cairo_paginated_surface_t *surface) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_start_page (cairo_paginated_surface_t *surface) +{ + if (! surface->backend->start_page) + return CAIRO_STATUS_SUCCESS; + + return (surface->backend->start_page) (surface->target); +} + static cairo_int_status_t _cairo_paginated_surface_copy_page (void *abstract_surface) { + cairo_status_t status; cairo_paginated_surface_t *surface = abstract_surface; + status = _start_page (surface); + if (status) + return status; + _paint_page (surface); /* XXX: It might make sense to add some suport here for calling @@ -289,8 +303,13 @@ _cairo_paginated_surface_copy_page (void *abstract_surface) static cairo_int_status_t _cairo_paginated_surface_show_page (void *abstract_surface) { + cairo_status_t status; cairo_paginated_surface_t *surface = abstract_surface; + status = _start_page (surface); + if (status) + return status; + _paint_page (surface); _cairo_surface_show_page (surface->target); diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index dfbae3730..033ba041f 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -2134,5 +2134,6 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { }; static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = { + NULL, /* start_page */ _cairo_pdf_surface_set_paginated_mode }; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f398176bd..84efa6e15 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -96,7 +96,7 @@ typedef struct cairo_ps_surface { double x_dpi; double y_dpi; - cairo_bool_t need_start_page; + cairo_bool_t page_is_blank; int num_pages; cairo_paginated_mode_t paginated_mode; @@ -574,7 +574,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->y_dpi = PS_SURFACE_DPI_DEFAULT; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - surface->need_start_page = TRUE; + surface->page_is_blank = TRUE; surface->num_pages = 0; return _cairo_paginated_surface_create (&surface->base, @@ -842,9 +842,11 @@ _cairo_ps_surface_finish (void *abstract_surface) return status; } -static void -_cairo_ps_surface_start_page (cairo_ps_surface_t *surface) +static cairo_int_status_t +_cairo_ps_surface_start_page (void *abstract_surface) { + cairo_ps_surface_t *surface = abstract_surface; + /* Increment before print so page numbers start at 1. */ surface->num_pages++; _cairo_output_stream_printf (surface->stream, @@ -858,7 +860,7 @@ _cairo_ps_surface_start_page (cairo_ps_surface_t *surface) 1.0/surface->base.device_x_scale, -1.0/surface->base.device_y_scale); - surface->need_start_page = FALSE; + return _cairo_output_stream_get_status (surface->stream); } static void @@ -866,8 +868,6 @@ _cairo_ps_surface_end_page (cairo_ps_surface_t *surface) { _cairo_output_stream_printf (surface->stream, "grestore\n"); - - surface->need_start_page = TRUE; } static cairo_int_status_t @@ -891,8 +891,6 @@ _cairo_ps_surface_show_page (void *abstract_surface) _cairo_output_stream_printf (surface->stream, "showpage\n"); - surface->need_start_page = TRUE; - return CAIRO_STATUS_SUCCESS; } @@ -1062,11 +1060,6 @@ operation_supported (cairo_ps_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern) { - /* As a special-case, (see all drawing operations below), we - * optimize away any erasing where nothing has been drawn yet. */ - if (surface->need_start_page && op == CAIRO_OPERATOR_CLEAR) - return TRUE; - if (! pattern_supported (pattern)) return FALSE; @@ -1460,9 +1453,6 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; - if (surface->need_start_page) - _cairo_ps_surface_start_page (surface); - _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_intersect_clip_path\n"); @@ -1528,6 +1518,12 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_ps_surface_path_info_t info; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1541,13 +1537,6 @@ _cairo_ps_surface_paint (void *abstract_surface, assert (pattern_operation_supported (op, source)); */ - if (surface->need_start_page) { - /* Optimize away erasing of nothing. */ - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - _cairo_ps_surface_start_page (surface); - } - _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_paint\n"); @@ -1613,18 +1602,17 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_int_status_t status; cairo_ps_surface_path_info_t info; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); - if (surface->need_start_page) { - /* Optimize away erasing of nothing. */ - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - _cairo_ps_surface_start_page (surface); - } - _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_stroke\n"); @@ -1693,18 +1681,17 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); - if (surface->need_start_page) { - /* Optimize away erasing of nothing. */ - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - _cairo_ps_surface_start_page (surface); - } - _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_fill\n"); @@ -1763,18 +1750,17 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_ps_font_t *ps_font; cairo_ps_glyph_t *ps_glyph; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); - if (surface->need_start_page) { - /* Optimize away erasing of nothing. */ - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - _cairo_ps_surface_start_page (surface); - } - _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_show_glyphs\n"); status = _cairo_ps_font_find (surface, scaled_font, &ps_font); @@ -1828,6 +1814,7 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface, cairo_ps_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode; + surface->page_is_blank = TRUE; } static const cairo_surface_backend_t cairo_ps_surface_backend = { @@ -1865,5 +1852,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = { }; static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = { + _cairo_ps_surface_start_page, _cairo_ps_surface_set_paginated_mode }; diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c index 6190432bd..e4eb58a2d 100644 --- a/src/test-paginated-surface.c +++ b/src/test-paginated-surface.c @@ -279,5 +279,6 @@ static const cairo_surface_backend_t test_paginated_surface_backend = { }; static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = { + NULL, /* start_page */ _test_paginated_surface_set_paginated_mode }; From 2726f684547de7d381e56dce13bb7c025cd75b80 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 14:53:13 -0700 Subject: [PATCH 137/155] Update documentation of cairo_paginated_surface --- src/cairo-paginated-surface-private.h | 12 +++++++++++ src/cairo-paginated-surface.c | 29 ++------------------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index c18cb3c14..247ed7262 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -71,6 +71,18 @@ typedef struct _cairo_paginated_surface_backend { * have paginated output, (that is, things directed at printers, or * for saving content in files such as PostScript or PDF files). * + * To use the paginated surface, you'll first need to create your + * 'real' surface using _cairo_surface_init and the standard + * cairo_surface_backend_t. Then you also call + * _cairo_paginated_surface_create which takes its own, much simpler, + * cairo_paginated_surface_backend. You are free to return the result + * of _cairo_paginated_surface_create from your public + * cairo__surface_create. The paginated backend will be careful + * to not let the user see that they really got a "wrapped" + * surface. See test-paginated-surface.c for a fairly minimal example + * of a paginated-using surface. That should be a reasonable example + * to follow. + * * What the paginated surface does is first save all drawing * operations for a page into a meta-surface. Then when the user calls * cairo_show_page, the paginated surface performs the following diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 475db3e54..01b6ed83f 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -36,33 +36,8 @@ /* The paginated surface layer exists to provide as much code sharing * as possible for the various paginated surface backends in cairo - * (PostScript, PDF, etc.). - * - * The concept is that a surface which uses a paginated surface merely - * needs to implement backend operations which it can accurately - * provide, (and return CAIRO_INT_STATUS_UNSUPPORTED or leave backend - * function pointers NULL otherwise). The paginated surface is the - * responsible for collecting operations that aren't supported, - * replaying them against the image surface, and then supplying the - * resulting images to the target surface. - * - * When created, a paginated surface accepts the target surface to - * which the final drawing will eventually be performed. The paginated - * surface then uses cairo_meta_surface_t to record all drawing - * operations up until each show_page operation. - * - * At the time of show_page, the paginated surface replays the meta - * surface against the target surface and maintains regions of the - * result that will come from the nativ surface and regions that will - * need to come from image fallbacks. It then replays the necessary - * portions against image surface and provides those results to the - * target surface through existing interfaces. - * - * This way the target surface is never even aware of any distinction - * between native drawing operations vs. results that are supplied by - * image fallbacks. Instead the surface need only implement as much of - * the surface backend interface as it can do correctly, and let the - * paginated surface take care of all the messy details. + * (PostScript, PDF, etc.). See cairo-paginated-surface-private.h for + * more details on how it works and how to use it. */ #include "cairoint.h" From b8fb8dc375d2828a962bac2e1f50f44d8ec8cbee Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 15:23:30 -0700 Subject: [PATCH 138/155] Add stub implementations of drawing operations for the PDF backend. These new stubs explicitly return UNSUPPORTED unconditionally. This is no different than the implicit UNSUPPORTED which the analysis surface was inferring from NULL for 4 of the functions before. However, _cairo_pdf_surface_fill was actually trying to draw things, but without correctly characterizing it during the analysis stage. This was just an oversight, as the PDF surface was always triggereing full page fall backs anway due to the initial unsupported paint with CLEAR. Now, we explicitly return UNSUPPORTED for all drawing operations so we get image fallbacks by design and not by accident. --- src/cairo-pdf-surface.c | 160 ++++++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 57 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 033ba041f..291d3d106 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1348,59 +1348,6 @@ _cairo_pdf_path_close_path (void *closure) return CAIRO_STATUS_SUCCESS; } -static cairo_int_status_t -_cairo_pdf_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_document_t *document = surface->document; - const char *pdf_operator; - cairo_status_t status; - pdf_path_info_t info; - - status = emit_pattern (surface, pattern); - if (status) - return status; - - /* After the above switch the current stream should belong to this - * surface, so no need to _cairo_pdf_surface_ensure_stream() */ - assert (document->current_stream != NULL && - document->current_stream == surface->current_stream); - - info.output_stream = document->output_stream; - info.has_current_point = FALSE; - - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - pdf_operator = "f"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - pdf_operator = "f*"; - break; - default: - ASSERT_NOT_REACHED; - } - - _cairo_output_stream_printf (document->output_stream, - "%s\r\n", - pdf_operator); - - return status; -} - static cairo_int_status_t _cairo_pdf_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, @@ -2091,6 +2038,104 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document, return CAIRO_STATUS_SUCCESS; } +static cairo_int_status_t +_cairo_pdf_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +static cairo_int_status_t +_cairo_pdf_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +static cairo_int_status_t +_cairo_pdf_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +static cairo_int_status_t +_cairo_pdf_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *pattern, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_pdf_surface_t *surface = abstract_surface; + cairo_pdf_document_t *document = surface->document; + const char *pdf_operator; + cairo_status_t status; + pdf_path_info_t info; + + /* XXX: Temporarily disabling all "native" PDF output. */ + return CAIRO_INT_STATUS_UNSUPPORTED; + + status = emit_pattern (surface, pattern); + if (status) + return status; + + /* After the above switch the current stream should belong to this + * surface, so no need to _cairo_pdf_surface_ensure_stream() */ + assert (document->current_stream != NULL && + document->current_stream == surface->current_stream); + + info.output_stream = document->output_stream; + info.has_current_point = FALSE; + + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_pdf_path_move_to, + _cairo_pdf_path_line_to, + _cairo_pdf_path_curve_to, + _cairo_pdf_path_close_path, + &info); + + switch (fill_rule) { + case CAIRO_FILL_RULE_WINDING: + pdf_operator = "f"; + break; + case CAIRO_FILL_RULE_EVEN_ODD: + pdf_operator = "f*"; + break; + default: + ASSERT_NOT_REACHED; + } + + _cairo_output_stream_printf (document->output_stream, + "%s\r\n", + pdf_operator); + + return status; +} + +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, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + static void _cairo_pdf_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode) @@ -2126,11 +2171,12 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { /* Here are the drawing functions */ - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ + _cairo_pdf_surface_paint, + _cairo_pdf_surface_mask, + _cairo_pdf_surface_stroke, _cairo_pdf_surface_fill, - NULL /* show_glyphs */ + _cairo_pdf_surface_show_glyphs, + NULL, /* snapshot */ }; static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = { From e8a0da637fda4a29281cfb4f463169e51c300c42 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 16:18:36 -0700 Subject: [PATCH 139/155] Move optimization of CLEAR on blank page up from PS to paginated surface. --- src/cairo-paginated-surface-private.h | 8 +++++++ src/cairo-paginated-surface.c | 30 +++++++++++++++++++++++++++ src/cairo-ps-surface.c | 27 ------------------------ 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h index 247ed7262..b5e4d5c9b 100644 --- a/src/cairo-paginated-surface-private.h +++ b/src/cairo-paginated-surface-private.h @@ -116,6 +116,14 @@ typedef struct _cairo_paginated_surface_backend { * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate * whether rendering would be supported. And it should do this as * quickly as possible. + * + * NOTE: The paginated surface layer assumes that the target surface + * is "blank" by default at the beginning of each page, without any + * need for an explicit erasea operation, (as opposed to an image + * surface, for example, which might have uninitialized content + * originally). As such, it optimizes away CLEAR operations that + * happen at the beginning of each page---the target surface will not + * even see these operations. */ cairo_private cairo_surface_t * _cairo_paginated_surface_create (cairo_surface_t *target, diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 01b6ed83f..34b42e777 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -70,6 +70,8 @@ typedef struct _cairo_paginated_surface { * fallbacks. */ cairo_surface_t *meta; + cairo_bool_t page_is_blank; + } cairo_paginated_surface_t; const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend; @@ -126,6 +128,8 @@ _cairo_paginated_surface_create (cairo_surface_t *target, if (cairo_surface_status (surface->meta)) goto FAIL_CLEANUP_SURFACE; + surface->page_is_blank = TRUE; + return &surface->base; FAIL_CLEANUP_SURFACE: @@ -296,6 +300,8 @@ _cairo_paginated_surface_show_page (void *abstract_surface) if (cairo_surface_status (surface->meta)) return cairo_surface_status (surface->meta); + surface->page_is_blank = TRUE; + return CAIRO_STATUS_SUCCESS; } @@ -329,6 +335,12 @@ _cairo_paginated_surface_paint (void *abstract_surface, { cairo_paginated_surface_t *surface = abstract_surface; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + return _cairo_surface_paint (surface->meta, op, source); } @@ -356,6 +368,12 @@ _cairo_paginated_surface_stroke (void *abstract_surface, { cairo_paginated_surface_t *surface = abstract_surface; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + return _cairo_surface_stroke (surface->meta, op, source, path, style, ctm, ctm_inverse, @@ -373,6 +391,12 @@ _cairo_paginated_surface_fill (void *abstract_surface, { cairo_paginated_surface_t *surface = abstract_surface; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + return _cairo_surface_fill (surface->meta, op, source, path, fill_rule, tolerance, antialias); @@ -388,6 +412,12 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface, { cairo_paginated_surface_t *surface = abstract_surface; + /* Optimize away erasing of nothing. */ + if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) + return CAIRO_STATUS_SUCCESS; + + surface->page_is_blank = FALSE; + return _cairo_surface_show_glyphs (surface->meta, op, source, glyphs, num_glyphs, scaled_font); diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 84efa6e15..9319f8329 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -96,7 +96,6 @@ typedef struct cairo_ps_surface { double x_dpi; double y_dpi; - cairo_bool_t page_is_blank; int num_pages; cairo_paginated_mode_t paginated_mode; @@ -574,7 +573,6 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->y_dpi = PS_SURFACE_DPI_DEFAULT; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - surface->page_is_blank = TRUE; surface->num_pages = 0; return _cairo_paginated_surface_create (&surface->base, @@ -1518,12 +1516,6 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_output_stream_t *stream = surface->stream; cairo_ps_surface_path_info_t info; - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1602,12 +1594,6 @@ _cairo_ps_surface_stroke (void *abstract_surface, cairo_int_status_t status; cairo_ps_surface_path_info_t info; - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1681,12 +1667,6 @@ _cairo_ps_surface_fill (void *abstract_surface, cairo_ps_surface_path_info_t info; const char *ps_operator; - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1750,12 +1730,6 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_ps_font_t *ps_font; cairo_ps_glyph_t *ps_glyph; - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1814,7 +1788,6 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface, cairo_ps_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode; - surface->page_is_blank = TRUE; } static const cairo_surface_backend_t cairo_ps_surface_backend = { From 0e44e798b5f6fd58cc586e40f926d363cd8fff50 Mon Sep 17 00:00:00 2001 From: Dom Lachowicz Date: Fri, 14 Apr 2006 16:15:29 -0700 Subject: [PATCH 140/155] Change cairo_image_surface_create to zero out surface contents. This closes bug #5816: Image surfaces do not start out blank by default https://bugs.freedesktop.org/show_bug.cgi?id=5816 This also fixes all of the test suite failures introduced by moving the CLEAR on blank page optimization up to the paginated surface from the PS surface. --- pixman/src/icpixels.c | 1 + src/cairo-image-surface.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pixman/src/icpixels.c b/pixman/src/icpixels.c index cdec492e3..2ad34f478 100644 --- a/pixman/src/icpixels.c +++ b/pixman/src/icpixels.c @@ -70,6 +70,7 @@ FbPixelsCreate (int width, int height, int depth) return NULL; buf = (pixman_bits_t *) ((char *)pixels + base + adjust); + memset (buf, 0, height * stride); FbPixelsInit (pixels, buf, width, height, depth, bpp, stride); diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index e095aa04d..cef455b64 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -188,9 +188,10 @@ _create_pixman_format (cairo_format_t format) * @height: height of the surface, in pixels * * Creates an image surface of the specified format and - * dimensions. The initial contents of the surface is undefined; you - * must explicitly initialize the surface contents, using, for - * example, cairo_paint(). + * dimensions. Initially the surface contents are all + * 0. (Specifically, within each pixel, each color or alpha channel + * belonging to format will be 0. The contents of bits within a pixel, + * but not belonging to the given format are undefined). * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy when done From c7fd35fac2bc7c93e85ccbe50b20529ae4d9479d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 16:50:16 -0700 Subject: [PATCH 141/155] Add tests for PAGINATED_MODE_ANALYZE to PDF (no real analysis yet) --- src/cairo-pdf-surface.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 291d3d106..8c867ecb0 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -2043,6 +2043,13 @@ _cairo_pdf_surface_paint (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source) { + cairo_pdf_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + ASSERT_NOT_REACHED; + return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -2052,6 +2059,13 @@ _cairo_pdf_surface_mask (void *abstract_surface, cairo_pattern_t *source, cairo_pattern_t *mask) { + cairo_pdf_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + ASSERT_NOT_REACHED; + return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -2066,13 +2080,20 @@ _cairo_pdf_surface_stroke (void *abstract_surface, double tolerance, cairo_antialias_t antialias) { + cairo_pdf_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + ASSERT_NOT_REACHED; + return CAIRO_INT_STATUS_UNSUPPORTED; } static cairo_int_status_t _cairo_pdf_surface_fill (void *abstract_surface, cairo_operator_t op, - cairo_pattern_t *pattern, + cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, @@ -2084,10 +2105,13 @@ _cairo_pdf_surface_fill (void *abstract_surface, cairo_status_t status; pdf_path_info_t info; - /* XXX: Temporarily disabling all "native" PDF output. */ - return CAIRO_INT_STATUS_UNSUPPORTED; + /* XXX: Temporarily disabling all "native" PDF output---will be + * switching to real analysis shortly. */ + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_INT_STATUS_UNSUPPORTED; + ASSERT_NOT_REACHED; - status = emit_pattern (surface, pattern); + status = emit_pattern (surface, source); if (status) return status; @@ -2133,6 +2157,13 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, int num_glyphs, cairo_scaled_font_t *scaled_font) { + cairo_pdf_surface_t *surface = abstract_surface; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + ASSERT_NOT_REACHED; + return CAIRO_INT_STATUS_UNSUPPORTED; } From a7f4f1b350e158eca394da63eed0e14a97480a5a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 17:03:39 -0700 Subject: [PATCH 142/155] Move analysis of operators from cairo-ps-surface.c to cairo-operator.c --- src/Makefile.am | 1 + src/cairo-operator.c | 119 +++++++++++++++++++++++++++++++++++++++++ src/cairo-ps-surface.c | 73 ++----------------------- src/cairoint.h | 7 +++ 4 files changed, 132 insertions(+), 68 deletions(-) create mode 100644 src/cairo-operator.c diff --git a/src/Makefile.am b/src/Makefile.am index 43ffcd7f8..4ccf3278b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -153,6 +153,7 @@ libcairo_la_SOURCES = \ cairo-image-surface.c \ cairo-lzw.c \ cairo-matrix.c \ + cairo-operator.c \ cairo-path.c \ cairo-path-bounds.c \ cairo-path-data.c \ diff --git a/src/cairo-operator.c b/src/cairo-operator.c new file mode 100644 index 000000000..99c3aaaa0 --- /dev/null +++ b/src/cairo-operator.c @@ -0,0 +1,119 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2006 Keith Packard + * 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 + * 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 + * Keith Packard + */ + +#include "cairoint.h" + +/* The analysis here assumes destination alpha semantics (that is + * CAIRO_CONTENT_COLOR_ALPHA). More things can be considered opaque + * otherwise (CAIRO_CONTENT_COLOR) so we'll probably want to add a + * cairo_content_t parameter to this function + * + * We also need a definition of what "opaque" means. Is it, "does not + * requiring 'knowing' the original contents of destination, nor does + * it set the destination alpha to anything but 1.0" ? + */ +cairo_bool_t +_cairo_operator_always_opaque (cairo_operator_t op) +{ + switch (op) { + case CAIRO_OPERATOR_CLEAR: + return FALSE; + + case CAIRO_OPERATOR_SOURCE: + return FALSE; + + case CAIRO_OPERATOR_OVER: + case CAIRO_OPERATOR_IN: + case CAIRO_OPERATOR_OUT: + case CAIRO_OPERATOR_ATOP: + return FALSE; + + case CAIRO_OPERATOR_DEST: + return TRUE; + + case CAIRO_OPERATOR_DEST_OVER: + case CAIRO_OPERATOR_DEST_IN: + case CAIRO_OPERATOR_DEST_OUT: + case CAIRO_OPERATOR_DEST_ATOP: + return FALSE; + + case CAIRO_OPERATOR_XOR: + case CAIRO_OPERATOR_ADD: + case CAIRO_OPERATOR_SATURATE: + return FALSE; + } + return FALSE; +} + +/* As above, we'll probably want to add a cairo_content_t parameter to + * this function + * + * We also need a definition of what "translucent" means. + */ +cairo_bool_t +_cairo_operator_always_translucent (cairo_operator_t op) +{ + switch (op) { + case CAIRO_OPERATOR_CLEAR: + return TRUE; + + case CAIRO_OPERATOR_SOURCE: + return FALSE; + + case CAIRO_OPERATOR_OVER: + case CAIRO_OPERATOR_IN: + case CAIRO_OPERATOR_OUT: + case CAIRO_OPERATOR_ATOP: + return FALSE; + + case CAIRO_OPERATOR_DEST: + return FALSE; + + case CAIRO_OPERATOR_DEST_OVER: + case CAIRO_OPERATOR_DEST_IN: + case CAIRO_OPERATOR_DEST_OUT: + case CAIRO_OPERATOR_DEST_ATOP: + return FALSE; + + case CAIRO_OPERATOR_XOR: + case CAIRO_OPERATOR_ADD: + case CAIRO_OPERATOR_SATURATE: + return TRUE; + } + return TRUE; +} diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 9319f8329..1bf2863e9 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -968,77 +968,12 @@ pattern_is_opaque (const cairo_pattern_t *abstract_pattern) return FALSE; } -static cairo_bool_t -operator_always_opaque (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return FALSE; - - case CAIRO_OPERATOR_SOURCE: - return FALSE; - - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - return FALSE; - - case CAIRO_OPERATOR_DEST: - return TRUE; - - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return FALSE; - } - return FALSE; -} - -static cairo_bool_t -operator_always_translucent (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return TRUE; - - case CAIRO_OPERATOR_SOURCE: - return FALSE; - - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - return FALSE; - - case CAIRO_OPERATOR_DEST: - return FALSE; - - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return TRUE; - } - return TRUE; -} - static cairo_bool_t surface_pattern_supported (const cairo_surface_pattern_t *pattern) { if (pattern->surface->backend->acquire_source_image != NULL) return TRUE; + return FALSE; } @@ -1047,6 +982,7 @@ pattern_supported (const cairo_pattern_t *pattern) { if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) return TRUE; + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern); @@ -1061,9 +997,10 @@ operation_supported (cairo_ps_surface_t *surface, if (! pattern_supported (pattern)) return FALSE; - if (operator_always_opaque (op)) + if (_cairo_operator_always_opaque (op)) return TRUE; - if (operator_always_translucent (op)) + + if (_cairo_operator_always_translucent (op)) return FALSE; return pattern_is_opaque (pattern); diff --git a/src/cairoint.h b/src/cairoint.h index 51829c9a7..03fc48904 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1390,6 +1390,13 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, cairo_private cairo_status_t _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices); +/* cairo_operator.c */ +cairo_private cairo_bool_t +_cairo_operator_always_opaque (cairo_operator_t op); + +cairo_private cairo_bool_t +_cairo_operator_always_translucent (cairo_operator_t op); + /* cairo_path.c */ cairo_private void _cairo_path_fixed_init (cairo_path_fixed_t *path); From b7309d065e49ae73ff8d90feca35f6b8f35922d2 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 17:25:54 -0700 Subject: [PATCH 143/155] Farm out the surface and pattern analysis functions away from cairo-ps-surface.c. We're setting things up here for better sharing as PDF surface (and others) now want to do some of the same analysis. --- src/cairo-pattern.c | 44 ++++++++++++++++++++++++-- src/cairo-pdf-surface.c | 6 +++- src/cairo-ps-surface.c | 69 +---------------------------------------- src/cairo-surface.c | 28 +++++++++++++++++ src/cairoint.h | 8 ++++- 5 files changed, 83 insertions(+), 72 deletions(-) diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 8aa296988..3f0b5e457 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1050,7 +1050,6 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } - /** * _cairo_pattern_is_opaque_solid * @@ -1063,7 +1062,7 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern, * Return value: %TRUE if the pattern is an opaque, solid color. **/ cairo_bool_t -_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern) +_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern) { cairo_solid_pattern_t *solid; @@ -1075,6 +1074,47 @@ _cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern) return CAIRO_ALPHA_IS_OPAQUE (solid->color.alpha); } +static cairo_bool_t +_gradient_is_opaque (const cairo_gradient_pattern_t *gradient) +{ + int i; + + for (i = 0; i < gradient->n_stops; i++) + if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha)) + return FALSE; + + return TRUE; +} + +/** + * _cairo_pattern_is_opaque + * + * Convenience function to determine whether a pattern is an opaque + * pattern (of any type). The same caveats that apply to + * _cairo_pattern_is_opaque_solid apply here as well. + * + * Return value: %TRUE if the pattern is a opaque. + **/ +cairo_bool_t +_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern) +{ + const cairo_pattern_union_t *pattern; + + pattern = (cairo_pattern_union_t *) abstract_pattern; + switch (pattern->base.type) { + case CAIRO_PATTERN_TYPE_SOLID: + return _cairo_pattern_is_opaque_solid (abstract_pattern); + case CAIRO_PATTERN_TYPE_SURFACE: + return _cairo_surface_is_opaque (pattern->surface.surface); + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: + return _gradient_is_opaque (&pattern->gradient.base); + } + + ASSERT_NOT_REACHED; + return FALSE; +} + static cairo_int_status_t _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, cairo_surface_t *dst, diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 8c867ecb0..9f4e5901a 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -2048,7 +2048,11 @@ _cairo_pdf_surface_paint (void *abstract_surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_INT_STATUS_UNSUPPORTED; - ASSERT_NOT_REACHED; + /* One would think that since we analyzed this away as unsupported + * that it would never be called after analyzing. But in fact, + * paint is called to paint the actual fallback surface. So we + * must not ASSERT_NOT_REACHED as we do for the other drawing + * operations. */ return CAIRO_INT_STATUS_UNSUPPORTED; } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 1bf2863e9..19a835b9b 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -901,73 +901,6 @@ color_is_gray (cairo_color_t *color) fabs (color->red - color->blue) < epsilon); } -static cairo_bool_t -color_is_opaque (const cairo_color_t *color) -{ - return color->alpha >= 0.999; -} - -static cairo_bool_t -format_is_opaque (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - return FALSE; - case CAIRO_FORMAT_RGB24: - return TRUE; - case CAIRO_FORMAT_A8: - return FALSE; - case CAIRO_FORMAT_A1: - return TRUE; - } - return FALSE; -} - -static cairo_bool_t -surface_is_opaque (const cairo_surface_t *surface) -{ - if (_cairo_surface_is_image (surface)) { - const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - return format_is_opaque (image_surface->format); - } - return TRUE; -} - -static cairo_bool_t -gradient_is_opaque (const cairo_gradient_pattern_t *gradient) -{ - return FALSE; /* XXX no gradient support */ -#if 0 - int i; - - for (i = 0; i < gradient->n_stops; i++) - if (!color_is_opaque (&gradient->stops[i].color)) - return FALSE; - return TRUE; -#endif -} - -static cairo_bool_t -pattern_is_opaque (const cairo_pattern_t *abstract_pattern) -{ - const cairo_pattern_union_t *pattern; - - pattern = (cairo_pattern_union_t *) abstract_pattern; - switch (pattern->base.type) { - case CAIRO_PATTERN_TYPE_SOLID: - return color_is_opaque (&pattern->solid.color); - case CAIRO_PATTERN_TYPE_SURFACE: - return surface_is_opaque (pattern->surface.surface); - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - return gradient_is_opaque (&pattern->gradient.base); - } - - ASSERT_NOT_REACHED; - return FALSE; -} - static cairo_bool_t surface_pattern_supported (const cairo_surface_pattern_t *pattern) { @@ -1003,7 +936,7 @@ operation_supported (cairo_ps_surface_t *surface, if (_cairo_operator_always_translucent (op)) return FALSE; - return pattern_is_opaque (pattern); + return _cairo_pattern_is_opaque (pattern); } static cairo_int_status_t diff --git a/src/cairo-surface.c b/src/cairo-surface.c index d0810aa96..5af49da5d 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -1693,3 +1693,31 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle, dst_x, dst_y, width, height); } + +static cairo_bool_t +_format_is_opaque (cairo_format_t format) +{ + switch (format) { + case CAIRO_FORMAT_ARGB32: + return FALSE; + case CAIRO_FORMAT_RGB24: + return TRUE; + case CAIRO_FORMAT_A8: + return FALSE; + case CAIRO_FORMAT_A1: + return TRUE; + } + return FALSE; +} + +cairo_bool_t +_cairo_surface_is_opaque (const cairo_surface_t *surface) +{ + if (_cairo_surface_is_image (surface)) { + const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; + + return _format_is_opaque (image_surface->format); + } + + return TRUE; +} diff --git a/src/cairoint.h b/src/cairoint.h index 03fc48904..a3d4bbe7a 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1826,6 +1826,9 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, unsigned int width, unsigned int height); +cairo_private cairo_bool_t +_cairo_surface_is_opaque (const cairo_surface_t *surface); + /* cairo_image_surface.c */ #define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \ @@ -2075,7 +2078,10 @@ _cairo_pattern_transform (cairo_pattern_t *pattern, const cairo_matrix_t *ctm_inverse); cairo_private cairo_bool_t -_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern); +_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern); + +cairo_bool_t +_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern); cairo_private cairo_int_status_t _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, From e890bfd2bf04a973ead9f5d53d06728165faa28d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 17:26:23 -0700 Subject: [PATCH 144/155] Ignore dash-zero-length --- test/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/test/.gitignore b/test/.gitignore index 8a1a8acf0..8060e7bec 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -19,6 +19,7 @@ create-from-png create-from-png-stream dash-caps-joins dash-offset-negative +dash-zero-length extend-reflect fill-and-stroke fill-rule From db111197ac436ace0c3aceb88a6d7c1abca03b02 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 14 Apr 2006 17:29:19 -0700 Subject: [PATCH 145/155] Fix _cairo_surface_is_opaque to return FALSE not TRUE for non-image surfaces. --- src/cairo-surface.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 5af49da5d..9a15db4f6 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -1710,6 +1710,14 @@ _format_is_opaque (cairo_format_t format) return FALSE; } +/* XXX: This function is funny in a couple of ways. First it seems to + * be computing something like "not translucent" rather than "opaque" + * since it returns TRUE for an A1 image surface. Second, it just + * gives up on anything other than an image surface. + * + * I imagine something that might be more useful here (or in addition) + * would be cairo_surface_get_content. + */ cairo_bool_t _cairo_surface_is_opaque (const cairo_surface_t *surface) { @@ -1719,5 +1727,5 @@ _cairo_surface_is_opaque (const cairo_surface_t *surface) return _format_is_opaque (image_surface->format); } - return TRUE; + return FALSE; } From d0356a87f7b274a0721c2644c4a62a8424923eb9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 15 Apr 2006 03:58:42 -0400 Subject: [PATCH 146/155] Implement cairo_set_scaled_font(). --- doc/public/tmpl/cairo-beos.sgml | 3 -- doc/public/tmpl/cairo-font-options.sgml | 3 -- doc/public/tmpl/cairo-font.sgml | 3 -- doc/public/tmpl/cairo-ft.sgml | 3 -- doc/public/tmpl/cairo-glitz.sgml | 3 -- doc/public/tmpl/cairo-image.sgml | 3 -- doc/public/tmpl/cairo-matrix.sgml | 3 -- doc/public/tmpl/cairo-paths.sgml | 3 -- doc/public/tmpl/cairo-pattern.sgml | 3 -- doc/public/tmpl/cairo-pdf.sgml | 3 -- doc/public/tmpl/cairo-png.sgml | 3 -- doc/public/tmpl/cairo-ps.sgml | 3 -- doc/public/tmpl/cairo-quartz.sgml | 3 -- doc/public/tmpl/cairo-scaled-font.sgml | 3 -- doc/public/tmpl/cairo-status.sgml | 3 -- doc/public/tmpl/cairo-surface.sgml | 3 -- doc/public/tmpl/cairo-text.sgml | 3 -- doc/public/tmpl/cairo-transforms.sgml | 3 -- doc/public/tmpl/cairo-types.sgml | 3 -- doc/public/tmpl/cairo-version.sgml | 3 -- doc/public/tmpl/cairo-win32-fonts.sgml | 3 -- doc/public/tmpl/cairo-win32.sgml | 3 -- doc/public/tmpl/cairo-xcb-xrender.sgml | 3 -- doc/public/tmpl/cairo-xcb.sgml | 3 -- doc/public/tmpl/cairo-xlib-xrender.sgml | 3 -- doc/public/tmpl/cairo-xlib.sgml | 3 -- doc/public/tmpl/cairo.sgml | 3 -- src/cairo.c | 40 +++++++++++++++++++++++++ src/cairo.h | 4 +++ 29 files changed, 44 insertions(+), 81 deletions(-) diff --git a/doc/public/tmpl/cairo-beos.sgml b/doc/public/tmpl/cairo-beos.sgml index 707d7e1ae..b3ea139dc 100644 --- a/doc/public/tmpl/cairo-beos.sgml +++ b/doc/public/tmpl/cairo-beos.sgml @@ -14,6 +14,3 @@ BeOS surface support - - - diff --git a/doc/public/tmpl/cairo-font-options.sgml b/doc/public/tmpl/cairo-font-options.sgml index e87b5506c..f80064241 100644 --- a/doc/public/tmpl/cairo-font-options.sgml +++ b/doc/public/tmpl/cairo-font-options.sgml @@ -14,9 +14,6 @@ How a font should be rendered - - - diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml index b65281e21..fff13cd89 100644 --- a/doc/public/tmpl/cairo-font.sgml +++ b/doc/public/tmpl/cairo-font.sgml @@ -14,9 +14,6 @@ Base class for fonts - - - diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml index 275f7af2f..d5ee69c6e 100644 --- a/doc/public/tmpl/cairo-ft.sgml +++ b/doc/public/tmpl/cairo-ft.sgml @@ -14,6 +14,3 @@ Font support for FreeType - - - diff --git a/doc/public/tmpl/cairo-glitz.sgml b/doc/public/tmpl/cairo-glitz.sgml index 437c71e08..0d204dedf 100644 --- a/doc/public/tmpl/cairo-glitz.sgml +++ b/doc/public/tmpl/cairo-glitz.sgml @@ -14,6 +14,3 @@ OpenGL accelerated rendering using the Glitz library - - - diff --git a/doc/public/tmpl/cairo-image.sgml b/doc/public/tmpl/cairo-image.sgml index 8e8dc86e1..761627ead 100644 --- a/doc/public/tmpl/cairo-image.sgml +++ b/doc/public/tmpl/cairo-image.sgml @@ -17,9 +17,6 @@ Rendering to memory buffers - - - diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml index 3effbd239..19b3abc5f 100644 --- a/doc/public/tmpl/cairo-matrix.sgml +++ b/doc/public/tmpl/cairo-matrix.sgml @@ -29,9 +29,6 @@ Generic matrix operations - - - diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml index 01bf12d67..b06bc0e9d 100644 --- a/doc/public/tmpl/cairo-paths.sgml +++ b/doc/public/tmpl/cairo-paths.sgml @@ -14,9 +14,6 @@ Creating paths and manipulating path data - - - diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml index f7f29b147..831985863 100644 --- a/doc/public/tmpl/cairo-pattern.sgml +++ b/doc/public/tmpl/cairo-pattern.sgml @@ -14,9 +14,6 @@ Gradients and filtered sources - - - diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml index 4f7dbd71d..efef4a671 100644 --- a/doc/public/tmpl/cairo-pdf.sgml +++ b/doc/public/tmpl/cairo-pdf.sgml @@ -14,6 +14,3 @@ Rendering PDF documents - - - diff --git a/doc/public/tmpl/cairo-png.sgml b/doc/public/tmpl/cairo-png.sgml index cba1516e7..d2d6d383d 100644 --- a/doc/public/tmpl/cairo-png.sgml +++ b/doc/public/tmpl/cairo-png.sgml @@ -14,9 +14,6 @@ Reading and writing PNG images - - - diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml index a3d5765a6..087f464fd 100644 --- a/doc/public/tmpl/cairo-ps.sgml +++ b/doc/public/tmpl/cairo-ps.sgml @@ -14,6 +14,3 @@ Rendering PostScript documents - - - diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml index 02a69d919..226dabe07 100644 --- a/doc/public/tmpl/cairo-quartz.sgml +++ b/doc/public/tmpl/cairo-quartz.sgml @@ -14,6 +14,3 @@ Rendering to Quartz surfaces - - - diff --git a/doc/public/tmpl/cairo-scaled-font.sgml b/doc/public/tmpl/cairo-scaled-font.sgml index 06564548f..9202aded4 100644 --- a/doc/public/tmpl/cairo-scaled-font.sgml +++ b/doc/public/tmpl/cairo-scaled-font.sgml @@ -14,9 +14,6 @@ Caching metrics for a particular font size - - - diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml index de5f35fea..1a9d86f9f 100644 --- a/doc/public/tmpl/cairo-status.sgml +++ b/doc/public/tmpl/cairo-status.sgml @@ -14,9 +14,6 @@ Decoding cairo's status - - - diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml index 69d63d276..bbd829d83 100644 --- a/doc/public/tmpl/cairo-surface.sgml +++ b/doc/public/tmpl/cairo-surface.sgml @@ -14,9 +14,6 @@ Base class for surfaces - - - diff --git a/doc/public/tmpl/cairo-text.sgml b/doc/public/tmpl/cairo-text.sgml index 56678b167..8514789c6 100644 --- a/doc/public/tmpl/cairo-text.sgml +++ b/doc/public/tmpl/cairo-text.sgml @@ -14,9 +14,6 @@ Rendering text and sets of glyphs - - - diff --git a/doc/public/tmpl/cairo-transforms.sgml b/doc/public/tmpl/cairo-transforms.sgml index 65199c8b4..14351e215 100644 --- a/doc/public/tmpl/cairo-transforms.sgml +++ b/doc/public/tmpl/cairo-transforms.sgml @@ -14,6 +14,3 @@ Manipulating the current transformation matrix - - - diff --git a/doc/public/tmpl/cairo-types.sgml b/doc/public/tmpl/cairo-types.sgml index 9e6f6b599..66a309864 100644 --- a/doc/public/tmpl/cairo-types.sgml +++ b/doc/public/tmpl/cairo-types.sgml @@ -14,9 +14,6 @@ Generic data types used in the cairo API - - - diff --git a/doc/public/tmpl/cairo-version.sgml b/doc/public/tmpl/cairo-version.sgml index 42eb58eb7..329a2f43b 100644 --- a/doc/public/tmpl/cairo-version.sgml +++ b/doc/public/tmpl/cairo-version.sgml @@ -114,9 +114,6 @@ if (cairo_version() >= %CAIRO_VERSION_ENCODE(1, 0, 0)) - - - diff --git a/doc/public/tmpl/cairo-win32-fonts.sgml b/doc/public/tmpl/cairo-win32-fonts.sgml index 3652ccbdc..d686ace2e 100644 --- a/doc/public/tmpl/cairo-win32-fonts.sgml +++ b/doc/public/tmpl/cairo-win32-fonts.sgml @@ -14,6 +14,3 @@ Font support for Microsoft Windows - - - diff --git a/doc/public/tmpl/cairo-win32.sgml b/doc/public/tmpl/cairo-win32.sgml index b486ba833..6cc1cd864 100644 --- a/doc/public/tmpl/cairo-win32.sgml +++ b/doc/public/tmpl/cairo-win32.sgml @@ -14,6 +14,3 @@ Microsoft Windows surface support - - - diff --git a/doc/public/tmpl/cairo-xcb-xrender.sgml b/doc/public/tmpl/cairo-xcb-xrender.sgml index fc243236d..635fa3ccc 100644 --- a/doc/public/tmpl/cairo-xcb-xrender.sgml +++ b/doc/public/tmpl/cairo-xcb-xrender.sgml @@ -14,6 +14,3 @@ X Window System rendering using the XCB library - - - diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml index fc243236d..635fa3ccc 100644 --- a/doc/public/tmpl/cairo-xcb.sgml +++ b/doc/public/tmpl/cairo-xcb.sgml @@ -14,6 +14,3 @@ X Window System rendering using the XCB library - - - diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml index c99d78407..df970a2f2 100644 --- a/doc/public/tmpl/cairo-xlib-xrender.sgml +++ b/doc/public/tmpl/cairo-xlib-xrender.sgml @@ -14,6 +14,3 @@ XLib/Xrender Backend - - - diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml index f931a50f8..7480fad1a 100644 --- a/doc/public/tmpl/cairo-xlib.sgml +++ b/doc/public/tmpl/cairo-xlib.sgml @@ -14,6 +14,3 @@ X Window System rendering using XLib - - - diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml index 04480e715..32fd94f40 100644 --- a/doc/public/tmpl/cairo.sgml +++ b/doc/public/tmpl/cairo.sgml @@ -24,9 +24,6 @@ The cairo drawing context - - - diff --git a/src/cairo.c b/src/cairo.c index 60166f554..e48630f65 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -1984,6 +1984,46 @@ cairo_get_font_options (cairo_t *cr, _cairo_gstate_get_font_options (cr->gstate, options); } +/** + * cairo_set_scaled_font: + * @cr: a #cairo_t + * @scaled_font: a #cairo_scaled_font_t + * + * Replaces the current font face, font matrix, and font options in + * the #cairo_t with those of the #cairo_scaled_font_t. Except for + * some translation, the current CTM of the #cairo_t should be the + * same as that of the #cairo_scaled_font_t, which can be accessed + * using cairo_scaled_font_get_ctm(). + **/ +void +cairo_set_scaled_font (cairo_t *cr, + const cairo_scaled_font_t *scaled_font) +{ + if (cr->status) + return; + + cr->status = scaled_font->status; + if (cr->status) + goto BAIL; + + cr->status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face); + if (cr->status) + goto BAIL; + + cr->status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix); + if (cr->status) + goto BAIL; + + cr->status = _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options); + if (cr->status) + goto BAIL; + + return; + +BAIL: + _cairo_set_error (cr, cr->status); +} + /** * cairo_text_extents: * @cr: a #cairo_t diff --git a/src/cairo.h b/src/cairo.h index 5b38d18e4..e6f8626fb 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -852,6 +852,10 @@ cairo_public void cairo_get_font_options (cairo_t *cr, cairo_font_options_t *options); +cairo_public void +cairo_set_scaled_font (cairo_t *cr, + const cairo_scaled_font_t *scaled_font); + cairo_public void cairo_show_text (cairo_t *cr, const char *utf8); From 714bb88832f0e6324cd4737aaa37a4ba39f8d14e Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Sun, 16 Apr 2006 15:42:49 +0200 Subject: [PATCH 147/155] SVG: Add support for CAIRO_CONTENT_COLOR in create_similar. Also add support for testing this feature in test/cairo-test.c And a bunch of unwanted commit of sgml files. --- doc/public/tmpl/cairo-beos.sgml | 3 ++ doc/public/tmpl/cairo-font-options.sgml | 3 ++ doc/public/tmpl/cairo-font.sgml | 3 ++ doc/public/tmpl/cairo-ft.sgml | 3 ++ doc/public/tmpl/cairo-glitz.sgml | 3 ++ doc/public/tmpl/cairo-image.sgml | 3 ++ doc/public/tmpl/cairo-matrix.sgml | 3 ++ doc/public/tmpl/cairo-paths.sgml | 3 ++ doc/public/tmpl/cairo-pattern.sgml | 3 ++ doc/public/tmpl/cairo-pdf.sgml | 3 ++ doc/public/tmpl/cairo-png.sgml | 3 ++ doc/public/tmpl/cairo-ps.sgml | 3 ++ doc/public/tmpl/cairo-quartz.sgml | 3 ++ doc/public/tmpl/cairo-scaled-font.sgml | 3 ++ doc/public/tmpl/cairo-status.sgml | 3 ++ doc/public/tmpl/cairo-surface.sgml | 3 ++ doc/public/tmpl/cairo-text.sgml | 3 ++ doc/public/tmpl/cairo-transforms.sgml | 3 ++ doc/public/tmpl/cairo-types.sgml | 3 ++ doc/public/tmpl/cairo-version.sgml | 3 ++ doc/public/tmpl/cairo-win32-fonts.sgml | 3 ++ doc/public/tmpl/cairo-win32.sgml | 3 ++ doc/public/tmpl/cairo-xcb-xrender.sgml | 3 ++ doc/public/tmpl/cairo-xcb.sgml | 3 ++ doc/public/tmpl/cairo-xlib-xrender.sgml | 3 ++ doc/public/tmpl/cairo-xlib.sgml | 3 ++ doc/public/tmpl/cairo.sgml | 3 ++ src/cairo-svg-surface.c | 69 +++++++++++++++++++------ test/cairo-test.c | 36 +++++++++++-- 29 files changed, 167 insertions(+), 19 deletions(-) diff --git a/doc/public/tmpl/cairo-beos.sgml b/doc/public/tmpl/cairo-beos.sgml index b3ea139dc..707d7e1ae 100644 --- a/doc/public/tmpl/cairo-beos.sgml +++ b/doc/public/tmpl/cairo-beos.sgml @@ -14,3 +14,6 @@ BeOS surface support + + + diff --git a/doc/public/tmpl/cairo-font-options.sgml b/doc/public/tmpl/cairo-font-options.sgml index f80064241..e87b5506c 100644 --- a/doc/public/tmpl/cairo-font-options.sgml +++ b/doc/public/tmpl/cairo-font-options.sgml @@ -14,6 +14,9 @@ How a font should be rendered + + + diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml index fff13cd89..b65281e21 100644 --- a/doc/public/tmpl/cairo-font.sgml +++ b/doc/public/tmpl/cairo-font.sgml @@ -14,6 +14,9 @@ Base class for fonts + + + diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml index d5ee69c6e..275f7af2f 100644 --- a/doc/public/tmpl/cairo-ft.sgml +++ b/doc/public/tmpl/cairo-ft.sgml @@ -14,3 +14,6 @@ Font support for FreeType + + + diff --git a/doc/public/tmpl/cairo-glitz.sgml b/doc/public/tmpl/cairo-glitz.sgml index 0d204dedf..437c71e08 100644 --- a/doc/public/tmpl/cairo-glitz.sgml +++ b/doc/public/tmpl/cairo-glitz.sgml @@ -14,3 +14,6 @@ OpenGL accelerated rendering using the Glitz library + + + diff --git a/doc/public/tmpl/cairo-image.sgml b/doc/public/tmpl/cairo-image.sgml index 761627ead..8e8dc86e1 100644 --- a/doc/public/tmpl/cairo-image.sgml +++ b/doc/public/tmpl/cairo-image.sgml @@ -17,6 +17,9 @@ Rendering to memory buffers + + + diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml index 19b3abc5f..3effbd239 100644 --- a/doc/public/tmpl/cairo-matrix.sgml +++ b/doc/public/tmpl/cairo-matrix.sgml @@ -29,6 +29,9 @@ Generic matrix operations + + + diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml index b06bc0e9d..01bf12d67 100644 --- a/doc/public/tmpl/cairo-paths.sgml +++ b/doc/public/tmpl/cairo-paths.sgml @@ -14,6 +14,9 @@ Creating paths and manipulating path data + + + diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml index 831985863..f7f29b147 100644 --- a/doc/public/tmpl/cairo-pattern.sgml +++ b/doc/public/tmpl/cairo-pattern.sgml @@ -14,6 +14,9 @@ Gradients and filtered sources + + + diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml index efef4a671..4f7dbd71d 100644 --- a/doc/public/tmpl/cairo-pdf.sgml +++ b/doc/public/tmpl/cairo-pdf.sgml @@ -14,3 +14,6 @@ Rendering PDF documents + + + diff --git a/doc/public/tmpl/cairo-png.sgml b/doc/public/tmpl/cairo-png.sgml index d2d6d383d..cba1516e7 100644 --- a/doc/public/tmpl/cairo-png.sgml +++ b/doc/public/tmpl/cairo-png.sgml @@ -14,6 +14,9 @@ Reading and writing PNG images + + + diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml index 087f464fd..a3d5765a6 100644 --- a/doc/public/tmpl/cairo-ps.sgml +++ b/doc/public/tmpl/cairo-ps.sgml @@ -14,3 +14,6 @@ Rendering PostScript documents + + + diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml index 226dabe07..02a69d919 100644 --- a/doc/public/tmpl/cairo-quartz.sgml +++ b/doc/public/tmpl/cairo-quartz.sgml @@ -14,3 +14,6 @@ Rendering to Quartz surfaces + + + diff --git a/doc/public/tmpl/cairo-scaled-font.sgml b/doc/public/tmpl/cairo-scaled-font.sgml index 9202aded4..06564548f 100644 --- a/doc/public/tmpl/cairo-scaled-font.sgml +++ b/doc/public/tmpl/cairo-scaled-font.sgml @@ -14,6 +14,9 @@ Caching metrics for a particular font size + + + diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml index 1a9d86f9f..de5f35fea 100644 --- a/doc/public/tmpl/cairo-status.sgml +++ b/doc/public/tmpl/cairo-status.sgml @@ -14,6 +14,9 @@ Decoding cairo's status + + + diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml index bbd829d83..69d63d276 100644 --- a/doc/public/tmpl/cairo-surface.sgml +++ b/doc/public/tmpl/cairo-surface.sgml @@ -14,6 +14,9 @@ Base class for surfaces + + + diff --git a/doc/public/tmpl/cairo-text.sgml b/doc/public/tmpl/cairo-text.sgml index 8514789c6..56678b167 100644 --- a/doc/public/tmpl/cairo-text.sgml +++ b/doc/public/tmpl/cairo-text.sgml @@ -14,6 +14,9 @@ Rendering text and sets of glyphs + + + diff --git a/doc/public/tmpl/cairo-transforms.sgml b/doc/public/tmpl/cairo-transforms.sgml index 14351e215..65199c8b4 100644 --- a/doc/public/tmpl/cairo-transforms.sgml +++ b/doc/public/tmpl/cairo-transforms.sgml @@ -14,3 +14,6 @@ Manipulating the current transformation matrix + + + diff --git a/doc/public/tmpl/cairo-types.sgml b/doc/public/tmpl/cairo-types.sgml index 66a309864..9e6f6b599 100644 --- a/doc/public/tmpl/cairo-types.sgml +++ b/doc/public/tmpl/cairo-types.sgml @@ -14,6 +14,9 @@ Generic data types used in the cairo API + + + diff --git a/doc/public/tmpl/cairo-version.sgml b/doc/public/tmpl/cairo-version.sgml index 329a2f43b..42eb58eb7 100644 --- a/doc/public/tmpl/cairo-version.sgml +++ b/doc/public/tmpl/cairo-version.sgml @@ -114,6 +114,9 @@ if (cairo_version() >= %CAIRO_VERSION_ENCODE(1, 0, 0)) + + + diff --git a/doc/public/tmpl/cairo-win32-fonts.sgml b/doc/public/tmpl/cairo-win32-fonts.sgml index d686ace2e..3652ccbdc 100644 --- a/doc/public/tmpl/cairo-win32-fonts.sgml +++ b/doc/public/tmpl/cairo-win32-fonts.sgml @@ -14,3 +14,6 @@ Font support for Microsoft Windows + + + diff --git a/doc/public/tmpl/cairo-win32.sgml b/doc/public/tmpl/cairo-win32.sgml index 6cc1cd864..b486ba833 100644 --- a/doc/public/tmpl/cairo-win32.sgml +++ b/doc/public/tmpl/cairo-win32.sgml @@ -14,3 +14,6 @@ Microsoft Windows surface support + + + diff --git a/doc/public/tmpl/cairo-xcb-xrender.sgml b/doc/public/tmpl/cairo-xcb-xrender.sgml index 635fa3ccc..fc243236d 100644 --- a/doc/public/tmpl/cairo-xcb-xrender.sgml +++ b/doc/public/tmpl/cairo-xcb-xrender.sgml @@ -14,3 +14,6 @@ X Window System rendering using the XCB library + + + diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml index 635fa3ccc..fc243236d 100644 --- a/doc/public/tmpl/cairo-xcb.sgml +++ b/doc/public/tmpl/cairo-xcb.sgml @@ -14,3 +14,6 @@ X Window System rendering using the XCB library + + + diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml index df970a2f2..c99d78407 100644 --- a/doc/public/tmpl/cairo-xlib-xrender.sgml +++ b/doc/public/tmpl/cairo-xlib-xrender.sgml @@ -14,3 +14,6 @@ XLib/Xrender Backend + + + diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml index 7480fad1a..f931a50f8 100644 --- a/doc/public/tmpl/cairo-xlib.sgml +++ b/doc/public/tmpl/cairo-xlib.sgml @@ -14,3 +14,6 @@ X Window System rendering using XLib + + + diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml index 32fd94f40..04480e715 100644 --- a/doc/public/tmpl/cairo.sgml +++ b/doc/public/tmpl/cairo.sgml @@ -24,6 +24,9 @@ The cairo drawing context + + + diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index accbe0043..eb01214ae 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -80,6 +80,8 @@ struct cairo_svg_document { struct cairo_svg_surface { cairo_surface_t base; + cairo_content_t content; + unsigned int id; double width; @@ -112,8 +114,9 @@ _cairo_svg_document_reference (cairo_svg_document_t *document); static cairo_surface_t * _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - double width, - double height); + cairo_content_t content, + double width, + double height); static const cairo_surface_backend_t cairo_svg_surface_backend; @@ -129,7 +132,8 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, if (document == NULL) return NULL; - surface = _cairo_svg_surface_create_for_document (document, width, height); + surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, + width, height); document->owner = surface; _cairo_svg_document_destroy (document); @@ -234,11 +238,12 @@ cairo_svg_surface_set_dpi (cairo_surface_t *surface, static cairo_surface_t * _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - double width, - double height) + cairo_content_t content, + double width, + double height) { cairo_svg_surface_t *surface; - xmlNodePtr clip, clip_rect; + xmlNodePtr clip, rect; int clip_id; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; @@ -262,11 +267,11 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, clip = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("clipPath"), NULL); snprintf (buffer, sizeof buffer, "clip%d", clip_id); xmlSetProp (clip, CC2XML ("id"), C2XML (buffer)); - clip_rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL); + rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL); _cairo_dtostr (buffer, sizeof buffer, width); - xmlSetProp (clip_rect, CC2XML ("width"), C2XML (buffer)); + xmlSetProp (rect, CC2XML ("width"), C2XML (buffer)); _cairo_dtostr (buffer, sizeof buffer, height); - xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer)); + xmlSetProp (rect, CC2XML ("height"), C2XML (buffer)); surface->xml_node = xmlNewNode (NULL, CC2XML ("g")); surface->xml_root_node = surface->xml_node; @@ -276,9 +281,19 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id); xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer)); + if (content == CAIRO_CONTENT_COLOR) { + rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL); + _cairo_dtostr (buffer, sizeof buffer, width); + xmlSetProp (rect, CC2XML ("width"), C2XML (buffer)); + _cairo_dtostr (buffer, sizeof buffer, height); + xmlSetProp (rect, CC2XML ("height"), C2XML (buffer)); + xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);")); + } + surface->modified = TRUE; surface->previous_id = surface->id; - + surface->content = content; + return &surface->base; } @@ -290,8 +305,12 @@ _cairo_svg_surface_create_similar (void *abstract_src, { cairo_svg_surface_t *template = abstract_src; + if (content != CAIRO_CONTENT_COLOR_ALPHA && + content != CAIRO_CONTENT_COLOR) + return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_svg_surface_create_for_document (template->document, - width, height); + content, width, height); } static cairo_status_t @@ -524,7 +543,8 @@ emit_composite_svg_pattern (xmlNodePtr node, xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); child = xmlNewChild (node, NULL, CC2XML("use"), NULL); - snprintf (buffer, sizeof buffer, "#surface%d", surface->previous_id); + snprintf (buffer, sizeof buffer, "#surface%d", + surface->modified ? surface->id : surface->previous_id); xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer)); if (!is_pattern) { @@ -1061,9 +1081,28 @@ _cairo_svg_surface_paint (void *abstract_surface, if (surface->clip_level == 0 && (op == CAIRO_OPERATOR_CLEAR || op == CAIRO_OPERATOR_SOURCE)) { - xmlFreeNode (surface->xml_root_node->children); - if (op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; + xmlNodePtr child = surface->xml_root_node->children; + + while (child != NULL) { + xmlUnlinkNode (child); + xmlFreeNode (child); + child = surface->xml_root_node->children; + } + + if (op == CAIRO_OPERATOR_CLEAR) { + if (surface->content == CAIRO_CONTENT_COLOR) { + xmlNodePtr rect; + char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; + + rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL); + _cairo_dtostr (buffer, sizeof buffer, surface->width); + xmlSetProp (rect, CC2XML ("width"), C2XML (buffer)); + _cairo_dtostr (buffer, sizeof buffer, surface->height); + xmlSetProp (rect, CC2XML ("height"), C2XML (buffer)); + xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);")); + } + return CAIRO_STATUS_SUCCESS; + } } emit_paint (surface->xml_node, surface, op, source); diff --git a/test/cairo-test.c b/test/cairo-test.c index 59b55f7ba..9105a1b36 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1304,6 +1304,7 @@ typedef struct _svg_target_closure { char *filename; int width, height; + cairo_surface_t *target; } svg_target_closure_t; static cairo_surface_t * @@ -1330,7 +1331,19 @@ create_svg_surface (cairo_test_t *test, free (ptc); return NULL; } + cairo_svg_surface_set_dpi (surface, 72., 72.); + + if (content == CAIRO_CONTENT_COLOR) { + ptc->target = surface; + surface = cairo_surface_create_similar (ptc->target, + CAIRO_CONTENT_COLOR, + width, height); + } else { + ptc->target = NULL; + } + cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL); + return surface; } @@ -1340,15 +1353,26 @@ svg_surface_write_to_png (cairo_surface_t *surface, const char *filename) svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key); char command[4096]; - cairo_surface_finish (surface); + if (ptc->target) { + cairo_t *cr; + cr = cairo_create (ptc->target); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_show_page (cr); + cairo_destroy (cr); + cairo_surface_finish (surface); + surface = ptc->target; + } + + cairo_surface_finish (surface); sprintf (command, "./svg2png %s %s", ptc->filename, filename); if (system (command) != 0) return CAIRO_STATUS_WRITE_ERROR; - return CAIRO_STATUS_WRITE_ERROR; + return CAIRO_STATUS_SUCCESS; } static void @@ -1593,10 +1617,14 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf }, #endif #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE - { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR, - create_svg_surface, svg_surface_write_to_png, cleanup_svg }, { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, create_svg_surface, svg_surface_write_to_png, cleanup_svg }, + + /* A SVG surface is COLOR_APLHA by default, and currently a create + * similar with content != COLOR_ALPHA will return a nil surface. + * So don't test COLOR for now. */ + { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR, + create_svg_surface, svg_surface_write_to_png, cleanup_svg }, #endif #if CAIRO_HAS_BEOS_SURFACE { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, From 347083b3f0be2f07d1953278b8516774253752f1 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Sun, 16 Apr 2006 16:00:27 +0200 Subject: [PATCH 148/155] SVG: Add reference files for antialiased text tests. Currently, text are rendered as paths in SVG files, so, when rendered to png through librsvg, they don't match general reference images. --- test/show-text-current-point-svg-argb32-ref.png | Bin 0 -> 4236 bytes test/show-text-current-point-svg-rgb24-ref.png | Bin 0 -> 4236 bytes test/text-antialias-gray-svg-argb32-ref.png | Bin 0 -> 1077 bytes test/text-antialias-gray-svg-rgb24-ref.png | Bin 0 -> 1077 bytes test/text-pattern-svg-argb32-ref.png | Bin 0 -> 2643 bytes test/text-pattern-svg-rgb24-ref.png | Bin 0 -> 2428 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/show-text-current-point-svg-argb32-ref.png create mode 100644 test/show-text-current-point-svg-rgb24-ref.png create mode 100644 test/text-antialias-gray-svg-argb32-ref.png create mode 100644 test/text-antialias-gray-svg-rgb24-ref.png create mode 100644 test/text-pattern-svg-argb32-ref.png create mode 100644 test/text-pattern-svg-rgb24-ref.png diff --git a/test/show-text-current-point-svg-argb32-ref.png b/test/show-text-current-point-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..717ad7e425712d1026fa2e5b3efd670af2105116 GIT binary patch literal 4236 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 literal 0 HcmV?d00001 diff --git a/test/show-text-current-point-svg-rgb24-ref.png b/test/show-text-current-point-svg-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..717ad7e425712d1026fa2e5b3efd670af2105116 GIT binary patch literal 4236 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 literal 0 HcmV?d00001 diff --git a/test/text-antialias-gray-svg-argb32-ref.png b/test/text-antialias-gray-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/text-antialias-gray-svg-rgb24-ref.png b/test/text-antialias-gray-svg-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/text-pattern-svg-argb32-ref.png b/test/text-pattern-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b5f753e791f1a1f790e3e327048108194362b7 GIT binary patch literal 2643 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 Pq(m{4y^CFq4Vv^XmNgH! literal 0 HcmV?d00001 diff --git a/test/text-pattern-svg-rgb24-ref.png b/test/text-pattern-svg-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..6f3510cbfef57b0a62a6c53313ec59e7ef7686ff GIT binary patch literal 2428 zcmZ`*do&Y#AD@uPrCiEnE(=Ye&9x?0%(S^D520AhB|;-hS#oQ0*<3dFZI$c86M37S z;St$*V#Jo@PI4`IqC{?Qy`FQP^PbLm&-*>+^ZlI9@At>&oZtDK^ZBH?I-irUiU{BS~yY-XX zkCzK#SdWxW6BV!9wDHbgUV|KW!uX&=y^BSBag3Ij;-bS_>oyq`0;RwlXnoZ^#a;~q zEJ;*$dl<@&vx&%5f<{blwBC%PNR5rDF894Ga`M*{EI_?RCsuolmRXVWtRJM{pqj+T z$(iP>3y^{z*LLn}rBCx_6r{=IR#E(k!S#?Obl zea$E@&*XDFdm%E(_G}FK|AF2@FTvO0V^x?-m(iyWx{GD&_97=Ivxvz4u zyG)XcjX1Dy6yX*t?PjfgzP%_wWvYpXfxiTam#38(p$qk540JK@=fXhKdM51izBB&x zns8{dYWl)xe3Ch_zv#z(?H;X}*}~F%;Fa!ui>Xr!Xzmm8@eA8C<&E73j&TMQALbo@ zHlDl`K3`vnJDaHno>$z)!d-Ei<>`SpUh&OMDbAoNuxBg<=}gDhq|zus<|}X)Hzz}l zC{s}vij@95y6p+$%uao0h#F6*p<#_$5GThn?nW0QIgY)`I&tW;N{g zDLc&zX^g20Klfp_ zk$-HfsVjKn_*#cZG-9i=d_CnUEfy}-5kF}(N?s`~i7twdfAIh#L@34Veif(ZF(TWO z`m);R$dN0DhCqhHLwZ-^`Dy+5<&{^t_AW~!qry8?xI{?;Xs5tWtS4X55Mm&sAy^rjEBumB~Kl? zLp5Q23qIDP&b@9znRVoLB0BX5kmtVv`>zysEF1IQO30fJ>66WFxCZ^};{tGtMTl-y z4S+AZh_7+E5wkl>s>Wg4NY9izp%s1Q9huSU6Yl_k!~wzhg=TV0C8wEnh}dr!V-Tns zR;_C%`OC&%3M{+(Pfv^hvDo9vVrVh0|ElOncvy~BK3=!^crhF9&87^spJs0 zQrOBBMe={dvb+!9%il|VkSqZXg*mNPVi|+>gzg^anEK~x zt11NUk+9%^@saScpa`od{u(XnCL(|nUa5BJf#_aJ zTH$(;4&>>??ZMunsz3W7-{NAKJ(6U{F`|;vXy4i@L}}bV`}O7*`}{tMxyi0<)4%Hb zkG?g_*snQpEoMaUA_EooX^xyKHhqaD-TgID?Mg;FT0eJ#)FtVAGVkUW%a|GkB3Cw& z7pXmN{$}&MMfgWi0(b3MVA5$RV#v!Hw|r$^+fJ*4<%&iCv{ z+{#t)60VoBttL+G?+KYPYQ;cL@9U032$e^6kj?Ld7--k-v@f#FBaTvsEf{3!fp81k z@xeQ1Gou(6$WQwelSlE~r9zI%^vrN|UzYyo^{! z+7(*cJzCpBQR_o42|?ywg8?_UG-rgSqPE2%Ef<*O8>OpuWk=s@ZmsCLaKZuk#sg4w(1uz&?RF>z+Wv!ohL=?q<4_c zM@xipLITj~sX|4umO{6vi|$Xg{?spY&8fJoPulPj*!yxNe04jlb`s-`I>Cb`Ja&fS^B27@geDjZ7 zyz7c3-!5a}tJLOnP_?^Of2VPtMb7`=rxNi`r Date: Mon, 17 Apr 2006 09:54:03 +0200 Subject: [PATCH 149/155] SVG: Return UNTESTED for test involving operators. unbounded-operator, operator-clear, operator-source, clip-operator --- test/cairo-test.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/cairo-test.c b/test/cairo-test.c index 9105a1b36..fce38fe48 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -183,7 +183,7 @@ typedef struct _cairo_test_target cairo_test_create_target_surface_t create_target_surface; cairo_test_write_to_png_t write_to_png; cairo_test_cleanup_target_t cleanup_target; - void *closure; + void *closure; } cairo_test_target_t; static char * @@ -1298,6 +1298,14 @@ cleanup_pdf (void *closure) #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE #include "cairo-svg.h" +static const char *svg_ignored_tests[] = { + "operator-source", + "operator-clear", + "clip-operator", + "unbounded-operator", + NULL +}; + cairo_user_data_key_t svg_closure_key; typedef struct _svg_target_closure @@ -1314,9 +1322,14 @@ create_svg_surface (cairo_test_t *test, { int width = test->width; int height = test->height; + int i; svg_target_closure_t *ptc; cairo_surface_t *surface; + for (i = 0; svg_ignored_tests[i] != NULL; i++) + if (strcmp (test->name, svg_ignored_tests[i]) == 0) + return NULL; + *closure = ptc = xmalloc (sizeof (svg_target_closure_t)); ptc->width = width; From c01805bafd5ad68263a3e644787cd7c04838124b Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Mon, 17 Apr 2006 10:21:50 +0200 Subject: [PATCH 150/155] SVG: Don't check for content type in create_similar, and mark surface as modified when clearing it. --- src/cairo-svg-surface.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index eb01214ae..b65796efc 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -305,10 +305,6 @@ _cairo_svg_surface_create_similar (void *abstract_src, { cairo_svg_surface_t *template = abstract_src; - if (content != CAIRO_CONTENT_COLOR_ALPHA && - content != CAIRO_CONTENT_COLOR) - return (cairo_surface_t *) &_cairo_surface_nil; - return _cairo_svg_surface_create_for_document (template->document, content, width, height); } @@ -1101,6 +1097,7 @@ _cairo_svg_surface_paint (void *abstract_surface, xmlSetProp (rect, CC2XML ("height"), C2XML (buffer)); xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);")); } + surface->modified = TRUE; return CAIRO_STATUS_SUCCESS; } } From 9e2a2ea0da93065c46a6d6249f98a319ee6158dd Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Mon, 17 Apr 2006 11:07:15 +0200 Subject: [PATCH 151/155] SVG: Don't insert /n/r in base64 encoded image data That doesn't work since libxml replace them by They were intended to ease readability of generated files. --- src/cairo-svg-surface.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index b65796efc..da38a1eb8 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -368,7 +368,6 @@ typedef struct { unsigned int in_mem; unsigned char src[3]; unsigned char dst[5]; - unsigned int count; unsigned int trailing; } base64_write_closure_t; @@ -402,11 +401,6 @@ base64_write_func (void *closure, data++; length--; } - info->count++; - if (info->count >= 18) { - info->count = 0; - xmlBufferCat (info->buffer, CC2XML ("\r\n")); - } dst[0] = base64_table[src[0] >> 2]; dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4]; dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6]; @@ -446,7 +440,6 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, info.buffer = xmlBufferCreate(); info.in_mem = 0; - info.count = 0; info.trailing = 0; memset (info.dst, '\x0', 5); *buffer = info.buffer; From 170a028bfa00286324d8598d831e570d868a26f1 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Mon, 17 Apr 2006 23:26:30 +0200 Subject: [PATCH 152/155] SVG: Fix mask and try to support CAIRO_CONTENT_ALPHA. Cairo and SVG differ in their implementation of mask. Cairo only uses alpha channel where SVG uses all channels. So, before using a surface for masking, we use a filter that sets RGB channels to 1.0. Support for CAIRO_CONTENT_ALPHA is similar and use the same filter when a SVG alpha surface is composited. --- src/cairo-svg-surface.c | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index da38a1eb8..447abf834 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -75,6 +75,8 @@ struct cairo_svg_document { unsigned int filter_id; unsigned int clip_id; unsigned int mask_id; + + cairo_bool_t alpha_filter; }; struct cairo_svg_surface { @@ -331,6 +333,29 @@ _cairo_svg_surface_finish (void *abstract_surface) return status; } +static void +emit_alpha_filter (cairo_svg_document_t *document) +{ + if (!document->alpha_filter) { + xmlNodePtr node; + xmlNodePtr child; + + node = xmlNewChild (document->xml_node_defs, NULL, + CC2XML ("filter"), NULL); + xmlSetProp (node, CC2XML ("id"), CC2XML ("alpha")); + xmlSetProp (node, CC2XML ("filterUnits"), CC2XML ("objectBoundingBox")); + xmlSetProp (node, CC2XML ("x"), CC2XML ("0%")); + xmlSetProp (node, CC2XML ("y"), CC2XML ("0%")); + xmlSetProp (node, CC2XML ("width"), CC2XML ("100%")); + xmlSetProp (node, CC2XML ("height"), CC2XML ("100%")); + child = xmlNewChild (node, NULL, CC2XML ("feColorMatrix"), NULL); + xmlSetProp (child, CC2XML("type"), CC2XML ("matrix")); + xmlSetProp (child, CC2XML("in"), CC2XML ("SourceGraphic")); + xmlSetProp (child, CC2XML("values"), CC2XML ("0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0")); + document->alpha_filter = TRUE; + } +} + static void emit_transform (xmlNodePtr node, char const *attribute_str, @@ -528,8 +553,13 @@ emit_composite_svg_pattern (xmlNodePtr node, xmlNodePtr child; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - if (surface->modified) - xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); + if (surface->modified) { + if (surface->content == CAIRO_CONTENT_ALPHA) + emit_alpha_filter (document); + child = xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1)); + if (surface->content == CAIRO_CONTENT_ALPHA) + xmlSetProp (child, CC2XML ("filter"), CC2XML("url(#alpha)")); + } child = xmlNewChild (node, NULL, CC2XML("use"), NULL); snprintf (buffer, sizeof buffer, "#surface%d", @@ -1033,7 +1063,8 @@ emit_paint (xmlNodePtr node, xmlBufferPtr style; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + source->extend == CAIRO_EXTEND_NONE) return emit_composite_pattern (node, (cairo_surface_pattern_t *) source, NULL, NULL, FALSE); @@ -1112,10 +1143,16 @@ _cairo_svg_surface_mask (void *abstract_surface, xmlNodePtr child, mask_node; char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN]; - mask_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("mask"), NULL); + emit_alpha_filter (document); + + mask_node = xmlNewNode (NULL, CC2XML ("mask")); snprintf (buffer, sizeof buffer, "mask%d", document->mask_id); xmlSetProp (mask_node, CC2XML ("id"), C2XML (buffer)); - emit_paint (mask_node, surface, op, mask); + child = xmlNewChild (mask_node, NULL, CC2XML ("g"), NULL); + xmlSetProp (child, CC2XML ("filter"), CC2XML ("url(#alpha)")); + emit_paint (child, surface, op, mask); + + xmlAddChild (document->xml_node_defs, mask_node); child = emit_paint (surface->xml_node, surface, op, source); @@ -1416,6 +1453,8 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, xmlSetProp (node, CC2XML ("xmlns:xlink"), CC2XML ("http://www.w3.org/1999/xlink")); xmlSetProp (node, CC2XML ("version"), CC2XML ("1.2")); + document->alpha_filter = FALSE; + return document; } From 3f84df97ddd639c9e1d3706be7c9c86eba22c5bb Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 18 Apr 2006 11:31:59 -0700 Subject: [PATCH 153/155] Enable real analysis for _cairo_pdf_surface_paint. After this patch we have three PDF tests passing with native output: clip-all fill-rule nil-surface --- src/cairo-pdf-surface.c | 61 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 9f4e5901a..836b3aebf 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -2038,6 +2038,55 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document, return CAIRO_STATUS_SUCCESS; } +static cairo_bool_t +_surface_pattern_supported (const cairo_surface_pattern_t *pattern) +{ + if (pattern->surface->backend->acquire_source_image != NULL) + return TRUE; + + return FALSE; +} + +static cairo_bool_t +_pattern_supported (const cairo_pattern_t *pattern) +{ + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) + return TRUE; + + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) + return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern); + + return FALSE; +} + +static cairo_int_status_t +_operation_supported (cairo_pdf_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern) +{ + if (! _pattern_supported (pattern)) + return FALSE; + + if (_cairo_operator_always_opaque (op)) + return TRUE; + + if (_cairo_operator_always_translucent (op)) + return FALSE; + + return _cairo_pattern_is_opaque (pattern); +} + +static cairo_int_status_t +_analyze_operation (cairo_pdf_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern) +{ + if (_operation_supported (surface, op, pattern)) + return CAIRO_STATUS_SUCCESS; + else + return CAIRO_INT_STATUS_UNSUPPORTED; +} + static cairo_int_status_t _cairo_pdf_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -2109,18 +2158,18 @@ _cairo_pdf_surface_fill (void *abstract_surface, cairo_status_t status; pdf_path_info_t info; - /* XXX: Temporarily disabling all "native" PDF output---will be - * switching to real analysis shortly. */ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_INT_STATUS_UNSUPPORTED; - ASSERT_NOT_REACHED; + return _analyze_operation (surface, op, source); + + assert (_operation_supported (surface, op, source)); status = emit_pattern (surface, source); if (status) return status; - /* After the above switch the current stream should belong to this - * surface, so no need to _cairo_pdf_surface_ensure_stream() */ + /* After emitting the pattern the current stream should belong to + * this surface, so no need to _cairo_pdf_surface_ensure_stream() + */ assert (document->current_stream != NULL && document->current_stream == surface->current_stream); From 36fb36fe8c4d8b2ac2b2de3f53842ae196bdca04 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Tue, 18 Apr 2006 21:22:58 +0200 Subject: [PATCH 154/155] SVG: Add validating ref file for unantialias tests. Antialias property is not directly supported by SVG, and probably not the most wanted feature. In the future, we could use an image fallback in order to emulate it, or try to use text-rendering, shape-rendering and image-rendering properties (http://www.w3.org/TR/SVG/painting.html#RenderingProperties). --- test/text-antialias-none-svg-argb32-ref.png | Bin 0 -> 1077 bytes test/text-antialias-none-svg-rgb24-ref.png | Bin 0 -> 1077 bytes test/text-antialias-subpixel-svg-argb32-ref.png | Bin 0 -> 1077 bytes test/text-antialias-subpixel-svg-rgb24-ref.png | Bin 0 -> 1077 bytes test/unantialiased-shapes-svg-argb32-ref.png | Bin 0 -> 19689 bytes test/unantialiased-shapes-svg-rgb24-ref.png | Bin 0 -> 19689 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/text-antialias-none-svg-argb32-ref.png create mode 100644 test/text-antialias-none-svg-rgb24-ref.png create mode 100644 test/text-antialias-subpixel-svg-argb32-ref.png create mode 100644 test/text-antialias-subpixel-svg-rgb24-ref.png create mode 100644 test/unantialiased-shapes-svg-argb32-ref.png create mode 100644 test/unantialiased-shapes-svg-rgb24-ref.png diff --git a/test/text-antialias-none-svg-argb32-ref.png b/test/text-antialias-none-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/text-antialias-none-svg-rgb24-ref.png b/test/text-antialias-none-svg-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/text-antialias-subpixel-svg-argb32-ref.png b/test/text-antialias-subpixel-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/text-antialias-subpixel-svg-rgb24-ref.png b/test/text-antialias-subpixel-svg-rgb24-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64fbbec5456e46ddb57013a3db267775b89003 GIT binary patch literal 1077 zcmV-51j_q~P){)8)eiP=ALJ9?T*8Y*2D9FU-&J~ z`JVgxo;U8j0J6QkE#c77(ILgf#bLR>#mdTx0AV=;XNV{OMNw#KYU1$lkg~Eeu3o(w zHh6GwkdcuQ+-^5Uqmhb=3L+yTb$)hsmfqf8*4Nj`%gdv(vNGh3{r!DfT3RS7D#8Fz zRaHfDaxw`C37AYKrlzLCinq77lb)WA(P*T-y&a3iqH{exJroueVlWuU&(CLke4PFL z{h;R+MZsh;v9+~Dc6K%Z($&?a&!MiaPRh&6|2T8E+bz-2(c<-bMMNYcBSU(6dQP1A z!oq@NXJ<=WTbs@S$nx^C?&$05lboEKu;Ny$RWdU(B`YgSj7FnGMn=l&>Z)vPYzQEm zo0}(!r=+9=3F`}YaB!fv#^dpjkdP44@_~T?Iy*a=oSbBSex9+hF#uFmB|bhLgTa8u z;|V)10IStXV`C#rOG~=X0MOmtt@U4ouC6W$3JO9Vb~>G;rlyjVlmtLWM+bhtAAs1{ zSPBXXXl-rP}_4SxcCg$emfTL}nnVF%aq=cQF9d>tjX>M)~5ic$- z#%i@a5#cy?Q}ZD<#Gv^FN?U{VHa9HeG+;4G(7izz_7Ro$3_!`y*+Tb zPTZmY3>VxT)(b~Z*D?$HN1Ltx_A`8qeoCvqd8(?;Kd7g_wLV` zAIJ0OaPJC|ku z8|?M~f9H;78;yaJn|pH0;i&TNZus_1Ta?k!z!DutObk4J3`Ip+bzi?iYHEOQXn+R~ z;O1ob+WE~7 v55wZ3)~Q>!;KGGd#6`64>RI4S|Ka`t^2;_OSJ$1000000NkvXXu0mjf*{c7q literal 0 HcmV?d00001 diff --git a/test/unantialiased-shapes-svg-argb32-ref.png b/test/unantialiased-shapes-svg-argb32-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..da297735bc10baba100133f0ab936f1854278c1a GIT binary patch literal 19689 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 Wb4fP~eP3_@0000 Date: Tue, 18 Apr 2006 21:52:06 +0200 Subject: [PATCH 155/155] Clear completely the temporary surface between each subtest in mask.c That helps SVG backend to pass this test, since CAIRO_OPERATOR_CLEAR on a part of a surface use "comp-op" element which is not supported with current librsvg. --- test/mask.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/mask.c b/test/mask.c index a9414e046..6d0e45878 100644 --- a/test/mask.c +++ b/test/mask.c @@ -213,12 +213,10 @@ draw (cairo_t *cr, int width, int height) int x = i * (WIDTH + PAD) + PAD; int y = (ARRAY_SIZE (mask_funcs) * k + j) * (HEIGHT + PAD) + PAD; - /* Clear area we are going to be drawing onto */ + /* Clear intermediate surface we are going to be drawing onto */ cairo_save (cr2); - cairo_set_source_rgba (cr2, 0, 0, 0, 0); /* transparent */ - cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE); - cairo_rectangle (cr2, x, y, WIDTH, HEIGHT); - cairo_fill (cr2); + cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr2); cairo_restore (cr2); /* draw */