From b22735849c3a1fb8f76f263d0c2d7ea48a1e03f0 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 5 Nov 2008 23:48:23 -0800 Subject: [PATCH] b=462938, Upgrade cairo to 1.8.2 and pixman to 0.12.0 [cairo piece] --- gfx/cairo/README | 6 +- gfx/cairo/cairo/src/Makefile.in | 2 + .../src/cairo-analysis-surface-private.h | 3 + gfx/cairo/cairo/src/cairo-analysis-surface.c | 170 +- gfx/cairo/cairo/src/cairo-array.c | 26 +- gfx/cairo/cairo/src/cairo-atomic-private.h | 13 +- gfx/cairo/cairo/src/cairo-atomic.c | 4 +- gfx/cairo/cairo/src/cairo-bentley-ottmann.c | 306 ++- gfx/cairo/cairo/src/cairo-cache.c | 3 +- gfx/cairo/cairo/src/cairo-clip.c | 28 +- gfx/cairo/cairo/src/cairo-color.c | 3 + gfx/cairo/cairo/src/cairo-compiler-private.h | 31 + gfx/cairo/cairo/src/cairo-directfb-surface.c | 2187 +++++++++-------- gfx/cairo/cairo/src/cairo-directfb.h | 2 +- gfx/cairo/cairo/src/cairo-features-win32.h | 14 - .../cairo/src/cairo-font-face-twin-data.c | 1030 ++++++++ gfx/cairo/cairo/src/cairo-font-face-twin.c | 209 ++ gfx/cairo/cairo/src/cairo-font-face.c | 71 +- gfx/cairo/cairo/src/cairo-font-options.c | 52 +- gfx/cairo/cairo/src/cairo-ft-font.c | 686 ++---- gfx/cairo/cairo/src/cairo-glitz-surface.c | 36 +- gfx/cairo/cairo/src/cairo-gstate.c | 89 +- gfx/cairo/cairo/src/cairo-hull.c | 31 +- gfx/cairo/cairo/src/cairo-image-surface.c | 49 +- gfx/cairo/cairo/src/cairo-matrix.c | 29 + .../cairo/src/cairo-meta-surface-private.h | 2 +- gfx/cairo/cairo/src/cairo-meta-surface.c | 46 +- gfx/cairo/cairo/src/cairo-misc.c | 4 +- .../cairo/src/cairo-mutex-impl-private.h | 29 +- .../cairo/src/cairo-mutex-list-private.h | 22 +- gfx/cairo/cairo/src/cairo-mutex-private.h | 6 +- .../cairo/src/cairo-mutex-type-private.h | 7 +- gfx/cairo/cairo/src/cairo-mutex.c | 6 +- gfx/cairo/cairo/src/cairo-no-features.h | 12 - gfx/cairo/cairo/src/cairo-os2-private.h | 6 +- gfx/cairo/cairo/src/cairo-os2-surface.c | 8 + .../cairo/src/cairo-output-stream-private.h | 4 + gfx/cairo/cairo/src/cairo-output-stream.c | 29 + gfx/cairo/cairo/src/cairo-paginated-private.h | 9 +- gfx/cairo/cairo/src/cairo-paginated-surface.c | 77 +- gfx/cairo/cairo/src/cairo-path-fill.c | 20 +- gfx/cairo/cairo/src/cairo-path-stroke.c | 168 +- gfx/cairo/cairo/src/cairo-pattern.c | 281 ++- .../cairo/src/cairo-pdf-operators-private.h | 2 +- gfx/cairo/cairo/src/cairo-pdf-operators.c | 42 +- .../cairo/src/cairo-pdf-surface-private.h | 2 +- gfx/cairo/cairo/src/cairo-pdf-surface.c | 148 +- gfx/cairo/cairo/src/cairo-png.c | 2 +- gfx/cairo/cairo/src/cairo-polygon.c | 71 +- .../cairo/src/cairo-ps-surface-private.h | 5 +- gfx/cairo/cairo/src/cairo-ps-surface.c | 159 +- gfx/cairo/cairo/src/cairo-quartz-font.c | 55 +- .../cairo/src/cairo-quartz-image-surface.c | 88 - gfx/cairo/cairo/src/cairo-quartz-private.h | 11 +- gfx/cairo/cairo/src/cairo-quartz-surface.c | 100 +- gfx/cairo/cairo/src/cairo-quartz.h | 4 +- .../cairo/src/cairo-reference-count-private.h | 8 - gfx/cairo/cairo/src/cairo-region-private.h | 8 +- .../src/cairo-scaled-font-subsets-private.h | 35 + .../cairo/src/cairo-scaled-font-subsets.c | 126 +- gfx/cairo/cairo/src/cairo-scaled-font.c | 229 +- gfx/cairo/cairo/src/cairo-skiplist.c | 16 +- gfx/cairo/cairo/src/cairo-slope.c | 20 +- .../src/cairo-surface-fallback-private.h | 2 + gfx/cairo/cairo/src/cairo-surface-fallback.c | 47 +- gfx/cairo/cairo/src/cairo-surface.c | 162 +- gfx/cairo/cairo/src/cairo-svg-surface.c | 343 ++- .../src/{cairo-win32.c => cairo-system.c} | 95 +- gfx/cairo/cairo/src/cairo-traps.c | 241 +- gfx/cairo/cairo/src/cairo-truetype-subset.c | 12 +- gfx/cairo/cairo/src/cairo-type1-fallback.c | 7 + gfx/cairo/cairo/src/cairo-type1-subset.c | 88 +- .../src/cairo-type3-glyph-surface-private.h | 14 +- .../cairo/src/cairo-type3-glyph-surface.c | 146 +- gfx/cairo/cairo/src/cairo-types-private.h | 21 +- gfx/cairo/cairo/src/cairo-unicode.c | 6 +- gfx/cairo/cairo/src/cairo-user-font.c | 217 +- gfx/cairo/cairo/src/cairo-wideint-private.h | 21 +- .../cairo/src/cairo-wideint-type-private.h | 2 + gfx/cairo/cairo/src/cairo-wideint.c | 48 + gfx/cairo/cairo/src/cairo-win32-font.c | 17 +- .../cairo/src/cairo-win32-printing-surface.c | 49 +- gfx/cairo/cairo/src/cairo-win32-private.h | 2 + gfx/cairo/cairo/src/cairo-win32-surface.c | 52 +- gfx/cairo/cairo/src/cairo-win32.h | 8 + gfx/cairo/cairo/src/cairo-xcb-surface.c | 285 ++- gfx/cairo/cairo/src/cairo-xlib-screen.c | 28 - gfx/cairo/cairo/src/cairo-xlib-surface.c | 409 ++- gfx/cairo/cairo/src/cairo.c | 73 +- gfx/cairo/cairo/src/cairo.h | 127 +- gfx/cairo/cairo/src/cairoint.h | 204 +- gfx/cairo/cairo/src/test-fallback-surface.c | 4 + gfx/cairo/cairo/src/test-meta-surface.c | 63 +- gfx/cairo/cairo/src/test-paginated-surface.c | 44 +- gfx/cairo/nonfatal-assertions.patch | 4 +- 95 files changed, 6090 insertions(+), 3698 deletions(-) delete mode 100644 gfx/cairo/cairo/src/cairo-features-win32.h create mode 100644 gfx/cairo/cairo/src/cairo-font-face-twin-data.c create mode 100644 gfx/cairo/cairo/src/cairo-font-face-twin.c delete mode 100644 gfx/cairo/cairo/src/cairo-no-features.h rename gfx/cairo/cairo/src/{cairo-win32.c => cairo-system.c} (58%) diff --git a/gfx/cairo/README b/gfx/cairo/README index 8b03ef67a85c..3a09edf8e1d2 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -7,8 +7,8 @@ http://www.cairographics.org/. VERSIONS: - cairo (1.7.4-136-g5ea2555) - pixman (pixman-0.11.10-8-g7180230) + cairo (1.8.2) + pixman (pixman-0.12.0-19-g95f2af9) ***** NOTE FOR VISUAL C++ 6.0 ***** @@ -28,6 +28,8 @@ buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions. +cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds + ==== pixman patches ==== endian.patch: include cairo-platform.h for endian macros diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index 446127b32b68..f02daea3da51 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -85,6 +85,8 @@ CSRCS = \ cairo-deflate-stream.c \ cairo-fixed.c \ cairo-font-face.c \ + cairo-font-face-twin.c \ + cairo-font-face-twin-data.c \ cairo-font-options.c \ cairo-freelist.c \ cairo-gstate.c \ diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h index b756a4b5ac2e..28bfd3bf437b 100644 --- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h @@ -66,6 +66,9 @@ cairo_private void _cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface, cairo_box_t *bbox); +cairo_private cairo_int_status_t +_cairo_analysis_surface_merge_status (cairo_int_status_t status_a, + cairo_int_status_t status_b); cairo_private cairo_surface_t * _cairo_null_surface_create (cairo_content_t content); diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface.c b/gfx/cairo/cairo/src/cairo-analysis-surface.c index c9f3e853a965..5093459b03dc 100644 --- a/gfx/cairo/cairo/src/cairo-analysis-surface.c +++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c @@ -62,9 +62,41 @@ typedef struct { } cairo_analysis_surface_t; +cairo_int_status_t +_cairo_analysis_surface_merge_status (cairo_int_status_t status_a, + cairo_int_status_t status_b) +{ + /* fatal errors should be checked and propagated at source */ + assert (! _cairo_status_is_error (status_a)); + assert (! _cairo_status_is_error (status_b)); + + /* return the most important status */ + if (status_a == CAIRO_INT_STATUS_UNSUPPORTED || + status_b == CAIRO_INT_STATUS_UNSUPPORTED) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK || + status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK) + return CAIRO_INT_STATUS_IMAGE_FALLBACK; + + if (status_a == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN || + status_b == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) + return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; + + if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY || + status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) + return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; + + /* at this point we have checked all the valid internal codes, so... */ + assert (status_a == CAIRO_STATUS_SUCCESS && + status_b == CAIRO_STATUS_SUCCESS); + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t -_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface, - cairo_pattern_t *pattern) +_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface, + cairo_pattern_t *pattern) { cairo_surface_t *analysis = &surface->base; cairo_surface_pattern_t *surface_pattern; @@ -118,9 +150,9 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t * } static cairo_int_status_t -_cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface, - cairo_rectangle_int_t *rect, - cairo_int_status_t backend_status) +_add_operation (cairo_analysis_surface_t *surface, + cairo_rectangle_int_t *rect, + cairo_int_status_t backend_status) { cairo_int_status_t status; cairo_box_t bbox; @@ -302,8 +334,7 @@ _cairo_analysis_surface_paint (void *abstract_surface, source); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); + backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -320,7 +351,7 @@ _cairo_analysis_surface_paint (void *abstract_surface, _cairo_rectangle_intersect (&extents, &surface->current_clip); - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -332,7 +363,7 @@ _cairo_analysis_surface_mask (void *abstract_surface, cairo_pattern_t *mask) { cairo_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; + cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents; if (!surface->target->backend->mask) @@ -342,25 +373,32 @@ _cairo_analysis_surface_mask (void *abstract_surface, source, mask); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) { + cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; + cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; - if (_cairo_surface_is_meta (surface_pattern->surface)) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); - if (backend_status != CAIRO_STATUS_SUCCESS && - backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK) - return backend_status; + if (_cairo_surface_is_meta (surface_pattern->surface)) { + backend_source_status = + _analyze_meta_surface_pattern (surface, source); + if (_cairo_status_is_error (backend_source_status)) + return backend_source_status; + } } if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; - if (_cairo_surface_is_meta (surface_pattern->surface)) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - mask); - if (backend_status != CAIRO_STATUS_SUCCESS && - backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK) - return backend_status; + if (_cairo_surface_is_meta (surface_pattern->surface)) { + backend_mask_status = + _analyze_meta_surface_pattern (surface, mask); + if (_cairo_status_is_error (backend_mask_status)) + return backend_mask_status; + } } + + backend_status = + _cairo_analysis_surface_merge_status (backend_source_status, + backend_mask_status); } status = _cairo_surface_get_extents (&surface->base, &extents); @@ -384,7 +422,7 @@ _cairo_analysis_surface_mask (void *abstract_surface, _cairo_rectangle_intersect (&extents, &surface->current_clip); - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -403,7 +441,6 @@ _cairo_analysis_surface_stroke (void *abstract_surface, cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_traps_t traps; - cairo_box_t box; cairo_rectangle_int_t extents; if (!surface->target->backend->stroke) @@ -415,8 +452,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface, tolerance, antialias); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); + backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -434,10 +470,9 @@ _cairo_analysis_surface_stroke (void *abstract_surface, _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { - box.p1.x = _cairo_fixed_from_int (extents.x); - box.p1.y = _cairo_fixed_from_int (extents.y); - box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); - box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); + cairo_box_t box; + + _cairo_box_from_rectangle (&box, &extents); _cairo_traps_init (&traps); _cairo_traps_limit (&traps, &box); @@ -451,22 +486,13 @@ _cairo_analysis_surface_stroke (void *abstract_surface, return status; } - if (traps.num_traps == 0) { - extents.x = 0; - extents.y = 0; - extents.width = 0; - extents.height = 0; - } else { - _cairo_traps_extents (&traps, &box); - extents.x = _cairo_fixed_integer_floor (box.p1.x); - extents.y = _cairo_fixed_integer_floor (box.p1.y); - extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x; - extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y; - } + _cairo_traps_extents (&traps, &box); _cairo_traps_fini (&traps); + + _cairo_box_round_to_rectangle (&box, &extents); } - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -483,7 +509,6 @@ _cairo_analysis_surface_fill (void *abstract_surface, cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_traps_t traps; - cairo_box_t box; cairo_rectangle_int_t extents; if (!surface->target->backend->fill) @@ -494,8 +519,7 @@ _cairo_analysis_surface_fill (void *abstract_surface, tolerance, antialias); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); + backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -513,10 +537,9 @@ _cairo_analysis_surface_fill (void *abstract_surface, _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { - box.p1.x = _cairo_fixed_from_int (extents.x); - box.p1.y = _cairo_fixed_from_int (extents.y); - box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); - box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); + cairo_box_t box; + + _cairo_box_from_rectangle (&box, &extents); _cairo_traps_init (&traps); _cairo_traps_limit (&traps, &box); @@ -529,23 +552,13 @@ _cairo_analysis_surface_fill (void *abstract_surface, return status; } - if (traps.num_traps == 0) { - extents.x = 0; - extents.y = 0; - extents.width = 0; - extents.height = 0; - } else { - _cairo_traps_extents (&traps, &box); - extents.x = _cairo_fixed_integer_floor (box.p1.x); - extents.y = _cairo_fixed_integer_floor (box.p1.y); - extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x; - extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y; - } - + _cairo_traps_extents (&traps, &box); _cairo_traps_fini (&traps); + + _cairo_box_round_to_rectangle (&box, &extents); } - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -582,8 +595,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); + backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -611,7 +623,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, _cairo_rectangle_intersect (&extents, &glyph_extents); } - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -634,7 +646,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_analysis_surface_t *surface = abstract_surface; @@ -648,8 +660,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, source, utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - backward, + clusters, num_clusters, cluster_flags, scaled_font); if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) { int remaining_glyphs = num_glyphs; @@ -665,8 +676,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, } if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface, - source); + backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -694,7 +704,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, _cairo_rectangle_intersect (&extents, &glyph_extents); } - status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status); + status = _add_operation (surface, &extents, backend_status); return status; } @@ -742,6 +752,11 @@ _cairo_analysis_surface_create (cairo_surface_t *target, int height) { cairo_analysis_surface_t *surface; + cairo_status_t status; + + status = target->status; + if (status) + return _cairo_surface_create_in_error (status); surface = malloc (sizeof (cairo_analysis_surface_t)); if (surface == NULL) @@ -785,17 +800,22 @@ _cairo_analysis_surface_create (cairo_surface_t *target, return &surface->base; } -cairo_private void +void _cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface, cairo_matrix_t *ctm) { - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; + cairo_analysis_surface_t *surface; + + if (abstract_surface->status) + return; + + surface = (cairo_analysis_surface_t *) abstract_surface; surface->ctm = *ctm; surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); } -cairo_private void +void _cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface, cairo_matrix_t *ctm) { diff --git a/gfx/cairo/cairo/src/cairo-array.c b/gfx/cairo/cairo/src/cairo-array.c index 1b2c9032124c..b2790c8a1521 100644 --- a/gfx/cairo/cairo/src/cairo-array.c +++ b/gfx/cairo/cairo/src/cairo-array.c @@ -85,6 +85,7 @@ _cairo_array_init_snapshot (cairo_array_t *array, /** * _cairo_array_fini: + * @array: A #cairo_array_t * * Free all resources associated with @array. After this call, @array * should not be used again without a subsequent call to @@ -104,6 +105,7 @@ _cairo_array_fini (cairo_array_t *array) /** * _cairo_array_grow_by: + * @array: a #cairo_array_t * * Increase the size of @array (if needed) so that there are at least * @additional free spaces in the array. The actual size of the array @@ -158,6 +160,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional) /** * _cairo_array_truncate: + * @array: a #cairo_array_t * * Truncate size of the array to @num_elements if less than the * current size. No memory is actually freed. The stored objects @@ -174,14 +177,16 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) /** * _cairo_array_index: + * @array: a #cairo_array_t + * Returns: A pointer to the object stored at @index. * - * Return value: A pointer to object stored at @index. If the - * resulting value is assigned to a pointer to an object of the same + * If the resulting value is assigned to a pointer to an object of the same * element_size as initially passed to _cairo_array_init() then that * pointer may be used for further direct indexing with []. For * example: * - * #cairo_array_t array; + * + * cairo_array_t array; * double *values; * * _cairo_array_init (&array, sizeof(double)); @@ -190,6 +195,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) * values = _cairo_array_index (&array, 0); * for (i = 0; i < _cairo_array_num_elements (&array); i++) * ... use values[i] here ... + * **/ void * _cairo_array_index (cairo_array_t *array, unsigned int index) @@ -215,6 +221,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index) /** * _cairo_array_copy_element: + * @array: a #cairo_array_t * * Copy a single element out of the array from index @index into the * location pointed to by @dst. @@ -227,6 +234,7 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst) /** * _cairo_array_append: + * @array: a #cairo_array_t * * Append a single item onto the array by growing the array by at * least one element, then copying element_size bytes from @element @@ -250,6 +258,7 @@ _cairo_array_append (cairo_array_t *array, /** * _cairo_array_append: + * @array: a #cairo_array_t * * Append one or more items onto the array by growing the array by * @num_elements, then copying @num_elements * element_size bytes from @@ -280,6 +289,7 @@ _cairo_array_append_multiple (cairo_array_t *array, /** * _cairo_array_allocate: + * @array: a #cairo_array_t * * Allocate space at the end of the array for @num_elements additional * elements, providing the address of the new memory chunk in @@ -314,8 +324,10 @@ _cairo_array_allocate (cairo_array_t *array, /** * _cairo_array_num_elements: + * @array: a #cairo_array_t + * Returns: The number of elements stored in @array. * - * Return value: The number of elements stored in @array. + * This space was left intentionally blank, but gtk-doc filled it. **/ int _cairo_array_num_elements (cairo_array_t *array) @@ -325,9 +337,11 @@ _cairo_array_num_elements (cairo_array_t *array) /** * _cairo_array_size: + * @array: a #cairo_array_t + * Returns: The number of elements for which there is currently space + * allocated in @array. * - * Return value: The number of elements for which there is currently - * space allocated in array. + * This space was left intentionally blank, but gtk-doc filled it. **/ int _cairo_array_size (cairo_array_t *array) diff --git a/gfx/cairo/cairo/src/cairo-atomic-private.h b/gfx/cairo/cairo/src/cairo-atomic-private.h index 85fe95626a33..2914a0221880 100644 --- a/gfx/cairo/cairo/src/cairo-atomic-private.h +++ b/gfx/cairo/cairo/src/cairo-atomic-private.h @@ -37,15 +37,17 @@ #ifndef CAIRO_ATOMIC_PRIVATE_H #define CAIRO_ATOMIC_PRIVATE_H +# include "cairo-compiler-private.h" + #if HAVE_CONFIG_H #include "config.h" #endif CAIRO_BEGIN_DECLS -#define CAIRO_HAS_ATOMIC_OPS 1 +#if HAVE_INTEL_ATOMIC_PRIMITIVES -#if CAIRO_HAS_INTEL_ATOMIC_PRIMITIVES +#define HAS_ATOMIC_OPS 1 typedef int cairo_atomic_int_t; @@ -53,11 +55,10 @@ typedef int cairo_atomic_int_t; # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1) # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv) -#else +#endif -# include "cairo-compiler-private.h" -# undef CAIRO_HAS_ATOMIC_OPS +#ifndef HAS_ATOMIC_OPS typedef int cairo_atomic_int_t; @@ -73,7 +74,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv); #endif -#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER +#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER # include "cairo-compiler-private.h" diff --git a/gfx/cairo/cairo/src/cairo-atomic.c b/gfx/cairo/cairo/src/cairo-atomic.c index 9e388ac1a8f0..c569000cb581 100644 --- a/gfx/cairo/cairo/src/cairo-atomic.c +++ b/gfx/cairo/cairo/src/cairo-atomic.c @@ -36,7 +36,7 @@ #include "cairo-atomic-private.h" #include "cairo-mutex-private.h" -#ifndef CAIRO_HAS_ATOMIC_OPS +#ifndef HAS_ATOMIC_OPS void _cairo_atomic_int_inc (int *x) { @@ -73,7 +73,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv) #endif -#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER +#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER int _cairo_atomic_int_get (int *x) { diff --git a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c index 8e97f1fd5d49..c657dd9cdb80 100644 --- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c +++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c @@ -39,6 +39,9 @@ #include "cairo-skiplist-private.h" #include "cairo-freelist-private.h" +#define DEBUG_VALIDATE 0 +#define DEBUG_PRINT_STATE 0 + typedef cairo_point_t cairo_bo_point32_t; typedef struct _cairo_bo_point128 { @@ -198,60 +201,163 @@ _slope_compare (cairo_bo_edge_t *a, * with respect to x. */ if ((adx ^ bdx) < 0) { return adx < 0 ? -1 : +1; - } - else { + } else { int32_t ady = a->bottom.y - a->top.y; int32_t bdy = b->bottom.y - b->top.y; - int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy); - int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady); + cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy); + cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady); - /* if (adx * bdy > bdx * ady) */ - if (_cairo_int64_gt (adx_bdy, bdx_ady)) - return 1; - - /* if (adx * bdy < bdx * ady) */ - if (_cairo_int64_lt (adx_bdy, bdx_ady)) - return -1; - return 0; + return _cairo_int64_cmp (adx_bdy, bdx_ady); } } -static cairo_quorem64_t -edge_x_for_y (cairo_bo_edge_t *edge, - int32_t y) +/* + * We need to compare the x-coordinates of a pair of lines for a particular y, + * without loss of precision. + * + * The x-coordinate along an edge for a given y is: + * X = A_x + (Y - A_y) * A_dx / A_dy + * + * So the inequality we wish to test is: + * A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy, + * where -?- is our inequality operator. + * + * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are + * all positive, so we can rearrange it thus without causing a sign change: + * A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy + * - (Y - A_y) * A_dx * B_dy + * + * Given the assumption that all the deltas fit within 32 bits, we can compute + * this comparison directly using 128 bit arithmetic. + * + * (And put the burden of the work on developing fast 128 bit ops, which are + * required throughout the tessellator.) + * + * See the similar discussion for _slope_compare(). + */ +static int +edges_compare_x_for_y_general (const cairo_bo_edge_t *a, + const cairo_bo_edge_t *b, + int32_t y) { /* XXX: We're assuming here that dx and dy will still fit in 32 * bits. That's not true in general as there could be overflow. We * should prevent that before the tessellation algorithm * begins. */ - int32_t dx = edge->bottom.x - edge->top.x; - int32_t dy = edge->bottom.y - edge->top.y; - int64_t numerator; - cairo_quorem64_t quorem; + int32_t adx, ady; + int32_t bdx, bdy; + cairo_int128_t L, R; - if (edge->middle.y == y) { - quorem.quo = edge->middle.x; - quorem.rem = 0; - return quorem; - } - if (edge->bottom.y == y) { - quorem.quo = edge->bottom.x; - quorem.rem = 0; - return quorem; - } - if (dy == 0) { - quorem.quo = _cairo_int32_to_int64 (edge->top.x); - quorem.rem = 0; - return quorem; - } + adx = a->bottom.x - a->top.x; + ady = a->bottom.y - a->top.y; - /* edge->top.x + (y - edge->top.y) * dx / dy */ - numerator = _cairo_int32x32_64_mul ((y - edge->top.y), dx); - quorem = _cairo_int64_divrem (numerator, dy); - quorem.quo += edge->top.x; + bdx = b->bottom.x - b->top.x; + bdy = b->bottom.y - b->top.y; - return quorem; + L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), + a->top.x - b->top.x); + + R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, + ady), + y - b->top.y), + _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, + bdy), + y - a->top.y)); + + /* return _cairo_int128_cmp (L, R); */ + if (_cairo_int128_lt (L, R)) + return -1; + if (_cairo_int128_gt (L, R)) + return 1; + return 0; +} + +/* + * We need to compare the x-coordinate of a line for a particular y wrt to a + * given x, without loss of precision. + * + * The x-coordinate along an edge for a given y is: + * X = A_x + (Y - A_y) * A_dx / A_dy + * + * So the inequality we wish to test is: + * A_x + (Y - A_y) * A_dx / A_dy -?- X + * where -?- is our inequality operator. + * + * By construction, we know that A_dy (and (Y - A_y)) are + * all positive, so we can rearrange it thus without causing a sign change: + * (Y - A_y) * A_dx -?- (X - A_x) * A_dy + * + * Given the assumption that all the deltas fit within 32 bits, we can compute + * this comparison directly using 64 bit arithmetic. + * + * See the similar discussion for _slope_compare() and + * edges_compare_x_for_y_general(). + */ +static int +edge_compare_for_y_against_x (const cairo_bo_edge_t *a, + int32_t y, + int32_t x) +{ + int32_t adx, ady; + int32_t dx, dy; + cairo_int64_t L, R; + + adx = a->bottom.x - a->top.x; + ady = a->bottom.y - a->top.y; + + dy = y - a->top.y; + dx = x - a->top.x; + + L = _cairo_int32x32_64_mul (dy, adx); + R = _cairo_int32x32_64_mul (dx, ady); + + return _cairo_int64_cmp (L, R); +} + +static int +edges_compare_x_for_y (const cairo_bo_edge_t *a, + const cairo_bo_edge_t *b, + int32_t y) +{ + /* If the sweep-line is currently on an end-point of a line, + * then we know its precise x value (and considering that we often need to + * compare events at end-points, this happens frequently enough to warrant + * special casing). + */ + enum { + HAVE_NEITHER = 0x0, + HAVE_AX = 0x1, + HAVE_BX = 0x2, + HAVE_BOTH = HAVE_AX | HAVE_BX + } have_ax_bx = HAVE_BOTH; + int32_t ax, bx; + + if (y == a->top.y) + ax = a->top.x; + else if (y == a->bottom.y) + ax = a->bottom.x; + else + have_ax_bx &= ~HAVE_AX; + + if (y == b->top.y) + bx = b->top.x; + else if (y == b->bottom.y) + bx = b->bottom.x; + else + have_ax_bx &= ~HAVE_BX; + + switch (have_ax_bx) { + default: + case HAVE_NEITHER: + return edges_compare_x_for_y_general (a, b, y); + case HAVE_AX: + return - edge_compare_for_y_against_x (b, y, ax); + case HAVE_BX: + return edge_compare_for_y_against_x (a, y, bx); + case HAVE_BOTH: + return ax - bx; + } } static int @@ -259,8 +365,6 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line, cairo_bo_edge_t *a, cairo_bo_edge_t *b) { - cairo_quorem64_t ax; - cairo_quorem64_t bx; int cmp; if (a == b) @@ -289,18 +393,9 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line, if (amin > bmax) return +1; } - ax = edge_x_for_y (a, sweep_line->current_y); - bx = edge_x_for_y (b, sweep_line->current_y); - if (ax.quo > bx.quo) - return 1; - else if (ax.quo < bx.quo) - return -1; - - /* Quotients are identical, test remainder. */ - if (ax.rem > bx.rem) - return 1; - else if (ax.rem < bx.rem) - return -1; + cmp = edges_compare_x_for_y (a, b, sweep_line->current_y); + if (cmp) + return cmp; /* The two edges intersect exactly at y, so fall back on slope * comparison. We know that this compare_edges function will be @@ -489,17 +584,17 @@ det32_64 (int32_t a, } static inline cairo_int128_t -det64_128 (cairo_int64_t a, - cairo_int64_t b, - cairo_int64_t c, - cairo_int64_t d) +det64x32_128 (cairo_int64_t a, + int32_t b, + cairo_int64_t c, + int32_t d) { cairo_int128_t ad; cairo_int128_t bc; /* det = a * d - b * c */ - ad = _cairo_int64x64_128_mul (a, d); - bc = _cairo_int64x64_128_mul (b, c); + ad = _cairo_int64x32_128_mul (a, d); + bc = _cairo_int64x32_128_mul (c, b); return _cairo_int128_sub (ad, bc); } @@ -532,7 +627,7 @@ intersect_lines (cairo_bo_edge_t *a, cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2); cairo_quorem64_t qr; - if (_cairo_int64_eq (den_det, 0)) + if (_cairo_int64_is_zero (den_det)) return CAIRO_BO_STATUS_PARALLEL; a_det = det32_64 (a->top.x, a->top.y, @@ -541,22 +636,22 @@ intersect_lines (cairo_bo_edge_t *a, b->bottom.x, b->bottom.y); /* x = det (a_det, dx1, b_det, dx2) / den_det */ - qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dx1, - b_det, dx2), - den_det); - if (_cairo_int64_eq (qr.rem,den_det)) - return CAIRO_BO_STATUS_NO_INTERSECTION; - intersection->x.ordinate = qr.quo; - intersection->x.exactness = qr.rem ? INEXACT : EXACT; - - /* y = det (a_det, dy1, b_det, dy2) / den_det */ - qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dy1, - b_det, dy2), + qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1, + b_det, dx2), den_det); if (_cairo_int64_eq (qr.rem, den_det)) return CAIRO_BO_STATUS_NO_INTERSECTION; - intersection->y.ordinate = qr.quo; - intersection->y.exactness = qr.rem ? INEXACT : EXACT; + intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo); + intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT; + + /* y = det (a_det, dy1, b_det, dy2) / den_det */ + qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1, + b_det, dy2), + den_det); + if (_cairo_int64_eq (qr.rem, den_det)) + return CAIRO_BO_STATUS_NO_INTERSECTION; + intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo); + intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT; return CAIRO_BO_STATUS_INTERSECTION; } @@ -941,7 +1036,6 @@ _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line, left->prev = right; } -#define DEBUG_PRINT_STATE 0 #if DEBUG_PRINT_STATE static void _cairo_bo_edge_print (cairo_bo_edge_t *edge) @@ -1078,35 +1172,35 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left, /* Only emit trapezoids with positive height. */ if (fixed_top < fixed_bot) { - cairo_point_t left_top, left_bot, right_top, right_bot; + cairo_line_t left_line; + cairo_line_t right_line; cairo_fixed_t xmin = bo_traps->xmin; cairo_fixed_t ymin = bo_traps->ymin; fixed_top += ymin; fixed_bot += ymin; - left_top.x = left->top.x + xmin; - left_top.y = left->top.y + ymin; - right_top.x = right->top.x + xmin; - right_top.y = right->top.y + ymin; - left_bot.x = left->bottom.x + xmin; - left_bot.y = left->bottom.y + ymin; - right_bot.x = right->bottom.x + xmin; - right_bot.y = right->bottom.y + ymin; + left_line.p1.x = left->top.x + xmin; + left_line.p1.y = left->top.y + ymin; + right_line.p1.x = right->top.x + xmin; + right_line.p1.y = right->top.y + ymin; + + left_line.p2.x = left->bottom.x + xmin; + left_line.p2.y = left->bottom.y + ymin; + right_line.p2.x = right->bottom.x + xmin; + right_line.p2.y = right->bottom.y + ymin; /* Avoid emitting the trapezoid if it is obviously degenerate. * TODO: need a real collinearity test here for the cases * where the trapezoid is degenerate, yet the top and bottom * coordinates aren't equal. */ - if (left_top.x != right_top.x || - left_top.y != right_top.y || - left_bot.x != right_bot.x || - left_bot.y != right_bot.y) + if (left_line.p1.x != right_line.p1.x || + left_line.p1.y != right_line.p1.y || + left_line.p2.x != right_line.p2.x || + left_line.p2.y != right_line.p2.y) { - _cairo_traps_add_trap_from_points (bo_traps->traps, - fixed_top, - fixed_bot, - left_top, left_bot, - right_top, right_bot); + _cairo_traps_add_trap (bo_traps->traps, + fixed_top, fixed_bot, + &left_line, &right_line); #if DEBUG_PRINT_STATE printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) " @@ -1177,6 +1271,7 @@ _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps) _cairo_freelist_fini (&bo_traps->freelist); } +#if DEBUG_VALIDATE static void _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line) { @@ -1193,15 +1288,16 @@ _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line) { if (SKIP_ELT_TO_EDGE (elt) != edge) { fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n"); - exit (1); + abort (); } } if (edge || elt) { fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n"); - exit (1); + abort (); } } +#endif static cairo_status_t @@ -1324,9 +1420,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges, #if DEBUG_PRINT_STATE print_state ("After processing start", &event_queue, &sweep_line); #endif - _cairo_bo_sweep_line_validate (&sweep_line); - break; + case CAIRO_BO_EVENT_TYPE_STOP: edge = event->e1; @@ -1346,9 +1441,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges, #if DEBUG_PRINT_STATE print_state ("After processing stop", &event_queue, &sweep_line); #endif - _cairo_bo_sweep_line_validate (&sweep_line); - break; + case CAIRO_BO_EVENT_TYPE_INTERSECTION: edge1 = event->e1; edge2 = event->e2; @@ -1382,10 +1476,11 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges, #if DEBUG_PRINT_STATE print_state ("After processing intersection", &event_queue, &sweep_line); #endif - _cairo_bo_sweep_line_validate (&sweep_line); - break; } +#if DEBUG_VALIDATE + _cairo_bo_sweep_line_validate (&sweep_line); +#endif } *num_intersections = intersection_count; @@ -1427,12 +1522,16 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, cairo_fixed_t ymin = 0x7FFFFFFF; cairo_fixed_t xmax = -0x80000000; cairo_fixed_t ymax = -0x80000000; + cairo_box_t limit; + cairo_bool_t has_limits; int num_bo_edges; int i; if (0 == polygon->num_edges) return CAIRO_STATUS_SUCCESS; + has_limits = _cairo_traps_get_limit (traps, &limit); + if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) { edges = stack_edges; } else { @@ -1471,6 +1570,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, cairo_point_t top = polygon->edges[i].edge.p1; cairo_point_t bot = polygon->edges[i].edge.p2; + /* Discard the edge if it lies outside the limits of traps. */ + if (has_limits) { + /* Strictly above or below the limits? */ + if (bot.y <= limit.p1.y || top.y >= limit.p2.y) + continue; + } + /* Offset coordinates into the non-negative range. */ top.x -= xmin; top.y -= ymin; diff --git a/gfx/cairo/cairo/src/cairo-cache.c b/gfx/cairo/cairo/src/cairo-cache.c index a9823d129a2c..1c458dff32ef 100644 --- a/gfx/cairo/cairo/src/cairo-cache.c +++ b/gfx/cairo/cairo/src/cairo-cache.c @@ -92,6 +92,7 @@ _cairo_cache_fini (cairo_cache_t *cache) * @keys_equal: a function to return %TRUE if two keys are equal * @entry_destroy: destroy notifier for cache entries * @max_size: the maximum size for this cache + * Returns: the newly created #cairo_cache_t * * Creates a new cache using the keys_equal() function to determine * the equality of entries. @@ -119,8 +120,6 @@ _cairo_cache_fini (cairo_cache_t *cache) * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be * used to establish a window during which no automatic removal of * entries will occur. - * - * Return value: **/ cairo_cache_t * _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, diff --git a/gfx/cairo/cairo/src/cairo-clip.c b/gfx/cairo/cairo/src/cairo-clip.c index 5de3667d0960..308da326c85d 100644 --- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -148,7 +148,10 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, cairo_box_t extents; cairo_rectangle_int_t extents_rect; + _cairo_box_from_rectangle (&extents, rectangle); + _cairo_traps_init (&traps); + _cairo_traps_limit (&traps, &extents); status = _cairo_path_fixed_fill_to_traps (&clip_path->path, clip_path->fill_rule, @@ -160,11 +163,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, } _cairo_traps_extents (&traps, &extents); + _cairo_traps_fini (&traps); + _cairo_box_round_to_rectangle (&extents, &extents_rect); _cairo_rectangle_intersect (rectangle, &extents_rect); - _cairo_traps_fini (&traps); - clip_path = clip_path->prev; } @@ -436,9 +439,8 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip, /* Intersect with the target surface rectangle so we don't use * more memory and time than we need to. */ - status = _cairo_surface_get_extents (target, &target_rect); - if (!status) + if (status == CAIRO_STATUS_SUCCESS) _cairo_rectangle_intersect (&surface_rect, &target_rect); if (surface_rect.width == 0 || surface_rect.height == 0) { @@ -561,6 +563,7 @@ _cairo_clip_clip (cairo_clip_t *clip, cairo_surface_t *target) { cairo_status_t status; + cairo_rectangle_int_t rectangle; cairo_traps_t traps; if (clip->all_clipped) @@ -582,6 +585,17 @@ _cairo_clip_clip (cairo_clip_t *clip, return status; _cairo_traps_init (&traps); + + /* Limit the traps to the target surface + * - so we don't add more traps than needed. */ + status = _cairo_surface_get_extents (target, &rectangle); + if (status == CAIRO_STATUS_SUCCESS) { + cairo_box_t box; + + _cairo_box_from_rectangle (&box, &rectangle); + _cairo_traps_limit (&traps, &box); + } + status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, @@ -676,16 +690,22 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip, } if (other->surface) { + int dx, dy; status = _cairo_surface_clone_similar (target, other->surface, 0, 0, other->surface_rect.width, other->surface_rect.height, + &dx, &dy, &clip->surface); if (status) goto BAIL; clip->surface_rect = other->surface_rect; + + /* src offset was 0, so we expect an exact replica of the surface */ + assert (dx == 0); + assert (dy == 0); } if (other->path) { diff --git a/gfx/cairo/cairo/src/cairo-color.c b/gfx/cairo/cairo/src/cairo-color.c index 50a9a1c26d3d..7640bf43621d 100644 --- a/gfx/cairo/cairo/src/cairo-color.c +++ b/gfx/cairo/cairo/src/cairo-color.c @@ -165,6 +165,9 @@ cairo_bool_t _cairo_color_equal (const cairo_color_t *color_a, const cairo_color_t *color_b) { + if (color_a == color_b) + return TRUE; + return color_a->red_short == color_b->red_short && color_a->green_short == color_b->green_short && color_a->blue_short == color_b->blue_short && diff --git a/gfx/cairo/cairo/src/cairo-compiler-private.h b/gfx/cairo/cairo/src/cairo-compiler-private.h index 295b5875bfb8..b93fd82982f2 100644 --- a/gfx/cairo/cairo/src/cairo-compiler-private.h +++ b/gfx/cairo/cairo/src/cairo-compiler-private.h @@ -38,6 +38,8 @@ #ifndef CAIRO_COMPILER_PRIVATE_H #define CAIRO_COMPILER_PRIVATE_H +#include "cairo.h" + #if HAVE_CONFIG_H #include "config.h" #endif @@ -109,6 +111,34 @@ # define CAIRO_FUNCTION_ALIAS(old, new) #endif +/* + * Cairo uses the following function attributes in order to improve the + * generated code (effectively by manual inter-procedural analysis). + * + * 'cairo_pure': The function is only allowed to read from its arguments + * and global memory (i.e. following a pointer argument or + * accessing a shared variable). The return value should + * only depend on its arguments, and for an identical set of + * arguments should return the same value. + * + * 'cairo_const': The function is only allowed to read from its arguments. + * It is not allowed to access global memory. The return + * value should only depend its arguments, and for an + * identical set of arguments should return the same value. + * This is currently the most strict function attribute. + * + * Both these function attributes allow gcc to perform CSE and + * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents + * do not change across the function call. + */ +#if __GNUC__ >= 3 +#define cairo_pure __attribute__((pure)) +#define cairo_const __attribute__((const)) +#else +#define cairo_pure +#define cairo_const +#endif + #ifndef __GNUC__ #undef __attribute__ #define __attribute__(x) @@ -116,6 +146,7 @@ #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) #define snprintf _snprintf +#define popen _popen #endif #ifdef _MSC_VER diff --git a/gfx/cairo/cairo/src/cairo-directfb-surface.c b/gfx/cairo/cairo/src/cairo-directfb-surface.c index ecfc0f494cc6..aa67b023bb33 100644 --- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c @@ -34,19 +34,17 @@ * Michael Emmel * Claudio Ciccani */ - #include "cairoint.h" #include "cairo-directfb.h" -#include - #include #include #include #include #include +#include "cairo-clip-private.h" /* * Rectangle works fine. @@ -58,7 +56,7 @@ /* * Composite works fine. */ -#define DFB_COMPOSITE 1 +#define DFB_COMPOSITE 1 /* * CompositeTrapezoids works (without antialiasing). @@ -71,52 +69,49 @@ #define DFB_SHOW_GLYPHS 1 -D_DEBUG_DOMAIN( CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire" ); -D_DEBUG_DOMAIN( CairoDFB_Clip, "CairoDFB/Clip", "Cairo DirectFB Clipping" ); -D_DEBUG_DOMAIN( CairoDFB_Font, "CairoDFB/Font", "Cairo DirectFB Font Rendering" ); -D_DEBUG_DOMAIN( CairoDFB_Render, "CairoDFB/Render", "Cairo DirectFB Rendering" ); -D_DEBUG_DOMAIN( CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface" ); +D_DEBUG_DOMAIN (CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire"); +D_DEBUG_DOMAIN (CairoDFB_Clip, "CairoDFB/Clip", "Cairo DirectFB Clipping"); +D_DEBUG_DOMAIN (CairoDFB_Font, "CairoDFB/Font", "Cairo DirectFB Font Rendering"); +D_DEBUG_DOMAIN (CairoDFB_Render, "CairoDFB/Render", "Cairo DirectFB Rendering"); +D_DEBUG_DOMAIN (CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface"); /*****************************************************************************/ - typedef struct _cairo_directfb_surface { cairo_surface_t base; cairo_format_t format; cairo_content_t content; - + IDirectFB *dfb; IDirectFBSurface *dfbsurface; IDirectFBSurface *tmpsurface; - - /* color buffer */ - cairo_surface_t *color; - + + cairo_bool_t has_clip; DFBRegion *clips; int n_clips; - + int width; int height; - - cairo_bool_t local; + + unsigned local : 1; + unsigned blit_premultiplied : 1; } cairo_directfb_surface_t; typedef struct _cairo_directfb_font_cache { - IDirectFB *dfb; + IDirectFB *dfb; IDirectFBSurface *dfbsurface; int width; int height; - /* coordinates within the surface + /* coordinates within the surface * of the last loaded glyph */ int x; int y; } cairo_directfb_font_cache_t; - -static cairo_surface_backend_t cairo_directfb_surface_backend; +static cairo_surface_backend_t _cairo_directfb_surface_backend; /*****************************************************************************/ @@ -124,9 +119,8 @@ static int _directfb_argb_font = 0; /*****************************************************************************/ - -#define RUN_CLIPPED( surface, clip, func ) {\ - if ((surface)->clips) {\ +#define RUN_CLIPPED(surface, clip, func) {\ + if ((surface)->has_clip) {\ int k;\ for (k = 0; k < (surface)->n_clips; k++) {\ if (clip) {\ @@ -144,28 +138,26 @@ static int _directfb_argb_font = 0; if (reg.y2 > cli->y2)\ reg.y2 = cli->y2;\ (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\ - }\ - else {\ + } else {\ (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\ &(surface)->clips[k]);\ }\ func;\ }\ - }\ - else {\ + } else {\ (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\ func;\ }\ } -#define TRANSFORM_POINT2X( m, x, y, ret_x, ret_y ) {\ +#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) {\ double _x = (x);\ double _y = (y);\ (ret_x) = (_x * (m).xx + (m).x0);\ (ret_y) = (_y * (m).yy + (m).y0);\ } -#define TRANSFORM_POINT3X( m, x, y, ret_x, ret_y ) {\ +#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\ double _x = (x);\ double _y = (y);\ (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\ @@ -176,36 +168,35 @@ static int _directfb_argb_font = 0; * Probably we should drop it. */ -static cairo_content_t +static cairo_content_t _directfb_format_to_content (DFBSurfacePixelFormat format) { - if (DFB_PIXELFORMAT_HAS_ALPHA(format)) { - if (DFB_COLOR_BITS_PER_PIXEL(format)) + if (DFB_PIXELFORMAT_HAS_ALPHA (format)) { + if (DFB_COLOR_BITS_PER_PIXEL (format)) return CAIRO_CONTENT_COLOR_ALPHA; - + return CAIRO_CONTENT_ALPHA; } - + return CAIRO_CONTENT_COLOR; } - -static inline DFBSurfacePixelFormat +static inline DFBSurfacePixelFormat _cairo_to_directfb_format (cairo_format_t format) { switch (format) { - case CAIRO_FORMAT_RGB24: - return DSPF_RGB32; - case CAIRO_FORMAT_ARGB32: - return DSPF_ARGB; - case CAIRO_FORMAT_A8: - return DSPF_A8; - case CAIRO_FORMAT_A1: - return DSPF_A1; - default: - break; + case CAIRO_FORMAT_RGB24: + return DSPF_RGB32; + case CAIRO_FORMAT_ARGB32: + return DSPF_ARGB; + case CAIRO_FORMAT_A8: + return DSPF_A8; + case CAIRO_FORMAT_A1: + return DSPF_A1; + default: + break; } - + return -1; } @@ -213,110 +204,112 @@ static inline cairo_format_t _directfb_to_cairo_format (DFBSurfacePixelFormat format) { switch (format) { - case DSPF_RGB32: - return CAIRO_FORMAT_RGB24; - case DSPF_ARGB: - return CAIRO_FORMAT_ARGB32; - case DSPF_A8: - return CAIRO_FORMAT_A8; - case DSPF_A1: - return CAIRO_FORMAT_A1; - default: - break; + case DSPF_RGB32: + return CAIRO_FORMAT_RGB24; + case DSPF_ARGB: + return CAIRO_FORMAT_ARGB32; + case DSPF_A8: + return CAIRO_FORMAT_A8; + case DSPF_A1: + return CAIRO_FORMAT_A1; + default: + break; } - + return -1; } - -static cairo_status_t +static cairo_bool_t _directfb_get_operator (cairo_operator_t operator, DFBSurfaceBlendFunction *ret_srcblend, - DFBSurfaceBlendFunction *ret_dstblend ) + DFBSurfaceBlendFunction *ret_dstblend) { DFBSurfaceBlendFunction srcblend = DSBF_ONE; DFBSurfaceBlendFunction dstblend = DSBF_ZERO; - + switch (operator) { - case CAIRO_OPERATOR_CLEAR: - srcblend = DSBF_ZERO; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_SOURCE: - srcblend = DSBF_ONE; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OVER: - srcblend = DSBF_ONE; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_IN: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OUT: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_ATOP: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST: - srcblend = DSBF_ZERO; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_OVER: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_IN: - srcblend = DSBF_ZERO; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_DEST_OUT: - srcblend = DSBF_ZERO; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST_ATOP: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_XOR: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_ADD: - srcblend = DSBF_ONE; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_SATURATE: - srcblend = DSBF_SRCALPHASAT; - dstblend = DSBF_ONE; - break; - default: - return CAIRO_INT_STATUS_UNSUPPORTED; + case CAIRO_OPERATOR_CLEAR: + srcblend = DSBF_ZERO; + dstblend = DSBF_ZERO; + break; + case CAIRO_OPERATOR_SOURCE: + srcblend = DSBF_ONE; + dstblend = DSBF_ZERO; + break; + case CAIRO_OPERATOR_OVER: + srcblend = DSBF_ONE; + dstblend = DSBF_INVSRCALPHA; + break; + case CAIRO_OPERATOR_IN: + srcblend = DSBF_DESTALPHA; + dstblend = DSBF_ZERO; + break; + case CAIRO_OPERATOR_OUT: + srcblend = DSBF_INVDESTALPHA; + dstblend = DSBF_ZERO; + break; + case CAIRO_OPERATOR_ATOP: + srcblend = DSBF_DESTALPHA; + dstblend = DSBF_INVSRCALPHA; + break; + case CAIRO_OPERATOR_DEST: + srcblend = DSBF_ZERO; + dstblend = DSBF_ONE; + break; + case CAIRO_OPERATOR_DEST_OVER: + srcblend = DSBF_INVDESTALPHA; + dstblend = DSBF_ONE; + break; + case CAIRO_OPERATOR_DEST_IN: + srcblend = DSBF_ZERO; + dstblend = DSBF_SRCALPHA; + break; + case CAIRO_OPERATOR_DEST_OUT: + srcblend = DSBF_ZERO; + dstblend = DSBF_INVSRCALPHA; + break; + case CAIRO_OPERATOR_DEST_ATOP: + srcblend = DSBF_INVDESTALPHA; + dstblend = DSBF_SRCALPHA; + break; + case CAIRO_OPERATOR_XOR: + srcblend = DSBF_INVDESTALPHA; + dstblend = DSBF_INVSRCALPHA; + break; + case CAIRO_OPERATOR_ADD: + srcblend = DSBF_ONE; + dstblend = DSBF_ONE; + break; + case CAIRO_OPERATOR_SATURATE: + /* XXX This does not work. */ +#if 0 + srcblend = DSBF_SRCALPHASAT; + dstblend = DSBF_ONE; + break; +#endif + default: + return FALSE; } - if (ret_srcblend) - *ret_srcblend = srcblend; - if (ret_dstblend) - *ret_dstblend = dstblend; - - return CAIRO_STATUS_SUCCESS; + *ret_srcblend = srcblend; + *ret_dstblend = dstblend; + + return TRUE; } -static IDirectFBSurface* -_directfb_buffer_surface_create (IDirectFB *dfb, +static cairo_status_t +_directfb_buffer_surface_create (IDirectFB *dfb, DFBSurfacePixelFormat format, int width, - int height) + int height, + IDirectFBSurface **out) { IDirectFBSurface *buffer; DFBSurfaceDescription dsc; DFBResult ret; - + dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_PREMULTIPLIED; dsc.width = width; dsc.height = height; dsc.pixelformat = format; @@ -324,39 +317,44 @@ _directfb_buffer_surface_create (IDirectFB *dfb, ret = dfb->CreateSurface (dfb, &dsc, &buffer); if (ret) { DirectFBError ("IDirectFB::CreateSurface()", ret); - return NULL; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - - return buffer; + + *out = buffer; + return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_directfb_acquire_surface (cairo_directfb_surface_t *surface, +_directfb_acquire_surface (cairo_directfb_surface_t *surface, cairo_rectangle_int_t *intrest_rec, cairo_image_surface_t **image_out, cairo_rectangle_int_t *image_rect_out, void **image_extra, DFBSurfaceLockFlags lock_flags) -{ +{ IDirectFBSurface *buffer = NULL; DFBRectangle source_rect; + cairo_surface_t *image; cairo_format_t cairo_format; + cairo_status_t status; void *data; - int pitch; + int pitch; - if (surface->format == (cairo_format_t) -1) { + if (surface->format == (cairo_format_t) -1 || + (lock_flags & DSLF_WRITE && surface->has_clip)) + { DFBSurfaceCapabilities caps; - + if (intrest_rec) { source_rect.x = intrest_rec->x; source_rect.y = intrest_rec->y; - source_rect.w = intrest_rec->width; - source_rect.h = intrest_rec->height; + source_rect.w = intrest_rec->width; + source_rect.h = intrest_rec->height; } else { source_rect.x = 0; source_rect.y = 0; surface->dfbsurface->GetSize (surface->dfbsurface, - &source_rect.w, &source_rect.h); + &source_rect.w, &source_rect.h); } if (surface->tmpsurface) { @@ -367,47 +365,47 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface, surface->tmpsurface = NULL; } } - + cairo_format = _cairo_format_from_content (surface->content); if (!surface->tmpsurface) { D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface); - - surface->tmpsurface = - _directfb_buffer_surface_create (surface->dfb, + + status = + _directfb_buffer_surface_create (surface->dfb, _cairo_to_directfb_format (cairo_format), - source_rect.w, source_rect.h); - if (!surface->tmpsurface) + source_rect.w, source_rect.h, + &surface->tmpsurface); + if (status) goto ERROR; } buffer = surface->tmpsurface; - + /* surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps); if (caps & DSCAPS_FLIPPING) { - DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, + DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, .x2 = source_rect.x + source_rect.w - 1, .y2 = source_rect.y + source_rect.h - 1 }; surface->dfbsurface->Flip (surface->dfbsurface, ®ion, DSFLIP_BLIT); } */ buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0); - } - else { + } else { /*might be a subsurface get the offset*/ surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect); cairo_format = surface->format; - buffer = surface->dfbsurface; + buffer = surface->dfbsurface; } - - *image_extra = buffer; - + if (buffer->Lock (buffer, lock_flags, &data, &pitch)) { D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n"); + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto ERROR; } - - *image_out = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (data, cairo_format, - source_rect.w, source_rect.h, pitch); - if (*image_out == NULL) + + image = cairo_image_surface_create_for_data (data, cairo_format, + source_rect.w, source_rect.h, + pitch); + status = image->status; + if (status) goto ERROR; if (image_rect_out) { @@ -417,26 +415,26 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface, image_rect_out->height = source_rect.h; } else { /* lock for read */ - cairo_surface_t *sur = &((*image_out)->base); /* might be a subsurface */ - if (buffer == surface->dfbsurface) - cairo_surface_set_device_offset (sur, source_rect.x, source_rect.y); + if (buffer == surface->dfbsurface) { + cairo_surface_set_device_offset (image, + source_rect.x, source_rect.y); + } } - + + *image_extra = buffer; + *image_out = (cairo_image_surface_t *) image; return CAIRO_STATUS_SUCCESS; ERROR: - *image_extra = NULL; if (buffer) { buffer->Unlock (buffer); - if (buffer != surface->dfbsurface) + if (buffer != surface->dfbsurface) buffer->Release (buffer); } - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return status; } - - static cairo_surface_t * _cairo_directfb_surface_create_similar (void *abstract_src, cairo_content_t content, @@ -446,53 +444,60 @@ _cairo_directfb_surface_create_similar (void *abstract_src, cairo_directfb_surface_t *source = abstract_src; cairo_directfb_surface_t *surface; cairo_format_t format; - - D_DEBUG_AT (CairoDFB_Surface, + cairo_status_t status; + + D_DEBUG_AT (CairoDFB_Surface, "%s( src=%p, content=0x%x, width=%d, height=%d).\n", __FUNCTION__, source, content, width, height); - + width = (width <= 0) ? 1 : width; height = (height<= 0) ? 1 : height; - format = _cairo_format_from_content (content); - surface = calloc (1, sizeof(cairo_directfb_surface_t)); - if (!surface) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - + format = _cairo_format_from_content (content); + surface = calloc (1, sizeof (cairo_directfb_surface_t)); + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + surface->dfb = source->dfb; - + if (width < 8 || height < 8) { IDirectFBSurface *tmp; + DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height }; + /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */ - tmp = _directfb_buffer_surface_create (surface->dfb, + status = _directfb_buffer_surface_create (surface->dfb, _cairo_to_directfb_format (format), - MAX (width, 8), MAX (height, 8)); - if (tmp) { - DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height }; - tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface); - tmp->Release (tmp); - } + MAX (width, 8), MAX (height, 8), + &tmp); + if (status) { + free (surface); + return _cairo_surface_create_in_error (status); + } + + tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface); + tmp->Release (tmp); + } else { + status = + _directfb_buffer_surface_create (surface->dfb, + _cairo_to_directfb_format (format), + width, height, + &surface->dfbsurface); + if (status) { + free (surface); + return _cairo_surface_create_in_error (status); + } } - else { - surface->dfbsurface = _directfb_buffer_surface_create (surface->dfb, - _cairo_to_directfb_format (format), width, height); - } - - if (!surface->dfbsurface) { - D_ASSERT (surface->dfbsurface != NULL); - free (surface); - return NULL; - } - - _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, content); + + _cairo_surface_init (&surface->base, + &_cairo_directfb_surface_backend, + content); surface->format = format; surface->content = content; surface->width = width; surface->height = height; - surface->local = true; - + surface->local = TRUE; + surface->blit_premultiplied = TRUE; + return &surface->base; } @@ -500,20 +505,15 @@ static cairo_status_t _cairo_directfb_surface_finish (void *data) { cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data; - + D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface); - + if (surface->clips) { free (surface->clips); surface->clips = NULL; surface->n_clips = 0; } - - if (surface->color) { - cairo_surface_destroy (surface->color); - surface->color = NULL; - } - + if (surface->tmpsurface) { surface->tmpsurface->Release (surface->tmpsurface); surface->tmpsurface = NULL; @@ -523,10 +523,10 @@ _cairo_directfb_surface_finish (void *data) surface->dfbsurface->Release (surface->dfbsurface); surface->dfbsurface = NULL; } - + if (surface->dfb) surface->dfb = NULL; - + return CAIRO_STATUS_SUCCESS; } @@ -536,12 +536,12 @@ _cairo_directfb_surface_acquire_source_image (void *abstract_s void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - - return _directfb_acquire_surface (surface, NULL, image_out, - NULL, image_extra, DSLF_READ); + + D_DEBUG_AT (CairoDFB_Acquire, + "%s( surface=%p ).\n", __FUNCTION__, surface); + + return _directfb_acquire_surface (surface, NULL, image_out, + NULL, image_extra, DSLF_READ); } static void @@ -549,14 +549,13 @@ _cairo_directfb_surface_release_source_image (void *abstract_su cairo_image_surface_t *image, void *image_extra) { - cairo_directfb_surface_t *surface = abstract_surface; IDirectFBSurface *buffer = image_extra; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - + + D_DEBUG_AT (CairoDFB_Acquire, + "%s( surface=%p ).\n", __FUNCTION__, surface); + buffer->Unlock (buffer); - + cairo_surface_destroy (&image->base); } @@ -568,17 +567,18 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_s void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n", - __FUNCTION__, surface, surface->width, surface->height, - interest_rect ? interest_rect->x : 0, - interest_rect ? interest_rect->y : 0, - interest_rect ? interest_rect->width : (unsigned) surface->width, - interest_rect ? interest_rect->height : (unsigned) surface->height); - - return _directfb_acquire_surface (surface, interest_rect, image_out, - image_rect_out, image_extra, DSLF_READ | DSLF_WRITE); + + D_DEBUG_AT (CairoDFB_Acquire, + "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n", + __FUNCTION__, surface, surface->width, surface->height, + interest_rect ? interest_rect->x : 0, + interest_rect ? interest_rect->y : 0, + interest_rect ? interest_rect->width : (unsigned) surface->width, + interest_rect ? interest_rect->height : (unsigned) surface->height); + + return _directfb_acquire_surface (surface, interest_rect, image_out, + image_rect_out, image_extra, + DSLF_READ | DSLF_WRITE); } static void @@ -589,23 +589,27 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf void *image_extra) { cairo_directfb_surface_t *surface = abstract_surface; - IDirectFBSurface *buffer = image_extra; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - + IDirectFBSurface *buffer = image_extra; + + D_DEBUG_AT (CairoDFB_Acquire, + "%s( surface=%p ).\n", __FUNCTION__, surface); + buffer->Unlock (buffer); if (surface->dfbsurface != buffer) { - DFBRegion region = { .x1 = interest_rect->x, .y1 = interest_rect->y, - .x2 = interest_rect->x+interest_rect->width-1, - .y2 = interest_rect->y+interest_rect->height-1 }; - surface->dfbsurface->SetClip (surface->dfbsurface, ®ion); - surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX); - surface->dfbsurface->Blit (surface->dfbsurface, buffer, - NULL, image_rect->x, image_rect->y); + DFBRegion region = { + .x1 = interest_rect->x, + .y1 = interest_rect->y, + .x2 = interest_rect->x + interest_rect->width - 1, + .y2 = interest_rect->y + interest_rect->height - 1 + }; + surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX); + RUN_CLIPPED (surface, ®ion, + surface->dfbsurface->Blit (surface->dfbsurface, + buffer, NULL, + image_rect->x, image_rect->y)); } - + cairo_surface_destroy (&image->base); } @@ -616,81 +620,82 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_directfb_surface_t *surface = abstract_surface; cairo_directfb_surface_t *clone; - - D_DEBUG_AT (CairoDFB_Surface, - "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src); + + D_DEBUG_AT (CairoDFB_Surface, + "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src); if (src->backend == surface->base.backend) { - cairo_surface_reference (src); - *clone_out = src; - - return CAIRO_STATUS_SUCCESS; - } - else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; - unsigned char *dst, *src = image_src->data; - int pitch; - int i, j; - DFBResult ret; - - clone = (cairo_directfb_surface_t *) - _cairo_directfb_surface_create_similar (surface, - _cairo_content_from_format (image_src->format), - image_src->width, image_src->height); - if (!clone) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - ret = clone->dfbsurface->Lock (clone->dfbsurface, - DSLF_WRITE, (void *)&dst, &pitch); - if (ret) { - DirectFBError ("IDirectFBSurface::Lock()", ret); - cairo_surface_destroy ((cairo_surface_t *)clone); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } + *clone_offset_x = 0; + *clone_offset_y = 0; + *clone_out = cairo_surface_reference (src); - dst += pitch * src_y; - src += image_src->stride * src_y; - - if (image_src->format == CAIRO_FORMAT_A1) { - /* A1 -> A8 */ - for (i = 0; i < height; i++) { - for (j = src_x; j < src_x + width; j++) - dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00; - dst += pitch; - src += image_src->stride; - } - } - else { - int len; - - if (image_src->format == CAIRO_FORMAT_A8) { - dst += src_x; - src += src_x; - len = width; - } else { - dst += src_x * 4; - src += src_x * 4; - len = width * 4; - } - - for (i = 0; i < height; i++) { - direct_memcpy (dst, src, len); - dst += pitch; - src += image_src->stride; - } - } - - clone->dfbsurface->Unlock (clone->dfbsurface); - - *clone_out = &clone->base; - - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; + } else if (_cairo_surface_is_image (src)) { + cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; + unsigned char *dst, *src = image_src->data; + int pitch; + int i, j; + DFBResult ret; + + clone = (cairo_directfb_surface_t *) + _cairo_directfb_surface_create_similar (surface, + _cairo_content_from_format (image_src->format), + width, height); + if (clone == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (clone->base.status) + return clone->base.status; + + ret = clone->dfbsurface->Lock (clone->dfbsurface, + DSLF_WRITE, (void *)&dst, &pitch); + if (ret) { + DirectFBError ("IDirectFBSurface::Lock()", ret); + cairo_surface_destroy (&clone->base); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + src += image_src->stride * src_y; + if (image_src->format == CAIRO_FORMAT_A1) { + /* A1 -> A8 */ + dst -= src_x; + for (i = 0; i < height; i++) { + for (j = src_x; j < src_x + width; j++) + dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00; + dst += pitch; + src += image_src->stride; + } + } else { + int len; + + if (image_src->format == CAIRO_FORMAT_A8) { + src += src_x; + len = width; + } else { + src += src_x * 4; + len = width * 4; + } + + for (i = 0; i < height; i++) { + direct_memcpy (dst, src, len); + dst += pitch; + src += image_src->stride; + } + } + + clone->dfbsurface->Unlock (clone->dfbsurface); + + *clone_offset_x = src_x; + *clone_offset_y = src_y; + *clone_out = &clone->base; + return CAIRO_STATUS_SUCCESS; } - + return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -703,133 +708,135 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, int *src_x, int *src_y, int *mask_x, int *mask_y, unsigned int width, - unsigned int height, + unsigned int height, cairo_directfb_surface_t **ret_src, cairo_surface_attributes_t *ret_src_attr) { cairo_directfb_surface_t *src; cairo_surface_attributes_t src_attr; - cairo_status_t ret; + cairo_status_t status; DFBSurfaceBlittingFlags flags; DFBSurfaceBlendFunction sblend; DFBSurfaceBlendFunction dblend; - DFBColor color; - - if (_directfb_get_operator (op, &sblend, &dblend)) + const cairo_color_t *color; + + /* XXX Unbounded operators are not handled correctly */ + if (! _cairo_operator_bounded_by_source (op)) return CAIRO_INT_STATUS_UNSUPPORTED; - + + if (! _directfb_get_operator (op, &sblend, &dblend)) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (mask_pattern) { - cairo_solid_pattern_t *pattern; - - if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) { - cairo_pattern_t *tmp; - int tmp_x, tmp_y; - - if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID || - sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */ - return CAIRO_INT_STATUS_UNSUPPORTED; - - D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n"); - - tmp = src_pattern; - tmp_x = *src_x; tmp_y = *src_y; - - src_pattern = mask_pattern; - *src_x = *mask_x; *src_y = *mask_y; - - mask_pattern = tmp; - *mask_x = tmp_x; *mask_y = tmp_y; - - if (sblend == DSBF_ONE) { - sblend = DSBF_SRCALPHA; - /*dblend = DSBF_INVSRCALPHA;*/ - } - } - - pattern = (cairo_solid_pattern_t *)mask_pattern; - color.a = pattern->color.alpha_short >> 8; - color.r = pattern->color.red_short >> 8; - color.g = pattern->color.green_short >> 8; - color.b = pattern->color.blue_short >> 8; - } - else { - color.a = color.r = color.g = color.b = 0xff; - } - - if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *)src_pattern; - - if (!dst->color) { - dst->color = _cairo_directfb_surface_create_similar (dst, - CAIRO_CONTENT_COLOR_ALPHA, 1, 1); - if (!dst->color) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - src = (cairo_directfb_surface_t *)dst->color; - src->dfbsurface->Clear (src->dfbsurface, - pattern->color.red_short >> 8, - pattern->color.green_short >> 8, - pattern->color.blue_short >> 8, - pattern->color.alpha_short >> 8); - - src_attr.matrix = src_pattern->matrix; - src_attr.extend = CAIRO_EXTEND_NONE; - src_attr.filter = CAIRO_FILTER_NEAREST; - src_attr.x_offset = - src_attr.y_offset = 0; - } - else { - ret = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - *src_x, *src_y, width, height, - (cairo_surface_t **)&src, &src_attr); - if (ret) - return ret; - } - - if (src->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_SRCALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVSRCALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_SRCALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVSRCALPHA) - dblend = DSBF_ZERO; - } - if (dst->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_DESTALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVDESTALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_DESTALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVDESTALPHA) - dblend = DSBF_ZERO; + cairo_solid_pattern_t *pattern; + + return CAIRO_INT_STATUS_UNSUPPORTED; + if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) { + cairo_pattern_t *tmp; + int tmp_x, tmp_y; + + if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID || + sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */ + return CAIRO_INT_STATUS_UNSUPPORTED; + + D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n"); + + tmp = src_pattern; + tmp_x = *src_x; tmp_y = *src_y; + + src_pattern = mask_pattern; + *src_x = *mask_x; *src_y = *mask_y; + + mask_pattern = tmp; + *mask_x = tmp_x; *mask_y = tmp_y; + + if (sblend == DSBF_ONE) { + sblend = DSBF_SRCALPHA; + /*dblend = DSBF_INVSRCALPHA;*/ + } + } + + color = &((cairo_solid_pattern_t *) mask_pattern)->color; + } else { + color = _cairo_stock_color (CAIRO_STOCK_WHITE); } - flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) - ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; - if (color.a != 0xff) - flags |= DSBLIT_BLEND_COLORALPHA; - if (color.r != 0xff || color.g != 0xff || color.b != 0xff) - flags |= DSBLIT_COLORIZE; - - dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); - - if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); + /* XXX DirectFB currently does not support filtering, so force NEAREST + * in order to hit optimisations inside core. + */ + src_pattern->filter = CAIRO_FILTER_NEAREST; + + status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, + *src_x, *src_y, width, height, + (cairo_surface_t **) &src, + &src_attr); + if (status) + return status; + + if (src->base.backend != &_cairo_directfb_surface_backend || + src->dfb != dst->dfb) + { + _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); + return CAIRO_INT_STATUS_UNSUPPORTED; } - - if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) - dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); - + + if (src->content == CAIRO_CONTENT_COLOR) { + if (sblend == DSBF_SRCALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVSRCALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_SRCALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVSRCALPHA) + dblend = DSBF_ZERO; + } + + if (dst->content == CAIRO_CONTENT_COLOR) { + if (sblend == DSBF_DESTALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVDESTALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_DESTALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVDESTALPHA) + dblend = DSBF_ZERO; + } + + flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) + ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; + if (! CAIRO_COLOR_IS_OPAQUE (color)) + flags |= DSBLIT_BLEND_COLORALPHA; + if (! _cairo_color_equal (color, _cairo_stock_color (CAIRO_STOCK_WHITE))) + flags |= DSBLIT_COLORIZE; + + dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); + + if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); + } + + if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) { + if (dst->blit_premultiplied) { + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red_short >> 8, + color->green_short >> 8, + color->blue_short >> 8, + color->alpha_short >> 8); + } else { + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red * 0xff, + color->green * 0xff, + color->blue * 0xff, + color->alpha * 0xff); + } + } + *ret_src = src; *ret_src_attr = src_attr; - + return CAIRO_STATUS_SUCCESS; } @@ -839,34 +846,48 @@ _directfb_finish_composite (cairo_directfb_surface_t *dst, cairo_surface_t *src, cairo_surface_attributes_t *src_attr) { - if (src != dst->color) - _cairo_pattern_release_surface (src_pattern, src, src_attr); + _cairo_pattern_release_surface (src_pattern, src, src_attr); } -#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */ +#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */ #if DFB_COMPOSITE static DFBAccelerationMask _directfb_categorize_operation (cairo_surface_attributes_t *src_attr) { cairo_matrix_t *m = &src_attr->matrix; - + if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) { - if (src_attr->extend != CAIRO_EXTEND_NONE) - return DFXL_NONE; - return DFXL_TEXTRIANGLES; + if (src_attr->extend != CAIRO_EXTEND_NONE) + return DFXL_NONE; + + return DFXL_TEXTRIANGLES; } - + if (m->xx != 1 || m->yy != 1) { - if (src_attr->extend != CAIRO_EXTEND_NONE) - return DFXL_NONE; - return DFXL_STRETCHBLIT; + if (src_attr->extend != CAIRO_EXTEND_NONE) + return DFXL_NONE; + + return DFXL_STRETCHBLIT; + } + + switch (src_attr->extend) { + case CAIRO_EXTEND_NONE: + case CAIRO_EXTEND_REPEAT: + if (_cairo_matrix_is_integer_translation (&src_attr->matrix, + NULL, NULL)) + { + return DFXL_BLIT; + } + else + { + return DFXL_STRETCHBLIT; + } + + default: + case CAIRO_EXTEND_REFLECT: + case CAIRO_EXTEND_PAD: + return DFXL_NONE; } - - if (src_attr->extend != CAIRO_EXTEND_NONE && - src_attr->extend != CAIRO_EXTEND_REPEAT) - return DFXL_NONE; - - return DFXL_BLIT; } static cairo_int_status_t @@ -883,160 +904,181 @@ _cairo_directfb_surface_composite (cairo_operator_t op, cairo_directfb_surface_t *dst = abstract_dst; cairo_directfb_surface_t *src; cairo_surface_attributes_t src_attr; + cairo_bool_t is_integer_translation; DFBAccelerationMask accel, mask; - cairo_int_status_t ret; - + cairo_int_status_t status; + int tx, ty; + D_DEBUG_AT (CairoDFB_Render, - "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p," - " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d," - " dst_y=%d, width=%u, height=%u ).\n", - __FUNCTION__, op, src_pattern, mask_pattern, dst, - src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); - - ret = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op, - &src_x, &src_y, &mask_x, &mask_y, - width, height, &src, &src_attr); - if (ret) - return ret; - + "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p," + " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d," + " dst_y=%d, width=%u, height=%u ).\n", + __FUNCTION__, op, src_pattern, mask_pattern, dst, + src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); + + status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op, + &src_x, &src_y, &mask_x, &mask_y, + width, height, &src, &src_attr); + if (status) + return status; + accel = _directfb_categorize_operation (&src_attr); - - dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &mask); - if (!(mask & accel)) { - D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel); - if (accel != DFXL_BLIT) { - _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); - return CAIRO_INT_STATUS_UNSUPPORTED; - } + if (accel == DFXL_NONE) { + _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); + return CAIRO_INT_STATUS_UNSUPPORTED; } - + + dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, + src->dfbsurface, + &mask); + if ((mask & accel) == 0) { + D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel); + if (accel != DFXL_BLIT) { + _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + } + src_x += src_attr.x_offset; src_y += src_attr.y_offset; - - switch (accel) { - case DFXL_BLIT: { - DFBRectangle sr; - - sr.x = src_x + _cairo_lround (src_attr.matrix.x0); - sr.y = src_y + _cairo_lround (src_attr.matrix.y0); - sr.w = width; - sr.h = height; - - if (src_attr.extend == CAIRO_EXTEND_NONE) { - D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n"); - - RUN_CLIPPED( dst, NULL, - dst->dfbsurface->Blit (dst->dfbsurface, - src->dfbsurface, &sr, dst_x, dst_y)); - } - else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { - DFBRegion clip; - - clip.x1 = dst_x; - clip.y1 = dst_y; - clip.x2 = dst_x + width - 1; - clip.y2 = dst_y + height - 1; - - D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n"); - - RUN_CLIPPED( dst, &clip, - dst->dfbsurface->TileBlit (dst->dfbsurface, - src->dfbsurface, &sr, dst_x, dst_y)); - } - } break; - - case DFXL_STRETCHBLIT: { - DFBRectangle sr, dr; - double x1, y1, x2, y2; - - TRANSFORM_POINT2X (src_attr.matrix, - src_x, src_y, x1, y1); - TRANSFORM_POINT2X (src_attr.matrix, - src_x+width, src_y+height, x2, y2); - - sr.x = _cairo_lround (x1); - sr.y = _cairo_lround (y1); - sr.w = _cairo_lround (x2-x1); - sr.h = _cairo_lround (y2-y1); - - dr.x = dst_x; - dr.y = dst_y; - dr.w = width; - dr.h = height; - - D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n"); - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->StretchBlit (dst->dfbsurface, - src->dfbsurface, &sr, &dr)); - } break; - - case DFXL_TEXTRIANGLES: { - DFBRegion clip; - DFBVertex v[4]; - float x1, y1, x2, y2; - int w, h; - - if (cairo_matrix_invert (&src_attr.matrix) != CAIRO_STATUS_SUCCESS) { - ret = CAIRO_INT_STATUS_UNSUPPORTED; - break; - } - - x1 = src_attr.x_offset; - y1 = src_attr.y_offset; - x2 = src->width - x1; - y2 = src->height - y1; - - src->dfbsurface->GetSize (src->dfbsurface, &w, &h); - - TRANSFORM_POINT3X (src_attr.matrix, - x1, y1, v[0].x, v[0].y); - v[0].z = 0; - v[0].w = 1; - v[0].s = x1 / w; - v[0].t = y1 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x2, y1, v[1].x, v[1].y); - v[1].z = 0; - v[1].w = 1; - v[1].s = x2 / w; - v[1].t = y1 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x2, y2, v[2].x, v[2].y); - v[2].z = 0; - v[2].w = 1; - v[2].s = x2 / w; - v[2].t = y2 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x1, y2, v[3].x, v[3].y); - v[3].z = 0; - v[3].w = 1; - v[3].s = x1 / w; - v[3].t = y2 / h; - - clip.x1 = dst_x; - clip.y1 = dst_y; - clip.x2 = dst_x + width - 1; - clip.y2 = dst_y + height - 1; - - D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n"); - - RUN_CLIPPED (dst, &clip, - dst->dfbsurface->TextureTriangles (dst->dfbsurface, - src->dfbsurface, v, NULL, 4, DTTF_FAN)); - } break; - - default: - D_BUG ("Unexpected operation"); - break; + switch (accel) { + case DFXL_BLIT: + { + DFBRectangle sr; + + is_integer_translation = + _cairo_matrix_is_integer_translation (&src_attr.matrix, + &tx, &ty); + assert (is_integer_translation); + + sr.x = src_x + tx; + sr.y = src_y + ty; + sr.w = width; + sr.h = height; + + if (src_attr.extend == CAIRO_EXTEND_NONE) { + D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n"); + + RUN_CLIPPED (dst, NULL, + dst->dfbsurface->Blit (dst->dfbsurface, + src->dfbsurface, + &sr, + dst_x, dst_y)); + } else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { + DFBRegion clip; + + clip.x1 = dst_x; + clip.y1 = dst_y; + clip.x2 = dst_x + width - 1; + clip.y2 = dst_y + height - 1; + + D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n"); + + RUN_CLIPPED (dst, &clip, + dst->dfbsurface->TileBlit (dst->dfbsurface, + src->dfbsurface, + &sr, + dst_x, dst_y)); + } + break; + } + + case DFXL_STRETCHBLIT: + { + DFBRectangle sr, dr; + double x1, y1, x2, y2; + + TRANSFORM_POINT2X (src_attr.matrix, + src_x, src_y, x1, y1); + TRANSFORM_POINT2X (src_attr.matrix, + src_x+width, src_y+height, x2, y2); + + sr.x = floor (x1); + sr.y = floor (y1); + sr.w = ceil (x2) - sr.x; + sr.h = ceil (y2) - sr.y; + + dr.x = dst_x; + dr.y = dst_y; + dr.w = width; + dr.h = height; + + D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n"); + + RUN_CLIPPED (dst, NULL, + dst->dfbsurface->StretchBlit (dst->dfbsurface, + src->dfbsurface, &sr, &dr)); + break; + } + + case DFXL_TEXTRIANGLES: + { + DFBRegion clip; + DFBVertex v[4]; + float x1, y1, x2, y2; + int w, h; + + status = cairo_matrix_invert (&src_attr.matrix); + /* guaranteed by cairo_pattern_set_matrix (); */ + assert (status == CAIRO_STATUS_SUCCESS); + + x1 = src_x; + y1 = src_y; + x2 = width + x1; + y2 = height + y1; + + src->dfbsurface->GetSize (src->dfbsurface, &w, &h); + + TRANSFORM_POINT3X (src_attr.matrix, + x1, y1, v[0].x, v[0].y); + v[0].z = 0; + v[0].w = 1; + v[0].s = x1 / w; + v[0].t = y1 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x2, y1, v[1].x, v[1].y); + v[1].z = 0; + v[1].w = 1; + v[1].s = x2 / w; + v[1].t = y1 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x2, y2, v[2].x, v[2].y); + v[2].z = 0; + v[2].w = 1; + v[2].s = x2 / w; + v[2].t = y2 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x1, y2, v[3].x, v[3].y); + v[3].z = 0; + v[3].w = 1; + v[3].s = x1 / w; + v[3].t = y2 / h; + + clip.x1 = dst_x; + clip.y1 = dst_y; + clip.x2 = dst_x + width - 1; + clip.y2 = dst_y + height - 1; + + D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n"); + + RUN_CLIPPED (dst, &clip, + dst->dfbsurface->TextureTriangles (dst->dfbsurface, + src->dfbsurface, v, NULL, 4, DTTF_FAN)); + break; + } + + default: + D_BUG ("Unexpected operation"); + break; } _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); - - return ret; + + return status; } #endif /* DFB_COMPOSITE */ @@ -1054,60 +1096,63 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface DFBSurfaceBlendFunction dblend; DFBRectangle r[n_rects]; int i; - - D_DEBUG_AT (CairoDFB_Render, - "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n", - __FUNCTION__, dst, op, color, rects, n_rects); - if (_directfb_get_operator (op, &sblend, &dblend)) + D_DEBUG_AT (CairoDFB_Render, + "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n", + __FUNCTION__, dst, op, color, rects, n_rects); + + if (! _cairo_operator_bounded_by_source (op)) return CAIRO_INT_STATUS_UNSUPPORTED; - - if (color->alpha_short >= 0xff00) { - if (sblend == DSBF_SRCALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVSRCALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_SRCALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVSRCALPHA) - dblend = DSBF_ZERO; + + if (! _directfb_get_operator (op, &sblend, &dblend)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (CAIRO_COLOR_IS_OPAQUE (color)) { + if (sblend == DSBF_SRCALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVSRCALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_SRCALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVSRCALPHA) + dblend = DSBF_ZERO; } if (dst->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_DESTALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVDESTALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_DESTALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVDESTALPHA) - dblend = DSBF_ZERO; + if (sblend == DSBF_DESTALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVDESTALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_DESTALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVDESTALPHA) + dblend = DSBF_ZERO; } - + flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND; dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags); if (flags & DSDRAW_BLEND) { - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - } - - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8 ); - - for (i = 0; i < n_rects; i++) { - r[i].x = rects[i].x; - r[i].y = rects[i].y; - r[i].w = rects[i].width; - r[i].h = rects[i].height; + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } - + + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red_short >> 8, + color->green_short >> 8, + color->blue_short >> 8, + color->alpha_short >> 8); + + for (i = 0; i < n_rects; i++) { + r[i].x = rects[i].x; + r[i].y = rects[i].y; + r[i].w = rects[i].width; + r[i].h = rects[i].height; + } + RUN_CLIPPED (dst, NULL, - dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects)); - + dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects)); + return CAIRO_STATUS_SUCCESS; } #endif @@ -1123,14 +1168,14 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, unsigned int width, unsigned int height, cairo_trapezoid_t *traps, - int num_traps ) + int num_traps) { cairo_directfb_surface_t *dst = abstract_dst; cairo_directfb_surface_t *src; cairo_surface_attributes_t src_attr; - cairo_status_t ret; + cairo_status_t status; DFBAccelerationMask accel; - + D_DEBUG_AT (CairoDFB_Render, "%s( op=%d, pattern=%p, dst=%p, antialias=%d," " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d," @@ -1140,116 +1185,110 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, if (antialias != CAIRO_ANTIALIAS_NONE) return CAIRO_INT_STATUS_UNSUPPORTED; - + /* Textures are not supported yet. */ if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) return CAIRO_INT_STATUS_UNSUPPORTED; - - ret = _directfb_prepare_composite (dst, pattern, NULL, op, - &src_x, &src_y, NULL, NULL, - width, height, &src, &src_attr); - if (ret) - return ret; - - dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel); - - ret = CAIRO_INT_STATUS_UNSUPPORTED; - + + status = _directfb_prepare_composite (dst, pattern, NULL, op, + &src_x, &src_y, NULL, NULL, + width, height, &src, &src_attr); + if (status) + return status; + + dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, + src->dfbsurface, + &accel); + + status = CAIRO_INT_STATUS_UNSUPPORTED; + if (accel & DFXL_TEXTRIANGLES) { DFBVertex vertex[6*num_traps]; DFBVertex *v = &vertex[0]; - int n; - -#define ADD_TRI(id, x1, y1, s1, t1, x2, y2, s2, t2, x3, y3, s3, t3) {\ + int n = 0; + +#define ADD_TRI_V(V, X, Y) do { \ + (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \ +} while (0) +#define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\ const int p = (id)*3;\ - v[p+0].x=(x1); v[p+0].y=(y1); v[p+0].z=0; v[p+0].w=1; v[p+0].s=(s1); v[p+0].t=(t1);\ - v[p+1].x=(x2); v[p+1].y=(y2); v[p+1].z=0; v[p+1].w=1; v[p+1].s=(s2); v[p+1].t=(t2);\ - v[p+2].x=(x3); v[p+2].y=(y3); v[p+2].z=0; v[p+2].w=1; v[p+2].s=(s3); v[p+2].t=(t3);\ -} - - for (n = 0; num_traps; num_traps--) { - float lx1, ly1, lx2, ly2; - float rx1, ry1, rx2, ry2; - - /* XXX: Do we need to validate the trapezoid? */ - - lx1 = traps->left.p1.x/65536.0; - ly1 = traps->left.p1.y/65536.0; - lx2 = traps->left.p2.x/65536.0; - ly2 = traps->left.p2.y/65536.0; - rx1 = traps->right.p1.x/65536.0; - ry1 = traps->right.p1.y/65536.0; - rx2 = traps->right.p2.x/65536.0; - ry2 = traps->right.p2.y/65536.0; - + ADD_TRI_V (v+p+0, x1, y1); \ + ADD_TRI_V (v+p+1, x2, y2); \ + ADD_TRI_V (v+p+2, x3, y3); \ +} while (0) + while (num_traps--) { + double lx1, ly1, lx2, ly2; + double rx1, ry1, rx2, ry2; + + lx1 = _cairo_fixed_to_double (traps->left.p1.x); + ly1 = _cairo_fixed_to_double (traps->left.p1.y); + lx2 = _cairo_fixed_to_double (traps->left.p2.x); + ly2 = _cairo_fixed_to_double (traps->left.p2.y); + rx1 = _cairo_fixed_to_double (traps->right.p1.x); + ry1 = _cairo_fixed_to_double (traps->right.p1.y); + rx2 = _cairo_fixed_to_double (traps->right.p2.x); + ry2 = _cairo_fixed_to_double (traps->right.p2.y); + if (traps->left.p1.y < traps->top) { - float y = traps->top/65536.0; + double y = _cairo_fixed_to_double (traps->top); if (lx2 != lx1) lx1 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1; ly1 = y; - } + } if (traps->left.p2.y > traps->bottom) { - float y = traps->bottom/65536.0; + double y = _cairo_fixed_to_double (traps->bottom); if (lx2 != lx1) lx2 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1; ly2 = y; } - + if (traps->right.p1.y < traps->top) { - float y = traps->top/65536.0; + double y = _cairo_fixed_to_double (traps->top); if (rx2 != rx1) rx1 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1; ry1 = y; } if (traps->right.p2.y > traps->bottom) { - float y = traps->bottom/65536.0; + double y = _cairo_fixed_to_double (traps->bottom); if (rx2 != rx1) rx2 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1; ry2 = y; } - + if (lx1 == rx1 && ly1 == ry1) { - ADD_TRI (0, lx2, ly2, 0, 0, - lx1, ly1, 0, 0, - rx2, ry2, 0, 0 ); + ADD_TRI (0, lx2, ly2, lx1, ly1, rx2, ry2); v += 3; n += 3; - } - else if (lx2 == rx2 && ly2 == ry2) { - ADD_TRI (0, lx1, ly1, 0, 0, - lx2, ly2, 0, 0, - rx1, ry1, 0, 0 ); + } else if (lx2 == rx2 && ly2 == ry2) { + ADD_TRI (0, lx1, ly1, lx2, ly2, rx1, ry1); v += 3; n += 3; - } - else { - ADD_TRI (0, lx1, ly1, 0, 0, - rx1, ry1, 0, 0, - lx2, ly2, 0, 0); - ADD_TRI (1, lx2, ly2, 0, 0, - rx1, ry1, 0, 0, - rx2, ry2, 0, 0); + } else { + ADD_TRI (0, lx1, ly1, rx1, ry1, lx2, ly2); + ADD_TRI (1, lx2, ly2, rx1, ry1, rx2, ry2); v += 6; n += 6; } - + traps++; } - #undef ADD_TRI - +#undef ADD_TRI_V + D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n"); - + RUN_CLIPPED (dst, NULL, - dst->dfbsurface->TextureTriangles (dst->dfbsurface, src->dfbsurface, - vertex, NULL, n, DTTF_LIST)); - - ret = CAIRO_STATUS_SUCCESS; + dst->dfbsurface->TextureTriangles (dst->dfbsurface, + src->dfbsurface, + vertex, NULL, n, + DTTF_LIST)); + + status = CAIRO_STATUS_SUCCESS; } - + _directfb_finish_composite (dst, pattern, &src->base, &src_attr); - return ret; + return status; } #endif /* DFB_COMPOSITE_TRAPEZOIDS */ @@ -1258,52 +1297,54 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface, cairo_region_t *region) { cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Clip, - "%s( surface=%p, region=%p ).\n", - __FUNCTION__, surface, region); - + + D_DEBUG_AT (CairoDFB_Clip, + "%s( surface=%p, region=%p ).\n", + __FUNCTION__, surface, region); + if (region) { - cairo_box_int_t *boxes; - int n_boxes; - cairo_status_t status; - int i; + cairo_box_int_t *boxes; + int n_boxes; + cairo_status_t status; + int i; - status = _cairo_region_get_boxes (region, &n_boxes, &boxes); - if (n_boxes == 0) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (surface->n_clips != n_boxes) { - if (surface->clips) - free (surface->clips); - - surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion)); - if (!surface->clips) { - surface->n_clips = 0; - _cairo_region_boxes_fini (region, boxes); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - surface->n_clips = n_boxes; - } - - for (i = 0; i < n_boxes; i++) { - surface->clips[i].x1 = boxes[i].p1.x; - surface->clips[i].y1 = boxes[i].p1.y; - surface->clips[i].x2 = boxes[i].p2.x; - surface->clips[i].y2 = boxes[i].p2.y; - } + surface->has_clip = TRUE; - _cairo_region_boxes_fini (region, boxes); - } - else { - if (surface->clips) { - free (surface->clips); - surface->clips = NULL; - surface->n_clips = 0; - } + status = _cairo_region_get_boxes (region, &n_boxes, &boxes); + if (n_boxes == 0) + return CAIRO_STATUS_SUCCESS; + if (status) + return status; + + if (surface->n_clips != n_boxes) { + if (surface->clips) + free (surface->clips); + + surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion)); + if (!surface->clips) { + surface->n_clips = 0; + _cairo_region_boxes_fini (region, boxes); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + surface->n_clips = n_boxes; + } + + for (i = 0; i < n_boxes; i++) { + surface->clips[i].x1 = boxes[i].p1.x; + surface->clips[i].y1 = boxes[i].p1.y; + surface->clips[i].x2 = boxes[i].p2.x - 1; + surface->clips[i].y2 = boxes[i].p2.y - 1; + } + + _cairo_region_boxes_fini (region, boxes); + } else { + surface->has_clip = FALSE; + if (surface->clips) { + free (surface->clips); + surface->clips = NULL; + surface->n_clips = 0; + } } return CAIRO_STATUS_SUCCESS; @@ -1314,46 +1355,51 @@ _cairo_directfb_abstract_surface_get_extents (void *abstract_su cairo_rectangle_int_t *rectangle) { cairo_directfb_surface_t *surface = abstract_surface; - + D_DEBUG_AT (CairoDFB_Surface, - "%s( surface=%p, rectangle=%p ).\n", - __FUNCTION__, surface, rectangle); - - if (rectangle) { - if (!surface->local) { - surface->dfbsurface->GetSize (surface->dfbsurface, - &surface->width, &surface->height); - } - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; + "%s( surface=%p, rectangle=%p ).\n", + __FUNCTION__, surface, rectangle); + + if (!surface->local) { + surface->dfbsurface->GetSize (surface->dfbsurface, + &surface->width, &surface->height); } - + + rectangle->x = 0; + rectangle->y = 0; + rectangle->width = surface->width; + rectangle->height = surface->height; + return CAIRO_STATUS_SUCCESS; } #if DFB_SHOW_GLYPHS -static cairo_directfb_font_cache_t* -_directfb_allocate_font_cache (IDirectFB *dfb, int width, int height) +static cairo_status_t +_directfb_allocate_font_cache (IDirectFB *dfb, + int width, int height, + cairo_directfb_font_cache_t **out) { cairo_directfb_font_cache_t *cache; + cairo_status_t status; - cache = calloc (1, sizeof(cairo_directfb_font_cache_t)); - if (!cache) - return NULL; + cache = calloc (1, sizeof (cairo_directfb_font_cache_t)); + if (cache == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); cache->dfb = dfb; - cache->dfbsurface = _directfb_buffer_surface_create (dfb, - _directfb_argb_font ? DSPF_ARGB : DSPF_A8, width, height); - if (!cache->dfbsurface) { + status = _directfb_buffer_surface_create (dfb, + _directfb_argb_font ? DSPF_ARGB : DSPF_A8, + width, height, + &cache->dfbsurface); + if (status) { free (cache); - return NULL; + return status; } + cache->width = width; cache->height = height; - - return cache; + *out = cache; + return CAIRO_STATUS_SUCCESS; } static void @@ -1371,239 +1417,238 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, cairo_directfb_font_cache_t **ret_cache, DFBRectangle *rects, DFBPoint *points, - int *ret_num ) + int *ret_num) { - cairo_status_t ret; + cairo_status_t status; cairo_scaled_glyph_t *chars[num_glyphs]; int num_chars = 0; - cairo_directfb_font_cache_t *cache = NULL; + cairo_directfb_font_cache_t *cache = NULL; int n = 0; int x = 0; int y = 0; int w = 8; int h = 8; int i; - + D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs ); - if (scaled_font->surface_private) { - cache = scaled_font->surface_private; - x = cache->x; - y = cache->y; - } + _cairo_cache_freeze (scaled_font->glyphs); - _cairo_cache_freeze( scaled_font->glyphs ); + if (scaled_font->surface_private) { + cache = scaled_font->surface_private; + x = cache->x; + y = cache->y; + } for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - cairo_image_surface_t *img; - - D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index ); + cairo_scaled_glyph_t *scaled_glyph; + cairo_image_surface_t *img; - ret = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (ret) { - _cairo_cache_thaw( scaled_font->glyphs ); - return ret; - } - - img = scaled_glyph->surface; - switch (img->format) { - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_ARGB32: - break; - default: - D_DEBUG_AT (CairoDFB_Font, - " -> Unsupported font format %d!\n", img->format); - _cairo_cache_thaw( scaled_font->glyphs ); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0); - points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0); - -// D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n ); + D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index ); - if (points[n].x >= surface->width || - points[n].y >= surface->height || - points[n].x+img->width <= 0 || - points[n].y+img->height <= 0) - { - D_DEBUG_AT (CairoDFB_Font, - " -> Unsupported font format %d!\n", img->format); - continue; - } - - if (!scaled_glyph->surface_private) { - DFBRectangle *rect; - - if (x+img->width > 2048) { - x = 0; - y = h; - h = 0; - } - - rects[n].x = x; - rects[n].y = y; - rects[n].w = img->width; - rects[n].h = img->height; - - x += img->width; - h = MAX (h, img->height); - w = MAX (w, x); - - /* Remember glyph location */ - rect = malloc (sizeof(DFBRectangle)); - if (!rect) { - _cairo_cache_thaw( scaled_font->glyphs ); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - *rect = rects[n]; - - scaled_glyph->surface_private = rect; - chars[num_chars++] = scaled_glyph; - - D_DEBUG_AT (CairoDFB_Font, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n", - rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph); - } - else { - rects[n] = *((DFBRectangle *)scaled_glyph->surface_private); - - D_DEBUG_AT (CairoDFB_Font, " -> exists at %4d,%2d\n", rects[n].x, rects[n].y); - } - - n++; + status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + if (status) { + _cairo_cache_thaw (scaled_font->glyphs); + return status; + } + + img = scaled_glyph->surface; + switch (img->format) { + case CAIRO_FORMAT_A1: + case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_ARGB32: + break; + default: + D_DEBUG_AT (CairoDFB_Font, + " -> Unsupported font format %d!\n", img->format); + _cairo_cache_thaw (scaled_font->glyphs); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0); + points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0); + + // D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n ); + + if (points[n].x >= surface->width || + points[n].y >= surface->height || + points[n].x+img->width <= 0 || + points[n].y+img->height <= 0) + { + continue; + } + + if (scaled_glyph->surface_private == NULL) { + DFBRectangle *rect; + + if (x+img->width > 2048) { + x = 0; + y = h; + h = 0; + } + + rects[n].x = x; + rects[n].y = y; + rects[n].w = img->width; + rects[n].h = img->height; + + x += img->width; + h = MAX (h, img->height); + w = MAX (w, x); + + /* Remember glyph location */ + rect = malloc (sizeof (DFBRectangle)); + if (rect == NULL) { + _cairo_cache_thaw (scaled_font->glyphs); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + *rect = rects[n]; + + scaled_glyph->surface_private = rect; + chars[num_chars++] = scaled_glyph; + + D_DEBUG_AT (CairoDFB_Font, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n", + rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph); + } else { + rects[n] = *(DFBRectangle *) scaled_glyph->surface_private; + + D_DEBUG_AT (CairoDFB_Font, " -> exists at %4d,%2d\n", rects[n].x, rects[n].y); + } + + n++; } - - if (!n) { - _cairo_cache_thaw( scaled_font->glyphs ); - return CAIRO_INT_STATUS_NOTHING_TO_DO; + + if (n == 0) { + _cairo_cache_thaw (scaled_font->glyphs); + return CAIRO_INT_STATUS_NOTHING_TO_DO; } - + h += y; w = MAX (w, 8); h = MAX (h, 8); - + + /* XXX query maximum surface size */ + if (w > 2048 || h > 2048) { + _cairo_cache_thaw (scaled_font->glyphs); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + if (cache) { - if (cache->width < w || cache->height < h) { - cairo_directfb_font_cache_t *new_cache; - - w = MAX (w, cache->width); - h = MAX (h, cache->height); - - D_DEBUG_AT (CairoDFB_Font, " -> Reallocating font cache (%dx%d).\n", w, h); - - new_cache = _directfb_allocate_font_cache (surface->dfb, w, h); - if (!new_cache) { - _cairo_cache_thaw( scaled_font->glyphs ); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - new_cache->dfbsurface->Blit (new_cache->dfbsurface, - cache->dfbsurface, NULL, 0, 0); - - _directfb_destroy_font_cache (cache); - scaled_font->surface_private = cache = new_cache; - } + if (cache->width < w || cache->height < h) { + cairo_directfb_font_cache_t *new_cache; + + w = MAX (w, cache->width); + h = MAX (h, cache->height); + + D_DEBUG_AT (CairoDFB_Font, " -> Reallocating font cache (%dx%d).\n", w, h); + + status = _directfb_allocate_font_cache (surface->dfb, + w, h, + &new_cache); + if (status) { + _cairo_cache_thaw (scaled_font->glyphs); + return status; + } + + new_cache->dfbsurface->Blit (new_cache->dfbsurface, + cache->dfbsurface, NULL, 0, 0); + + _directfb_destroy_font_cache (cache); + scaled_font->surface_private = cache = new_cache; + } + } else { + D_DEBUG_AT (CairoDFB_Font, " -> Allocating font cache (%dx%d).\n", w, h); + + status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache); + if (status) { + _cairo_cache_thaw (scaled_font->glyphs); + return status; + } + + scaled_font->surface_backend = &_cairo_directfb_surface_backend; + scaled_font->surface_private = cache; } - else { - D_DEBUG_AT (CairoDFB_Font, " -> Allocating font cache (%dx%d).\n", w, h); - - cache = _directfb_allocate_font_cache (surface->dfb, w, h); - if (!cache) { - _cairo_cache_thaw( scaled_font->glyphs ); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - scaled_font->surface_backend = &cairo_directfb_surface_backend; - scaled_font->surface_private = cache; - } - + if (num_chars) { - unsigned char *data; - int pitch; - - if (cache->dfbsurface->Lock (cache->dfbsurface, - DSLF_WRITE, (void *)&data, &pitch)) - { - _cairo_cache_thaw( scaled_font->glyphs ); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - D_DEBUG_AT (CairoDFB_Font, " => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height); + unsigned char *data; + int pitch; - for (i = 0; i < num_chars; i++) { - cairo_image_surface_t *img = chars[i]->surface; - DFBRectangle *rect = chars[i]->surface_private; - unsigned char *dst = data; - unsigned char *src; - int j; - - D_DEBUG_AT (CairoDFB_Font, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]); + if (cache->dfbsurface->Lock (cache->dfbsurface, + DSLF_WRITE, (void *)&data, &pitch)) + { + _cairo_cache_thaw (scaled_font->glyphs); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - src = img->data; + D_DEBUG_AT (CairoDFB_Font, " => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height); - D_DEBUG_AT (CairoDFB_Font, " from %p\n", src); + for (i = 0; i < num_chars; i++) { + cairo_image_surface_t *img = chars[i]->surface; + DFBRectangle *rect = chars[i]->surface_private; + unsigned char *dst = data; + unsigned char *src; + int j; - dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x); - - D_DEBUG_AT (CairoDFB_Font, " to %4d,%2d (%p)\n", rect->x, rect->y, dst); + D_DEBUG_AT (CairoDFB_Font, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]); - if (img->format == CAIRO_FORMAT_A1) { - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - for (j = 0; j < rect->w; j++) - ((uint32_t *)dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0; - } - else { - for (j = 0; j < rect->w; j++) - dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0; - } - - dst += pitch; - src += img->stride; - } - } - else if (img->format == CAIRO_FORMAT_A8) { - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - for (j = 0; j < rect->w; j++) - ((uint32_t *)dst)[j] = src[j] * 0x01010101; - } - else { - direct_memcpy (dst, src, rect->w); - } - - dst += pitch; - src += img->stride; - } - } - else { /* ARGB32 */ - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - direct_memcpy (dst, src, rect->w<<2); - } - else { - for (j = 0; j < rect->w; j++) - dst[j] = ((uint32_t *)src)[j] >> 24; - } - - dst += pitch; - src += img->stride; - } - } - } - - cache->dfbsurface->Unlock (cache->dfbsurface); + src = img->data; + + D_DEBUG_AT (CairoDFB_Font, " from %p\n", src); + + dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x); + + D_DEBUG_AT (CairoDFB_Font, " to %4d,%2d (%p)\n", rect->x, rect->y, dst); + + if (img->format == CAIRO_FORMAT_A1) { + for (h = rect->h; h; h--) { + if (_directfb_argb_font) { + for (j = 0; j < rect->w; j++) + ((uint32_t *) dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0; + } else { + for (j = 0; j < rect->w; j++) + dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0; + } + + dst += pitch; + src += img->stride; + } + } else if (img->format == CAIRO_FORMAT_A8) { + for (h = rect->h; h; h--) { + if (_directfb_argb_font) { + for (j = 0; j < rect->w; j++) + ((uint32_t *) dst)[j] = src[j] * 0x01010101; + } else { + direct_memcpy (dst, src, rect->w); + } + + dst += pitch; + src += img->stride; + } + } else { /* ARGB32 */ + for (h = rect->h; h; h--) { + if (_directfb_argb_font) { + direct_memcpy (dst, src, rect->w<<2); + } else { + for (j = 0; j < rect->w; j++) + dst[j] = ((uint32_t *) src)[j] >> 24; + } + + dst += pitch; + src += img->stride; + } + } + } + + cache->dfbsurface->Unlock (cache->dfbsurface); } - _cairo_cache_thaw( scaled_font->glyphs ); + _cairo_cache_thaw (scaled_font->glyphs); cache->x = x; cache->y = y; - + D_DEBUG_AT (CairoDFB_Font, " => cache %d,%d, %p [%d]\n", x, y, cache, n); *ret_cache = cache; @@ -1616,13 +1661,13 @@ static void _cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) { cairo_directfb_font_cache_t *cache = scaled_font->surface_private; - + D_DEBUG_AT (CairoDFB_Font, - "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font); - - if (cache) { - _directfb_destroy_font_cache (cache); - scaled_font->surface_private = NULL; + "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font); + + if (cache != NULL) { + _directfb_destroy_font_cache (cache); + scaled_font->surface_private = NULL; } } @@ -1634,7 +1679,7 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, "%s( scaled_glyph=%p, scaled_font=%p ).\n", __FUNCTION__, scaled_glyph, scaled_font); - if (scaled_glyph->surface_private) { + if (scaled_glyph->surface_private != NULL) { free (scaled_glyph->surface_private); scaled_glyph->surface_private = NULL; } @@ -1651,62 +1696,88 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst, { cairo_directfb_surface_t *dst = abstract_dst; cairo_directfb_font_cache_t *cache; - cairo_status_t ret; + cairo_status_t status; DFBSurfaceBlittingFlags flags; DFBSurfaceBlendFunction sblend; DFBSurfaceBlendFunction dblend; - DFBColor color; DFBRectangle rects[num_glyphs]; DFBPoint points[num_glyphs]; int num; - + const cairo_color_t *color; + + D_DEBUG_AT (CairoDFB_Font, - "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n", - __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font); - + "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n", + __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font); + if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* Fallback if we need to emulate clip regions */ + if (dst->base.clip && + (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION || + dst->base.clip->surface != NULL)) + { return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_directfb_get_operator (op, &sblend, &dblend) || - sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) - return CAIRO_INT_STATUS_UNSUPPORTED; - - ret = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs, - &cache, &rects[0], &points[0], &num); - if (ret) { - if (ret == CAIRO_INT_STATUS_NOTHING_TO_DO) - ret = CAIRO_STATUS_SUCCESS; - return ret; } - - color.a = ((cairo_solid_pattern_t *)pattern)->color.alpha_short >> 8; - color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short >> 8; - color.g = ((cairo_solid_pattern_t *)pattern)->color.green_short >> 8; - color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short >> 8; - + + /* XXX Unbounded operators are not handled correctly */ + if (! _cairo_operator_bounded_by_mask (op)) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (! _cairo_operator_bounded_by_source (op)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (! _directfb_get_operator (op, &sblend, &dblend) || + sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) + { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + status = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs, + &cache, &rects[0], &points[0], &num); + if (status) { + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + status = CAIRO_STATUS_SUCCESS; + return status; + } + + color = &((cairo_solid_pattern_t *) pattern)->color; + flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE; - if (color.a != 0xff) - flags |= DSBLIT_BLEND_COLORALPHA; - + if (! CAIRO_COLOR_IS_OPAQUE (color)) + flags |= DSBLIT_BLEND_COLORALPHA; + if (!_directfb_argb_font) { - if (sblend == DSBF_ONE) { - sblend = DSBF_SRCALPHA; - if (dblend == DSBF_ZERO) - dblend = DSBF_INVSRCALPHA; - } - } - + if (sblend == DSBF_ONE) { + sblend = DSBF_SRCALPHA; + if (dblend == DSBF_ZERO) + dblend = DSBF_INVSRCALPHA; + } + } + dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); - + if (dst->blit_premultiplied) { + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red_short >> 8, + color->green_short >> 8, + color->blue_short >> 8, + color->alpha_short >> 8); + } else { + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red * 0xff, + color->green * 0xff, + color->blue * 0xff, + color->alpha * 0xff); + } + D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n"); - + RUN_CLIPPED (dst, NULL, - dst->dfbsurface->BatchBlit (dst->dfbsurface, - cache->dfbsurface, rects, points, num)); - + dst->dfbsurface->BatchBlit (dst->dfbsurface, + cache->dfbsurface, rects, points, num)); + return CAIRO_STATUS_SUCCESS; } #endif /* DFB_SHOW_GLYPHS */ @@ -1721,14 +1792,15 @@ _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_cont return a->dfb == b->dfb; } -static cairo_surface_backend_t cairo_directfb_surface_backend = { +static cairo_surface_backend_t +_cairo_directfb_surface_backend = { CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/ _cairo_directfb_surface_create_similar,/*create_similar*/ _cairo_directfb_surface_finish, /*finish*/ _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/ _cairo_directfb_surface_release_source_image,/*release_source_image*/ _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/ - _cairo_directfb_surface_release_dest_image,/*release_dest_image*/ + _cairo_directfb_surface_release_dest_image,/*release_dest_image*/ _cairo_directfb_surface_clone_similar,/*clone_similar*/ #if DFB_COMPOSITE _cairo_directfb_surface_composite,/*composite*/ @@ -1780,78 +1852,81 @@ static void cairo_directfb_surface_backend_init (IDirectFB *dfb) { static int done = 0; - + if (done) - return; - + return; + if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) { #if DFB_RECTANGLES - cairo_directfb_surface_backend.fill_rectangles = NULL; + _cairo_directfb_surface_backend.fill_rectangles = NULL; #endif #if DFB_COMPOSITE - cairo_directfb_surface_backend.composite = NULL; + _cairo_directfb_surface_backend.composite = NULL; #endif #if DFB_COMPOSITE_TRAPEZOIDS - cairo_directfb_surface_backend.composite_trapezoids = NULL; + _cairo_directfb_surface_backend.composite_trapezoids = NULL; #endif #if DFB_SHOW_GLYPHS - cairo_directfb_surface_backend.scaled_font_fini = NULL; - cairo_directfb_surface_backend.scaled_glyph_fini = NULL; - cairo_directfb_surface_backend.show_glyphs = NULL; + _cairo_directfb_surface_backend.scaled_font_fini = NULL; + _cairo_directfb_surface_backend.scaled_glyph_fini = NULL; + _cairo_directfb_surface_backend.show_glyphs = NULL; #endif - D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n"); - } - else { - DFBGraphicsDeviceDescription dsc; - - dfb->GetDeviceDescription (dfb, &dsc); - + D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n"); + } else { + DFBGraphicsDeviceDescription dsc; + + dfb->GetDeviceDescription (dfb, &dsc); + #if DFB_COMPOSITE -// if (!(dsc.acceleration_mask & DFXL_BLIT)) -// cairo_directfb_surface_backend.composite = NULL; + // if (!(dsc.acceleration_mask & DFXL_BLIT)) + // _cairo_directfb_surface_backend.composite = NULL; #endif #if DFB_COMPOSITE_TRAPEZOIDS -// if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES)) -// cairo_directfb_surface_backend.composite_trapezoids = NULL; + // if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES)) + // _cairo_directfb_surface_backend.composite_trapezoids = NULL; #endif } - + if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) { - _directfb_argb_font = 1; - D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n"); + _directfb_argb_font = 1; + D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n"); } done = 1; -} - +} cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) +cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) { cairo_directfb_surface_t *surface; DFBSurfacePixelFormat format; - + DFBSurfaceCapabilities caps; + D_ASSERT (dfb != NULL); D_ASSERT (dfbsurface != NULL); cairo_directfb_surface_backend_init (dfb); - - surface = calloc (1, sizeof(cairo_directfb_surface_t)); - if (!surface) - return NULL; - - dfbsurface->AddRef (dfbsurface); + + surface = calloc (1, sizeof (cairo_directfb_surface_t)); + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + + dfbsurface->AddRef (dfbsurface); dfbsurface->GetPixelFormat (dfbsurface, &format); dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height); surface->dfb = dfb; - surface->dfbsurface = dfbsurface; + surface->dfbsurface = dfbsurface; surface->format = _directfb_to_cairo_format (format); surface->content = _directfb_format_to_content (format); - _cairo_surface_init (&surface->base, - &cairo_directfb_surface_backend, surface->content); + dfbsurface->GetCapabilities (dfbsurface, &caps); + if (caps & DSCAPS_PREMULTIPLIED) + surface->blit_premultiplied = TRUE; + + _cairo_surface_init (&surface->base, + &_cairo_directfb_surface_backend, + surface->content); return &surface->base; } - diff --git a/gfx/cairo/cairo/src/cairo-directfb.h b/gfx/cairo/cairo/src/cairo-directfb.h index 6b3fcbdf5577..0396cb13a210 100644 --- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-directfb.h @@ -49,7 +49,7 @@ #include "cairo.h" -#ifdef CAIRO_HAS_DIRECTFB_SURFACE +#if CAIRO_HAS_DIRECTFB_SURFACE #include diff --git a/gfx/cairo/cairo/src/cairo-features-win32.h b/gfx/cairo/cairo/src/cairo-features-win32.h deleted file mode 100644 index 754b98ac2f44..000000000000 --- a/gfx/cairo/cairo/src/cairo-features-win32.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef CAIRO_FEATURES_H -#define CAIRO_FEATURES_H - -#define HAVE_WINDOWS_H 1 - -#define CAIRO_HAS_SVG_SURFACE 1 -#define CAIRO_HAS_PDF_SURFACE 1 -#define CAIRO_HAS_PS_SURFACE 1 -#define CAIRO_HAS_WIN32_SURFACE 1 -#define CAIRO_HAS_WIN32_FONT 1 -#define CAIRO_HAS_PNG_FUNCTIONS 1 - -#endif - diff --git a/gfx/cairo/cairo/src/cairo-font-face-twin-data.c b/gfx/cairo/cairo/src/cairo-font-face-twin-data.c new file mode 100644 index 000000000000..7a703244ac3c --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-font-face-twin-data.c @@ -0,0 +1,1030 @@ +/* See cairo-font-face-twin.c for copyright info */ + +#include "cairoint.h" + +const int8_t _cairo_twin_outlines[] = { +/* 0x0 '\0' offset 0 */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 24, -42, + 'l', 24, 0, + 'l', 0, 0, + 'e', +/* 0x20 ' ' offset 28 */ + 0, 4, 0, 0, 2, 3, + -128, 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'e', +/* 0x21 '!' offset 40 */ + 0, 4, 42, 0, 3, 3, + 0, 2, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -42, + 'l', 2, -14, + 'm', 2, -4, + 'c', 1, -4, 0, -3, 0, -2, + 'c', 0, -1, 1, 0, 2, 0, + 'c', 3, 0, 4, -1, 4, -2, + 'c', 4, -3, 3, -4, 2, -4, + 'e', +/* 0x22 '"' offset 90 */ + 0, 16, 42, -28, 2, 3, + 0, 16, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, -28, + 'm', 16, -42, + 'l', 16, -28, + 'e', +/* 0x23 '#' offset 114 */ + 0, 30, 50, 14, 2, 5, + 0, 30, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 16, -50, + 'l', 2, 14, + 'm', 28, -50, + 'l', 14, 14, + 'm', 2, -24, + 'l', 30, -24, + 'm', 0, -12, + 'l', 28, -12, + 'e', +/* 0x24 '$' offset 152 */ + 0, 28, 50, 8, 4, 4, + 0, 10, 18, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 10, -50, + 'l', 10, 8, + 'm', 18, -50, + 'l', 18, 8, + 'm', 28, -36, + 'c', 24, -42, 18, -42, 14, -42, + 'c', 10, -42, 0, -42, 0, -34, + 'c', 0, -25, 8, -24, 14, -22, + 'c', 20, -20, 28, -19, 28, -9, + 'c', 28, 0, 18, 0, 14, 0, + 'c', 10, 0, 4, 0, 0, -6, + 'e', +/* 0x25 '%' offset 224 */ + 0, 36, 42, 0, 4, 7, + 0, 14, 22, 36, /* snap_x */ + -42, -38, -28, -21, -15, -14, 0, /* snap_y */ + 'm', 10, -42, + 'c', 12, -41, 14, -40, 14, -36, + 'c', 14, -30, 11, -28, 6, -28, + 'c', 2, -28, 0, -30, 0, -34, + 'c', 0, -39, 3, -42, 8, -42, + 'l', 10, -42, + 'c', 18, -37, 28, -37, 36, -42, + 'l', 0, 0, + 'm', 28, -14, + 'c', 24, -14, 22, -11, 22, -6, + 'c', 22, -2, 24, 0, 28, 0, + 'c', 33, 0, 36, -2, 36, -8, + 'c', 36, -12, 34, -14, 30, -14, + 'l', 28, -14, + 'e', + 'X', 'X', 'X', +/* 0x26 '&' offset 323 */ + 0, 40, 42, 0, 4, 4, + 0, 10, 22, 40, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 40, -24, + 'c', 40, -27, 39, -28, 37, -28, + 'c', 29, -28, 32, 0, 12, 0, + 'c', 0, 0, 0, -8, 0, -10, + 'c', 0, -24, 22, -20, 22, -34, + 'c', 22, -45, 10, -45, 10, -34, + 'c', 10, -27, 25, 0, 36, 0, + 'c', 39, 0, 40, -1, 40, -4, + 'e', +/* 0x27 ''' offset 390 */ + 0, 4, 42, -30, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -38, + 'c', -1, -38, -1, -42, 2, -42, + 'c', 6, -42, 5, -33, 0, -30, + 'e', +/* 0x28 '(' offset 419 */ + 0, 14, 50, 14, 2, 3, + 0, 14, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 14, -50, + 'c', -5, -32, -5, -5, 14, 14, + 'e', +/* 0x29 ')' offset 441 */ + 0, 14, 50, 14, 2, 3, + 0, 14, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'c', 19, -34, 19, -2, 0, 14, + 'e', +/* 0x2a '*' offset 463 */ + 0, 20, 30, -6, 3, 3, + 0, 10, 20, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 10, -30, + 'l', 10, -6, + 'm', 0, -24, + 'l', 20, -12, + 'm', 20, -24, + 'l', 0, -12, + 'e', +/* 0x2b '+' offset 494 */ + 0, 36, 36, 0, 3, 4, + 0, 18, 36, /* snap_x */ + -21, -18, -15, 0, /* snap_y */ + 'm', 18, -36, + 'l', 18, 0, + 'm', 0, -18, + 'l', 36, -18, + 'e', +/* 0x2c ',' offset 520 */ + 0, 4, 4, 8, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 4, -2, + 'c', 4, 1, 0, 1, 0, -2, + 'c', 0, -5, 4, -5, 4, -2, + 'c', 4, 4, 2, 6, 0, 8, + 'e', +/* 0x2d '-' offset 556 */ + 0, 36, 18, -18, 2, 4, + 0, 36, /* snap_x */ + -21, -18, -15, 0, /* snap_y */ + 'm', 0, -18, + 'l', 36, -18, + 'e', +/* 0x2e '.' offset 575 */ + 0, 4, 4, 0, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -4, + 'c', -1, -4, -1, 0, 2, 0, + 'c', 5, 0, 5, -4, 2, -4, + 'e', +/* 0x2f '/' offset 604 */ + 0, 36, 50, 14, 2, 3, + 0, 36, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 36, -50, + 'l', 0, 14, + 'e', +/* 0x30 '0' offset 622 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 14, -42, + 'c', 9, -42, 0, -42, 0, -21, + 'c', 0, 0, 9, 0, 14, 0, + 'c', 19, 0, 28, 0, 28, -21, + 'c', 28, -42, 19, -42, 14, -42, + 'E', +/* 0x31 '1' offset 666 */ + 0, 28, 42, 0, 2, 3, + 0, 17, 28 /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 7, -34, + 'c', 11, -35, 15, -38, 17, -42, + 'l', 17, 0, + 'e', +/* 0x32 '2' offset 691 */ + 0, 28, 42, 0, 4, 4, + 0, 2, 26, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 2, -32, + 'c', 2, -34, 2, -42, 14, -42, + 'c', 26, -42, 26, -34, 26, -32, + 'c', 26, -30, 25, -25, 10, -10, + 'l', 0, 0, + 'l', 28, 0, + 'e', +/* 0x33 '3' offset 736 */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -26, -21, -15, 0, /* snap_y */ + 'm', 4, -42, + 'l', 26, -42, + 'l', 14, -26, + 'c', 21, -26, 28, -26, 28, -14, + 'c', 28, 0, 17, 0, 13, 0, + 'c', 8, 0, 3, -1, 0, -8, + 'e', +/* 0x34 '4' offset 780 */ + 0, 28, 42, 0, 3, 4, + 0, 20, 30, /* snap_x */ + -21, -15, -14, 0, /* snap_y */ + 'm', 20, 0, + 'l', 20, -42, + 'l', 0, -14, + 'l', 30, -14, + 'e', + 'X', 'X', 'X', +/* 0x35 '5' offset 809 */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -28, -21, -15, 0, /* snap_y */ + 'm', 24, -42, + 'l', 4, -42, + 'l', 2, -24, + 'c', 5, -27, 10, -28, 13, -28, + 'c', 16, -28, 28, -28, 28, -14, + 'c', 28, 0, 16, 0, 13, 0, + 'c', 10, 0, 3, 0, 0, -8, + 'e', +/* 0x36 '6' offset 860 */ + 0, 28, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -26, -21, -15, 0, /* snap_y */ + 'm', 24, -36, + 'c', 22, -41, 19, -42, 14, -42, + 'c', 9, -42, 0, -41, 0, -19, + 'c', 0, -1, 9, 0, 13, 0, + 'c', 18, 0, 26, -3, 26, -13, + 'c', 26, -18, 23, -26, 13, -26, + 'c', 10, -26, 1, -24, 0, -14, + 'e', +/* 0x37 '7' offset 919 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 28, -42, + 'l', 8, 0, + 'e', + 'X', 'X', 'X', +/* 0x38 '8' offset 944 */ + 0, 28, 42, 0, 4, 4, + 0, 2, 26, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 14, -42, + 'c', 5, -42, 2, -40, 2, -34, + 'c', 2, -18, 28, -32, 28, -11, + 'c', 28, 0, 18, 0, 14, 0, + 'c', 10, 0, 0, 0, 0, -11, + 'c', 0, -32, 26, -18, 26, -34, + 'c', 26, -40, 23, -42, 14, -42, + 'E', +/* 0x39 '9' offset 1004 */ + 0, 28, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -21, -16, -15, 0, /* snap_y */ + 'm', 26, -28, + 'c', 25, -16, 13, -16, 13, -16, + 'c', 8, -16, 0, -19, 0, -29, + 'c', 0, -34, 3, -42, 13, -42, + 'c', 24, -42, 26, -32, 26, -23, + 'c', 26, -14, 24, 0, 12, 0, + 'c', 7, 0, 4, -2, 2, -6, + 'e', +/* 0x3a ':' offset 1063 */ + 0, 4, 28, 0, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -28, + 'c', -1, -28, -1, -24, 2, -24, + 'c', 5, -24, 5, -28, 2, -28, + 'm', 2, -4, + 'c', -1, -4, -1, 0, 2, 0, + 'c', 5, 0, 5, -4, 2, -4, + 'e', +/* 0x3b ';' offset 1109 */ + 0, 4, 28, 8, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -28, + 'c', -1, -28, -1, -24, 2, -24, + 'c', 5, -24, 5, -28, 2, -28, + 'm', 4, -2, + 'c', 4, 1, 0, 1, 0, -2, + 'c', 0, -5, 4, -5, 4, -2, + 'c', 4, 3, 2, 6, 0, 8, + 'e', +/* 0x3c '<' offset 1162 */ + 0, 32, 36, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 32, -36, + 'l', 0, -18, + 'l', 32, 0, + 'e', +/* 0x3d '=' offset 1183 */ + 0, 36, 24, -12, 2, 5, + 0, 36, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 0, -24, + 'l', 36, -24, + 'm', 0, -12, + 'l', 36, -12, + 'e', +/* 0x3e '>' offset 1209 */ + 0, 32, 36, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -36, + 'l', 32, -18, + 'l', 0, 0, + 'e', +/* 0x3f '?' offset 1230 */ + 0, 24, 42, 0, 3, 4, + 0, 12, 24, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, -32, + 'c', 0, -34, 0, -42, 12, -42, + 'c', 24, -42, 24, -34, 24, -32, + 'c', 24, -29, 24, -24, 12, -20, + 'l', 12, -14, + 'm', 12, -4, + 'c', 9, -4, 9, 0, 12, 0, + 'c', 15, 0, 15, -4, 12, -4, + 'e', +/* 0x40 '@' offset 1288 */ + 0, 42, 42, 0, 1, 6, + 30, /* snap_x */ + -42, -32, -21, -15, -10, 0, /* snap_y */ + 'm', 30, -26, + 'c', 28, -31, 24, -32, 21, -32, + 'c', 10, -32, 10, -23, 10, -19, + 'c', 10, -13, 11, -10, 19, -10, + 'c', 30, -10, 28, -21, 30, -32, + 'c', 27, -10, 30, -10, 34, -10, + 'c', 41, -10, 42, -19, 42, -22, + 'c', 42, -34, 34, -42, 21, -42, + 'c', 9, -42, 0, -34, 0, -21, + 'c', 0, -9, 8, 0, 21, 0, + 'c', 30, 0, 34, -3, 36, -6, + 'e', +/* 0x41 'A' offset 1375 */ + 0, 32, 42, 0, 2, 4, + 0, 32, /* snap_x */ + -21, -15, -14, 0, /* snap_y */ + 'm', 0, 0, + 'l', 16, -42, + 'l', 32, 0, + 'm', 6, -14, + 'l', 26, -14, + 'e', + 'X', 'X', 'X', +/* 0x42 'B' offset 1406 */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 18, -42, + 'c', 32, -42, 32, -22, 18, -22, + 'l', 0, -22, + 'l', 18, -22, + 'c', 32, -22, 32, 0, 18, 0, + 'E', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x43 'C' offset 1455 */ + 0, 30, 42, 0, 2, 4, + 0, 30, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 30, -32, + 'c', 26, -42, 21, -42, 16, -42, + 'c', 2, -42, 0, -29, 0, -21, + 'c', 0, -13, 2, 0, 16, 0, + 'c', 21, 0, 26, 0, 30, -10, + 'e', +/* 0x44 'D' offset 1499 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 14, -42, + 'c', 33, -42, 33, 0, 14, 0, + 'E', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x45 'E' offset 1534 */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 26, -42, + 'l', 0, -42, + 'l', 0, 0, + 'l', 26, 0, + 'm', 0, -22, + 'l', 16, -22, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x46 'F' offset 1572 */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 26, -42, + 'm', 0, -22, + 'l', 16, -22, + 'e', + 'X', 'X', 'X', +/* 0x47 'G' offset 1604 */ + 0, 30, 42, 0, 2, 5, + 0, 30, /* snap_x */ + -42, -21, -16, -15, 0, /* snap_y */ + 'm', 30, -32, + 'c', 26, -42, 21, -42, 16, -42, + 'c', 2, -42, 0, -29, 0, -21, + 'c', 0, -13, 2, 0, 16, 0, + 'c', 28, 0, 30, -7, 30, -16, + 'l', 20, -16, + 'e', + 'X', 'X', 'X', +/* 0x48 'H' offset 1655 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 28, -42, + 'l', 28, 0, + 'm', 0, -22, + 'l', 28, -22, + 'e', +/* 0x49 'I' offset 1686 */ + 0, 0, 42, 0, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'e', +/* 0x4a 'J' offset 1703 */ + 0, 20, 42, 0, 2, 3, + 0, 20, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 20, -42, + 'l', 20, -10, + 'c', 20, 3, 0, 3, 0, -10, + 'l', 0, -14, + 'e', +/* 0x4b 'K' offset 1731 */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 28, -42, + 'l', 0, -14, + 'm', 10, -24, + 'l', 28, 0, + 'e', +/* 0x4c 'L' offset 1761 */ + 0, 24, 42, 0, 2, 3, + 0, 24, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'l', 24, 0, + 'e', + 'X', 'X', 'X', +/* 0x4d 'M' offset 1785 */ + 0, 32, 42, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 16, 0, + 'l', 32, -42, + 'l', 32, 0, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x4e 'N' offset 1821 */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 28, 0, + 'l', 28, -42, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x4f 'O' offset 1851 */ + 0, 32, 42, 0, 2, 4, + 0, 32, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 16, -42, + 'c', 2, -42, 0, -29, 0, -21, + 'c', 0, -13, 2, 0, 16, 0, + 'c', 30, 0, 32, -13, 32, -21, + 'c', 32, -29, 30, -42, 16, -42, + 'E', +/* 0x50 'P' offset 1895 */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -21, -20, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 18, -42, + 'c', 32, -42, 32, -20, 18, -20, + 'l', 0, -20, + 'e', + 'X', 'X', 'X', +/* 0x51 'Q' offset 1931 */ + 0, 32, 42, 4, 2, 4, + 0, 32, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 16, -42, + 'c', 2, -42, 0, -29, 0, -21, + 'c', 0, -13, 2, 0, 16, 0, + 'c', 30, 0, 32, -13, 32, -21, + 'c', 32, -29, 30, -42, 16, -42, + 'm', 18, -8, + 'l', 30, 4, + 'e', +/* 0x52 'R' offset 1981 */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 0, -42, + 'l', 18, -42, + 'c', 32, -42, 31, -22, 18, -22, + 'l', 0, -22, + 'm', 14, -22, + 'l', 28, 0, + 'e', + 'X', 'X', 'X', +/* 0x53 'S' offset 2023 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 28, -36, + 'c', 25, -41, 21, -42, 14, -42, + 'c', 10, -42, 0, -42, 0, -34, + 'c', 0, -17, 28, -28, 28, -9, + 'c', 28, 0, 19, 0, 14, 0, + 'c', 7, 0, 3, -1, 0, -6, + 'e', +/* 0x54 'T' offset 2074 */ + 0, 28, 42, 0, 3, 4, + 0, 14, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 14, -42, + 'l', 14, 0, + 'm', 0, -42, + 'l', 28, -42, + 'e', +/* 0x55 'U' offset 2100 */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, -12, + 'c', 0, 4, 28, 4, 28, -12, + 'l', 28, -42, + 'e', +/* 0x56 'V' offset 2128 */ + 0, 32, 42, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 16, 0, + 'l', 32, -42, + 'e', + 'X', 'X', 'X', +/* 0x57 'W' offset 2152 */ + 0, 40, 42, 0, 2, 3, + 0, 40, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 10, 0, + 'l', 20, -42, + 'l', 30, 0, + 'l', 40, -42, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x58 'X' offset 2188 */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 28, 0, + 'm', 28, -42, + 'l', 0, 0, + 'e', +/* 0x59 'Y' offset 2212 */ + 0, 32, 42, 0, 3, 3, + 0, 16, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 16, -22, + 'l', 16, 0, + 'm', 32, -42, + 'l', 16, -22, + 'e', +/* 0x5a 'Z' offset 2240 */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 28, 0, + 'l', 0, 0, + 'l', 28, -42, + 'l', 0, -42, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x5b '[' offset 2271 */ + 0, 14, 44, 0, 2, 4, + 0, 14, /* snap_x */ + -44, -21, -15, 0, /* snap_y */ + 'm', 14, -44, + 'l', 0, -44, + 'l', 0, 0, + 'l', 14, 0, + 'e', +/* 0x5c '\' offset 2296 */ + 0, 36, 50, 14, 2, 3, + 0, 36, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', 36, 14, + 'e', +/* 0x5d ']' offset 2314 */ + 0, 14, 44, 0, 2, 4, + 0, 14, /* snap_x */ + -44, -21, -15, 0, /* snap_y */ + 'm', 0, -44, + 'l', 14, -44, + 'l', 14, 0, + 'l', 0, 0, + 'e', +/* 0x5e '^' offset 2339 */ + 0, 32, 46, -18, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -18, + 'l', 16, -46, + 'l', 32, -18, + 'e', + 'X', 'X', 'X', +/* 0x5f '_' offset 2363 */ + 0, 36, 0, 0, 2, 3, + 0, 36, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 36, 0, + 'e', +/* 0x60 '`' offset 2381 */ + 0, 4, 42, -30, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 4, -42, + 'c', 2, -40, 0, -39, 0, -32, + 'c', 0, -31, 1, -30, 2, -30, + 'c', 5, -30, 5, -34, 2, -34, + 'e', +/* 0x61 'a' offset 2417 */ + 0, 24, 28, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -28, + 'l', 24, 0, + 'm', 24, -22, + 'c', 21, -27, 18, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -1, 24, -6, + 'e', +/* 0x62 'b' offset 2467 */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -22, + 'c', 3, -26, 6, -28, 11, -28, + 'c', 22, -28, 24, -19, 24, -14, + 'c', 24, -9, 22, 0, 11, 0, + 'c', 6, 0, 3, -2, 0, -6, + 'e', +/* 0x63 'c' offset 2517 */ + 0, 24, 28, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -22, + 'c', 21, -26, 18, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -2, 24, -6, + 'e', +/* 0x64 'd' offset 2561 */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -42, + 'l', 24, 0, + 'm', 24, -22, + 'c', 21, -26, 18, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -2, 24, -6, + 'e', +/* 0x65 'e' offset 2611 */ + 0, 24, 28, 0, 2, 5, + 0, 24, /* snap_x */ + -28, -21, -16, -15, 0, /* snap_y */ + 'm', 0, -16, + 'l', 24, -16, + 'c', 24, -20, 24, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -2, 24, -6, + 'e', +/* 0x66 'f' offset 2659 */ + 0, 16, 42, 0, 3, 5, + 0, 6, 16, /* snap_x */ + -42, -28, -21, -15, 0, /* snap_y */ + 'm', 16, -42, + 'c', 8, -42, 6, -40, 6, -34, + 'l', 6, 0, + 'm', 0, -28, + 'l', 14, -28, + 'e', +/* 0x67 'g' offset 2693 */ + 0, 24, 28, 14, 2, 5, + 0, 24, /* snap_x */ + -28, -21, -15, 0, 14, /* snap_y */ + 'm', 24, -28, + 'l', 24, 4, + 'c', 23, 14, 16, 14, 13, 14, + 'c', 10, 14, 8, 14, 6, 12, + 'm', 24, -22, + 'c', 21, -26, 18, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -2, 24, -6, + 'e', +/* 0x68 'h' offset 2758 */ + 0, 22, 42, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -20, + 'c', 8, -32, 22, -31, 22, -20, + 'l', 22, 0, + 'e', +/* 0x69 'i' offset 2790 */ + 0, 4, 44, 0, 3, 3, + 0, 2, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'c', 0, -39, 4, -39, 4, -42, + 'c', 4, -45, 0, -45, 0, -42, + 'm', 2, -28, + 'l', 2, 0, + 'e', +/* 0x6a 'j' offset 2826 */ + -8, 4, 44, 14, 3, 4, + 0, 2, 4, /* snap_x */ + -21, -15, 0, 14, /* snap_y */ + 'm', 0, -42, + 'c', 0, -39, 4, -39, 4, -42, + 'c', 4, -45, 0, -45, 0, -42, + 'm', 2, -28, + 'l', 2, 6, + 'c', 2, 13, -1, 14, -8, 14, + 'e', +/* 0x6b 'k' offset 2870 */ + 0, 22, 42, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 20, -28, + 'l', 0, -8, + 'm', 8, -16, + 'l', 22, 0, + 'e', +/* 0x6c 'l' offset 2900 */ + 0, 0, 42, 0, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'e', +/* 0x6d 'm' offset 2917 */ + 0, 44, 28, 0, 3, 4, + 0, 22, 44, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -20, + 'c', 5, -29, 22, -33, 22, -20, + 'l', 22, 0, + 'm', 22, -20, + 'c', 27, -29, 44, -33, 44, -20, + 'l', 44, 0, + 'e', +/* 0x6e 'n' offset 2963 */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -20, + 'c', 4, -28, 22, -34, 22, -20, + 'l', 22, 0, + 'e', +/* 0x6f 'o' offset 2995 */ + 0, 26, 28, 0, 2, 4, + 0, 26, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 24, 0, 26, -9, 26, -14, + 'c', 26, -19, 24, -28, 13, -28, + 'e', +/* 0x70 'p' offset 3039 */ + 0, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 14, + 'm', 0, -22, + 'c', 3, -26, 6, -28, 11, -28, + 'c', 22, -28, 24, -19, 24, -14, + 'c', 24, -9, 22, 0, 11, 0, + 'c', 6, 0, 3, -2, 0, -6, + 'e', +/* 0x71 'q' offset 3089 */ + 0, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -28, + 'l', 24, 14, + 'm', 24, -22, + 'c', 21, -26, 18, -28, 13, -28, + 'c', 2, -28, 0, -19, 0, -14, + 'c', 0, -9, 2, 0, 13, 0, + 'c', 18, 0, 21, -2, 24, -6, + 'e', +/* 0x72 'r' offset 3139 */ + 0, 16, 28, 0, 2, 4, + 0, 16, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -16, + 'c', 2, -27, 7, -28, 16, -28, + 'e', +/* 0x73 's' offset 3168 */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 22, -22, + 'c', 22, -27, 16, -28, 11, -28, + 'c', 4, -28, 0, -26, 0, -22, + 'c', 0, -11, 22, -20, 22, -7, + 'c', 22, 0, 17, 0, 11, 0, + 'c', 6, 0, 0, -1, 0, -6, + 'e', +/* 0x74 't' offset 3219 */ + 0, 16, 42, 0, 3, 4, + 0, 6, 16, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 6, -42, + 'l', 6, -8, + 'c', 6, -2, 8, 0, 16, 0, + 'm', 0, -28, + 'l', 14, -28, + 'e', +/* 0x75 'u' offset 3252 */ + 0, 22, 28, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, -8, + 'c', 0, 6, 18, 0, 22, -8, + 'm', 22, -28, + 'l', 22, 0, + 'e', +/* 0x76 'v' offset 3283 */ + 0, 24, 28, 0, 2, 3, + 0, 24, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 12, 0, + 'l', 24, -28, + 'e', + 'X', 'X', 'X', +/* 0x77 'w' offset 3307 */ + 0, 32, 28, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 8, 0, + 'l', 16, -28, + 'l', 24, 0, + 'l', 32, -28, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x78 'x' offset 3343 */ + 0, 22, 28, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 22, 0, + 'm', 22, -28, + 'l', 0, 0, + 'e', +/* 0x79 'y' offset 3367 */ + -2, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -21, -15, 0, 14, /* snap_y */ + 'm', 0, -28, + 'l', 12, 0, + 'm', 24, -28, + 'l', 12, 0, + 'c', 6, 13, 0, 14, -2, 14, + 'e', +/* 0x7a 'z' offset 3399 */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 22, 0, + 'l', 0, 0, + 'l', 22, -28, + 'l', 0, -28, + 'e', + 'X', 'X', 'X', + 'X', 'X', 'X', +/* 0x7b '{' offset 3430 */ + 0, 16, 44, 0, 3, 5, + 0, 6, 16, /* snap_x */ + -44, -24, -21, -15, 0, /* snap_y */ + 'm', 16, -44, + 'c', 10, -44, 6, -42, 6, -36, + 'l', 6, -24, + 'l', 0, -24, + 'l', 6, -24, + 'l', 6, -8, + 'c', 6, -2, 10, 0, 16, 0, + 'e', +/* 0x7c '|' offset 3474 */ + 0, 0, 50, 14, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', 0, 14, + 'e', +/* 0x7d '}' offset 3491 */ + 0, 16, 44, 0, 3, 5, + 0, 10, 16, /* snap_x */ + -44, -24, -21, -15, 0, /* snap_y */ + 'm', 0, -44, + 'c', 6, -44, 10, -42, 10, -36, + 'l', 10, -24, + 'l', 16, -24, + 'l', 10, -24, + 'l', 10, -8, + 'c', 10, -2, 6, 0, 0, 0, + 'e', +/* 0x7e '~' offset 3535 */ + 0, 36, 24, -12, 2, 5, + 0, 36, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 0, -14, + 'c', 1, -21, 4, -24, 8, -24, + 'c', 18, -24, 18, -12, 28, -12, + 'c', 32, -12, 35, -15, 36, -22, + 'e', +}; + +const uint16_t _cairo_twin_charmap[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 40, 90, 114, 152, 224, 323, 390, + 419, 441, 463, 494, 520, 556, 575, 604, + 622, 666, 691, 736, 780, 809, 860, 919, + 944, 1004, 1063, 1109, 1162, 1183, 1209, 1230, + 1288, 1375, 1406, 1455, 1499, 1534, 1572, 1604, + 1655, 1686, 1703, 1731, 1761, 1785, 1821, 1851, + 1895, 1931, 1981, 2023, 2074, 2100, 2128, 2152, + 2188, 2212, 2240, 2271, 2296, 2314, 2339, 2363, + 2381, 2417, 2467, 2517, 2561, 2611, 2659, 2693, + 2758, 2790, 2826, 2870, 2900, 2917, 2963, 2995, + 3039, 3089, 3139, 3168, 3219, 3252, 3283, 3307, + 3343, 3367, 3399, 3430, 3474, 3491, 3535, 0, +}; + diff --git a/gfx/cairo/cairo/src/cairo-font-face-twin.c b/gfx/cairo/cairo/src/cairo-font-face-twin.c new file mode 100644 index 000000000000..d8e662f1faf9 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-font-face-twin.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2004 Keith Packard + * Copyright © 2008 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 Keith Packard + * + * Contributor(s): + * Keith Packard + * Behdad Esfahbod + */ + +#include "cairoint.h" + +/* + * This file implements a user-font rendering the decendant of the Hershey + * font coded by Keith Packard for use in the Twin window system. + * The actual font data is in cairo-font-face-twin-data.c + * + * Ported to cairo user font by Behdad Esfahbod. + */ + + +#define twin_glyph_left(g) ((g)[0]) +#define twin_glyph_right(g) ((g)[1]) +#define twin_glyph_ascent(g) ((g)[2]) +#define twin_glyph_descent(g) ((g)[3]) + +#define twin_glyph_n_snap_x(g) ((g)[4]) +#define twin_glyph_n_snap_y(g) ((g)[5]) +#define twin_glyph_snap_x(g) (&g[6]) +#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g)) +#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g)) + +#define SNAPI(p) (p) +#define SNAPH(p) (p) + +#define FX(g) ((g) / 64.) +#define FY(g) ((g) / 64.) + + +static cairo_status_t +twin_scaled_font_init (cairo_scaled_font_t *scaled_font, + cairo_t *cr, + cairo_font_extents_t *metrics) +{ + metrics->ascent = FY (50); + metrics->descent = FY (14); + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font, + unsigned long unicode, + unsigned long *glyph) +{ + /* We use an identity charmap. Which means we could live + * with no unicode_to_glyph method too. But we define this + * to map all unknown chars to a single unknown glyph to + * reduce pressure on cache. */ + + if (unicode < ARRAY_LENGTH (_cairo_twin_charmap)) + *glyph = unicode; + else + *glyph = 0; + + return CAIRO_STATUS_SUCCESS; +} + +#define SNAPX(p) _twin_snap (p, info.snap_x, info.n_snap_x) +#define SNAPY(p) _twin_snap (p, info.snap_y, info.n_snap_y) + +static double +_twin_snap (double v, int a, int b) +{ + return v; /* XXX */ +} + +static cairo_status_t +twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, + unsigned long glyph, + cairo_t *cr, + cairo_text_extents_t *metrics) +{ + double x1, y1, x2, y2, x3, y3; + const int8_t *b = _cairo_twin_outlines + + _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph]; + const int8_t *g = twin_glyph_draw(b); + + struct { + cairo_bool_t snap; + int snap_x; + int snap_y; + int n_snap_x; + int n_snap_y; + } info = {FALSE}; + + cairo_set_line_width (cr, 0.06); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + + for (;;) { + switch (*g++) { + case 'M': + cairo_close_path (cr); + /* fall through */ + case 'm': + x1 = FX(*g++); + y1 = FY(*g++); + if (info.snap) + { + x1 = SNAPX (x1); + y1 = SNAPY (y1); + } + cairo_move_to (cr, x1, y1); + continue; + case 'L': + cairo_close_path (cr); + /* fall through */ + case 'l': + x1 = FX(*g++); + y1 = FY(*g++); + if (info.snap) + { + x1 = SNAPX (x1); + y1 = SNAPY (y1); + } + cairo_line_to (cr, x1, y1); + continue; + case 'C': + cairo_close_path (cr); + /* fall through */ + case 'c': + x1 = FX(*g++); + y1 = FY(*g++); + x2 = FX(*g++); + y2 = FY(*g++); + x3 = FX(*g++); + y3 = FY(*g++); + if (info.snap) + { + x1 = SNAPX (x1); + y1 = SNAPY (y1); + x2 = SNAPX (x2); + y2 = SNAPY (y2); + x3 = SNAPX (x3); + y3 = SNAPY (y3); + } + cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); + continue; + case 'E': + cairo_close_path (cr); + /* fall through */ + case 'e': + cairo_stroke (cr); + break; + case 'X': + /* filler */ + continue; + } + break; + } + + metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr); + metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */; + if (info.snap) + metrics->x_advance = SNAPI (SNAPX (metrics->x_advance)); + + + return CAIRO_STATUS_SUCCESS; +} + +cairo_font_face_t * +_cairo_font_face_twin_create (cairo_font_slant_t slant, + cairo_font_weight_t weight) +{ + cairo_font_face_t *twin_font_face; + + twin_font_face = cairo_user_font_face_create (); + cairo_user_font_face_set_init_func (twin_font_face, twin_scaled_font_init); + cairo_user_font_face_set_render_glyph_func (twin_font_face, twin_scaled_font_render_glyph); + cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph); + + return twin_font_face; +} diff --git a/gfx/cairo/cairo/src/cairo-font-face.c b/gfx/cairo/cairo/src/cairo-font-face.c index 4f822a21ced3..30c8d9fb3de4 100644 --- a/gfx/cairo/cairo/src/cairo-font-face.c +++ b/gfx/cairo/cairo/src/cairo-font-face.c @@ -282,6 +282,7 @@ cairo_font_face_get_user_data (cairo_font_face_t *font_face, return _cairo_user_data_array_get_data (&font_face->user_data, key); } +slim_hidden_def (cairo_font_face_get_user_data); /** * cairo_font_face_set_user_data: @@ -306,11 +307,12 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face, cairo_destroy_func_t destroy) { if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return font_face->status; return _cairo_user_data_array_set_data (&font_face->user_data, key, user_data, destroy); } +slim_hidden_def (cairo_font_face_set_user_data); static const cairo_font_face_backend_t _cairo_toy_font_face_backend; @@ -566,6 +568,38 @@ _cairo_toy_font_face_destroy (void *abstract_face) _cairo_toy_font_face_fini (font_face); } +static cairo_status_t +_cairo_toy_font_face_scaled_font_get_implementation (void *abstract_font_face, + cairo_font_face_t **font_face_out) +{ + cairo_toy_font_face_t *font_face = abstract_font_face; + cairo_status_t status; + + if (font_face->base.status) + return font_face->base.status; + + if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend) + { + const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT; + + if (backend->get_implementation == NULL) { + *font_face_out = &font_face->base; + return CAIRO_STATUS_SUCCESS; + } + + status = backend->get_implementation (font_face, + font_face_out); + + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return _cairo_font_face_set_error (&font_face->base, status); + } + + status = _cairo_user_scaled_font_backend.get_implementation (font_face, + font_face_out); + + return _cairo_font_face_set_error (&font_face->base, status); +} + static cairo_status_t _cairo_toy_font_face_scaled_font_create (void *abstract_font_face, const cairo_matrix_t *font_matrix, @@ -574,7 +608,6 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face cairo_scaled_font_t **scaled_font) { cairo_toy_font_face_t *font_face = abstract_font_face; - const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT; cairo_status_t status; if (font_face->base.status) @@ -584,12 +617,31 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face if (status) return status; - return _cairo_font_face_set_error (&font_face->base, - backend->create_toy (font_face, - font_matrix, - ctm, - options, - scaled_font)); + if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend) + { + const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT; + + *scaled_font = NULL; + status = backend->create_toy (font_face, + font_matrix, + ctm, + options, + scaled_font); + + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return _cairo_font_face_set_error (&font_face->base, status); + + if (*scaled_font) + cairo_scaled_font_destroy (*scaled_font); + } + + status = _cairo_user_scaled_font_backend.create_toy (font_face, + font_matrix, + ctm, + options, + scaled_font); + + return _cairo_font_face_set_error (&font_face->base, status); } static cairo_bool_t @@ -641,6 +693,7 @@ cairo_toy_font_face_get_slant (cairo_font_face_t *font_face) } return toy_font_face->slant; } +slim_hidden_def (cairo_toy_font_face_get_slant); /** * cairo_toy_font_face_get_weight: @@ -662,10 +715,12 @@ cairo_toy_font_face_get_weight (cairo_font_face_t *font_face) } return toy_font_face->weight; } +slim_hidden_def (cairo_toy_font_face_get_weight); 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_get_implementation, _cairo_toy_font_face_scaled_font_create }; diff --git a/gfx/cairo/cairo/src/cairo-font-options.c b/gfx/cairo/cairo/src/cairo-font-options.c index b3fb274835e0..dedd3379eec4 100644 --- a/gfx/cairo/cairo/src/cairo-font-options.c +++ b/gfx/cairo/cairo/src/cairo-font-options.c @@ -39,7 +39,6 @@ static const cairo_font_options_t _cairo_font_options_nil = { CAIRO_ANTIALIAS_DEFAULT, CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_LCD_FILTER_DEFAULT, CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_METRICS_DEFAULT }; @@ -55,7 +54,6 @@ _cairo_font_options_init_default (cairo_font_options_t *options) { options->antialias = CAIRO_ANTIALIAS_DEFAULT; options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; - options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT; options->hint_style = CAIRO_HINT_STYLE_DEFAULT; options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; } @@ -66,7 +64,6 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, { options->antialias = other->antialias; options->subpixel_order = other->subpixel_order; - options->lcd_filter = other->lcd_filter; options->hint_style = other->hint_style; options->hint_metrics = other->hint_metrics; } @@ -192,8 +189,6 @@ cairo_font_options_merge (cairo_font_options_t *options, options->antialias = other->antialias; if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) options->subpixel_order = other->subpixel_order; - if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT) - options->lcd_filter = other->lcd_filter; if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT) options->hint_style = other->hint_style; if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT) @@ -226,7 +221,6 @@ cairo_font_options_equal (const cairo_font_options_t *options, return (options->antialias == other->antialias && options->subpixel_order == other->subpixel_order && - options->lcd_filter == other->lcd_filter && options->hint_style == other->hint_style && options->hint_metrics == other->hint_metrics); } @@ -252,8 +246,7 @@ cairo_font_options_hash (const cairo_font_options_t *options) return ((options->antialias) | (options->subpixel_order << 4) | - (options->lcd_filter << 8) | - (options->hint_style << 12) | + (options->hint_style << 8) | (options->hint_metrics << 16)); } slim_hidden_def (cairo_font_options_hash); @@ -334,49 +327,6 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options) return options->subpixel_order; } -/** - * cairo_font_options_set_lcd_filter: - * @options: a #cairo_font_options_t - * @lcd_filter: the new LCD filter - * - * Sets the LCD filter for the font options object. The LCD filter - * specifies how pixels are filtered when rendered with an antialiasing - * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for - * #cairo_lcd_filter_t for full details. - * - * Since: 1.8 - **/ -void -cairo_font_options_set_lcd_filter (cairo_font_options_t *options, - cairo_lcd_filter_t lcd_filter) -{ - if (cairo_font_options_status (options)) - return; - - options->lcd_filter = lcd_filter; -} -slim_hidden_def (cairo_font_options_set_lcd_filter); - -/** - * cairo_font_options_get_lcd_filter: - * @options: a #cairo_font_options_t - * - * Gets the LCD filter for the font options object. - * See the documentation for #cairo_lcd_filter_t for full details. - * - * Return value: the LCD filter for the font options object - * - * Since: 1.8 - **/ -cairo_lcd_filter_t -cairo_font_options_get_lcd_filter (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return CAIRO_LCD_FILTER_DEFAULT; - - return options->lcd_filter; -} - /** * cairo_font_options_set_hint_style: * @options: a #cairo_font_options_t diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index b50319a62b7c..a6d2bd0860b3 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -57,30 +57,6 @@ #include FT_SYNTHESIS_H #endif -#if HAVE_FT_LIBRARY_SETLCDFILTER -#include FT_LCD_FILTER_H -#endif - -/* Fontconfig version older than 2.6 didn't have these options */ -#ifndef FC_LCD_FILTER -#define FC_LCD_FILTER "lcdfilter" -#endif -/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */ -#ifndef FC_LCD_NONE -#define FC_LCD_NONE 0 -#define FC_LCD_DEFAULT 1 -#define FC_LCD_LIGHT 2 -#define FC_LCD_LEGACY 3 -#endif - -/* FreeType version older than 2.3.5(?) didn't have these options */ -#ifndef FT_LCD_FILTER_NONE -#define FT_LCD_FILTER_NONE 0 -#define FT_LCD_FILTER_DEFAULT 1 -#define FT_LCD_FILTER_LIGHT 2 -#define FT_LCD_FILTER_LEGACY 16 -#endif - #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) @@ -767,286 +743,23 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, return CAIRO_STATUS_SUCCESS; } -/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot - * into a different format. For example, we want to convert a - * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit - * ARGB or ABGR bitmap. - * - * this function prepares a target descriptor for this operation. - * - * input :: target bitmap descriptor. The function will set its - * 'width', 'rows' and 'pitch' fields, and only these - * - * slot :: the glyph slot containing the source bitmap. this - * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP - * - * mode :: the requested final rendering mode. supported values are - * MONO, NORMAL (i.e. gray), LCD and LCD_V - * - * the function returns the size in bytes of the corresponding buffer, - * it's up to the caller to allocate the corresponding memory block - * before calling _fill_xrender_bitmap - * - * it also returns -1 in case of error (e.g. incompatible arguments, - * like trying to convert a gray bitmap into a monochrome one) - */ -static int -_compute_xrender_bitmap_size(FT_Bitmap *target, - FT_GlyphSlot slot, - FT_Render_Mode mode) -{ - FT_Bitmap *ftbit; - int width, height, pitch; - - if (slot->format != FT_GLYPH_FORMAT_BITMAP) - return -1; - - /* compute the size of the final bitmap */ - ftbit = &slot->bitmap; - - width = ftbit->width; - height = ftbit->rows; - pitch = (width + 3) & ~3; - - switch (ftbit->pixel_mode) { - case FT_PIXEL_MODE_MONO: - if (mode == FT_RENDER_MODE_MONO) { - pitch = (((width + 31) & ~31) >> 3); - break; - } - /* fall-through */ - - case FT_PIXEL_MODE_GRAY: - if (mode == FT_RENDER_MODE_LCD || - mode == FT_RENDER_MODE_LCD_V) - { - /* each pixel is replicated into a 32-bit ARGB value */ - pitch = width * 4; - } - break; - - case FT_PIXEL_MODE_LCD: - if (mode != FT_RENDER_MODE_LCD) - return -1; - - /* horz pixel triplets are packed into 32-bit ARGB values */ - width /= 3; - pitch = width * 4; - break; - - case FT_PIXEL_MODE_LCD_V: - if (mode != FT_RENDER_MODE_LCD_V) - return -1; - - /* vert pixel triplets are packed into 32-bit ARGB values */ - height /= 3; - pitch = width * 4; - break; - - default: /* unsupported source format */ - return -1; - } - - target->width = width; - target->rows = height; - target->pitch = pitch; - target->buffer = NULL; - - return pitch * height; -} - -/* this functions converts the glyph bitmap found in a FT_GlyphSlot - * into a different format (see _compute_xrender_bitmap_size) - * - * you should call this function after _compute_xrender_bitmap_size - * - * target :: target bitmap descriptor. Note that its 'buffer' pointer - * must point to memory allocated by the caller - * - * slot :: the glyph slot containing the source bitmap - * - * mode :: the requested final rendering mode - * - * bgr :: boolean, set if BGR or VBGR pixel ordering is needed - */ -static void -_fill_xrender_bitmap(FT_Bitmap *target, - FT_GlyphSlot slot, - FT_Render_Mode mode, - int bgr) -{ - FT_Bitmap *ftbit = &slot->bitmap; - unsigned char *srcLine = ftbit->buffer; - unsigned char *dstLine = target->buffer; - int src_pitch = ftbit->pitch; - int width = target->width; - int height = target->rows; - int pitch = target->pitch; - int subpixel; - int h; - - subpixel = (mode == FT_RENDER_MODE_LCD || - mode == FT_RENDER_MODE_LCD_V); - - if (src_pitch < 0) - srcLine -= src_pitch * (ftbit->rows - 1); - - target->pixel_mode = ftbit->pixel_mode; - - switch (ftbit->pixel_mode) { - case FT_PIXEL_MODE_MONO: - if (subpixel) { - /* convert mono to ARGB32 values */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { - int x; - - for (x = 0; x < width; x++) { - if (srcLine[(x >> 3)] & (0x80 >> (x & 7))) - ((unsigned int *) dstLine)[x] = 0xffffffffU; - } - } - target->pixel_mode = FT_PIXEL_MODE_LCD; - - } else if (mode == FT_RENDER_MODE_NORMAL) { - /* convert mono to 8-bit gray */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { - int x; - - for (x = 0; x < width; x++) { - if (srcLine[(x >> 3)] & (0x80 >> (x & 7))) - dstLine[x] = 0xff; - } - } - target->pixel_mode = FT_PIXEL_MODE_GRAY; - - } else { - /* copy mono to mono */ - - int bytes = (width + 7) >> 3; - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) - memcpy (dstLine, srcLine, bytes); - } - break; - - case FT_PIXEL_MODE_GRAY: - if (subpixel) { - /* convert gray to ARGB32 values */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { - int x; - unsigned int *dst = (unsigned int *) dstLine; - - for (x = 0; x < width; x++) { - unsigned int pix = srcLine[x]; - - pix |= (pix << 8); - pix |= (pix << 16); - - dst[x] = pix; - } - } - target->pixel_mode = FT_PIXEL_MODE_LCD; - } else { - /* copy gray into gray */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) - memcpy (dstLine, srcLine, width); - } - break; - - case FT_PIXEL_MODE_LCD: - if (!bgr) { - /* convert horizontal RGB into ARGB32 */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { - int x; - unsigned char *src = srcLine; - unsigned int *dst = (unsigned int *) dstLine; - - for (x = 0; x < width; x++, src += 3) { - unsigned int pix; - - pix = ((unsigned int)src[0] << 16) | - ((unsigned int)src[1] << 8) | - ((unsigned int)src[2] ) | - ((unsigned int)src[1] << 24) ; - - dst[x] = pix; - } - } - } else { - /* convert horizontal BGR into ARGB32 */ - - for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { - - int x; - unsigned char *src = srcLine; - unsigned int *dst = (unsigned int *) dstLine; - - for (x = 0; x < width; x++, src += 3) { - unsigned int pix; - - pix = ((unsigned int)src[2] << 16) | - ((unsigned int)src[1] << 8) | - ((unsigned int)src[0] ) | - ((unsigned int)src[1] << 24) ; - - dst[x] = pix; - } - } - } - break; - - default: /* FT_PIXEL_MODE_LCD_V */ - /* convert vertical RGB into ARGB32 */ - if (!bgr) { - - for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) { - int x; - unsigned char* src = srcLine; - unsigned int* dst = (unsigned int *) dstLine; - - for (x = 0; x < width; x++, src += 1) { - unsigned int pix; -#if 1 - pix = ((unsigned int)src[0] << 16) | - ((unsigned int)src[src_pitch] << 8) | - ((unsigned int)src[src_pitch*2] ) | - 0xFF000000 ; -#else - pix = ((unsigned int)src[0] << 16) | - ((unsigned int)src[src_pitch] << 8) | - ((unsigned int)src[src_pitch*2] ) | - ((unsigned int)src[src_pitch] << 24) ; +/* Empirically-derived subpixel filtering values thanks to Keith + * Packard and libXft. */ +static const int filters[3][3] = { + /* red */ +#if 0 + { 65538*4/7,65538*2/7,65538*1/7 }, + /* green */ + { 65536*1/4, 65536*2/4, 65537*1/4 }, + /* blue */ + { 65538*1/7,65538*2/7,65538*4/7 }, #endif - dst[x] = pix; - } - } - } else { - - for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) { - int x; - unsigned char *src = srcLine; - unsigned int *dst = (unsigned int *) dstLine; - - for (x = 0; x < width; x++, src += 1) { - unsigned int pix; - - pix = ((unsigned int)src[src_pitch * 2] << 16) | - ((unsigned int)src[src_pitch] << 8) | - ((unsigned int)src[0] ) | - ((unsigned int)src[src_pitch] << 24) ; - - dst[x] = pix; - } - } - } - } -} - + { 65538*9/13,65538*3/13,65538*1/13 }, + /* green */ + { 65538*1/6, 65538*4/6, 65538*1/6 }, + /* blue */ + { 65538*1/13,65538*3/13,65538*9/13 }, +}; /* Fills in val->image with an image surface created from @bitmap */ @@ -1059,7 +772,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, int width, height, stride; unsigned char *data; int format = CAIRO_FORMAT_A8; - cairo_image_surface_t *image; + cairo_bool_t subpixel = FALSE; width = bitmap->width; height = bitmap->rows; @@ -1116,7 +829,11 @@ _get_bitmap_surface (FT_Bitmap *bitmap, case FT_PIXEL_MODE_LCD: case FT_PIXEL_MODE_LCD_V: case FT_PIXEL_MODE_GRAY: - if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) { + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_NONE: + default: stride = bitmap->pitch; if (own_buffer) { data = bitmap->buffer; @@ -1128,16 +845,104 @@ _get_bitmap_surface (FT_Bitmap *bitmap, memcpy (data, bitmap->buffer, stride * height); } format = CAIRO_FORMAT_A8; - } else { - /* if we get there, the data from the source bitmap - * really comes from _fill_xrender_bitmap, and is - * made of 32-bit ARGB or ABGR values */ - assert (own_buffer != 0); - assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); + break; + case CAIRO_ANTIALIAS_SUBPIXEL: { + int x, y; + unsigned char *in_line, *out_line, *in; + unsigned int *out; + unsigned int red, green, blue; + int rf, gf, bf; + int s; + int o, os; + unsigned char *data_rgba; + unsigned int width_rgba, stride_rgba; + int vmul = 1; + int hmul = 1; - data = bitmap->buffer; + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: + case CAIRO_SUBPIXEL_ORDER_BGR: + default: + width /= 3; + hmul = 3; + break; + case CAIRO_SUBPIXEL_ORDER_VRGB: + case CAIRO_SUBPIXEL_ORDER_VBGR: + vmul = 3; + height /= 3; + break; + } + /* + * Filter the glyph to soften the color fringes + */ + width_rgba = width; stride = bitmap->pitch; + stride_rgba = (width_rgba * 4 + 3) & ~3; + data_rgba = calloc (stride_rgba, height); + if (data_rgba == NULL) { + if (own_buffer) + free (bitmap->buffer); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + os = 1; + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_VRGB: + os = stride; + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: + default: + rf = 0; + gf = 1; + bf = 2; + break; + case CAIRO_SUBPIXEL_ORDER_VBGR: + os = stride; + case CAIRO_SUBPIXEL_ORDER_BGR: + bf = 0; + gf = 1; + rf = 2; + break; + } + in_line = bitmap->buffer; + out_line = data_rgba; + for (y = 0; y < height; y++) + { + in = in_line; + out = (unsigned int *) out_line; + in_line += stride * vmul; + out_line += stride_rgba; + for (x = 0; x < width * hmul; x += hmul) + { + red = green = blue = 0; + o = 0; + for (s = 0; s < 3; s++) + { + red += filters[rf][s]*in[x+o]; + green += filters[gf][s]*in[x+o]; + blue += filters[bf][s]*in[x+o]; + o += os; + } + red = red / 65536; + green = green / 65536; + blue = blue / 65536; + *out++ = (green << 24) | (red << 16) | (green << 8) | blue; + } + } + + /* Images here are stored in native format. The + * backend must convert to its own format as needed + */ + + if (own_buffer) + free (bitmap->buffer); + data = data_rgba; + stride = stride_rgba; format = CAIRO_FORMAT_ARGB32; + subpixel = TRUE; + break; + } } break; case FT_PIXEL_MODE_GRAY2: @@ -1149,20 +954,19 @@ _get_bitmap_surface (FT_Bitmap *bitmap, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - /* XXX */ - *surface = image = (cairo_image_surface_t *) + *surface = (cairo_image_surface_t *) cairo_image_surface_create_for_data (data, format, width, height, stride); - if (image->base.status) { + if ((*surface)->base.status) { free (data); return (*surface)->base.status; } - if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) - pixman_image_set_component_alpha (image->pixman_image, TRUE); + if (subpixel) + pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); - _cairo_image_surface_assume_ownership_of_data (image); + _cairo_image_surface_assume_ownership_of_data ((*surface)); return CAIRO_STATUS_SUCCESS; } @@ -1187,59 +991,16 @@ _render_glyph_outline (FT_Face face, cairo_font_options_t *font_options, cairo_image_surface_t **surface) { - int rgba = FC_RGBA_UNKNOWN; - int lcd_filter = FT_LCD_FILTER_LEGACY; FT_GlyphSlot glyphslot = face->glyph; FT_Outline *outline = &glyphslot->outline; FT_Bitmap bitmap; FT_BBox cbox; - unsigned int width, height; + FT_Matrix matrix; + int hmul = 1; + int vmul = 1; + unsigned int width, height, stride; + cairo_bool_t subpixel = FALSE; cairo_status_t status; - FT_Error fterror; - FT_Library library = glyphslot->library; - FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL; - - switch (font_options->antialias) { - case CAIRO_ANTIALIAS_NONE: - render_mode = FT_RENDER_MODE_MONO; - break; - - case CAIRO_ANTIALIAS_SUBPIXEL: - switch (font_options->subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - case CAIRO_SUBPIXEL_ORDER_RGB: - case CAIRO_SUBPIXEL_ORDER_BGR: - render_mode = FT_RENDER_MODE_LCD; - break; - - case CAIRO_SUBPIXEL_ORDER_VRGB: - case CAIRO_SUBPIXEL_ORDER_VBGR: - render_mode = FT_RENDER_MODE_LCD_V; - break; - } - - switch (font_options->lcd_filter) { - case CAIRO_LCD_FILTER_NONE: - lcd_filter = FT_LCD_FILTER_NONE; - break; - case CAIRO_LCD_FILTER_DEFAULT: - case CAIRO_LCD_FILTER_INTRA_PIXEL: - lcd_filter = FT_LCD_FILTER_LEGACY; - break; - case CAIRO_LCD_FILTER_FIR3: - lcd_filter = FT_LCD_FILTER_LIGHT; - break; - case CAIRO_LCD_FILTER_FIR5: - lcd_filter = FT_LCD_FILTER_DEFAULT; - break; - } - - break; - - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: - render_mode = FT_RENDER_MODE_NORMAL; - } FT_Outline_Get_CBox (outline, &cbox); @@ -1250,21 +1011,20 @@ _render_glyph_outline (FT_Face face, width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); + stride = (width * hmul + 3) & ~3; if (width * height == 0) { cairo_format_t format; /* Looks like fb handles zero-sized images just fine */ - switch (render_mode) { - case FT_RENDER_MODE_MONO: + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break; - case FT_RENDER_MODE_LCD: - case FT_RENDER_MODE_LCD_V: + case CAIRO_ANTIALIAS_SUBPIXEL: format= CAIRO_FORMAT_ARGB32; break; - case FT_RENDER_MODE_LIGHT: - case FT_RENDER_MODE_NORMAL: - case FT_RENDER_MODE_MAX: + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: default: format = CAIRO_FORMAT_A8; break; @@ -1276,74 +1036,74 @@ _render_glyph_outline (FT_Face face, return (*surface)->base.status; } else { - int bitmap_size; + matrix.xx = matrix.yy = 0x10000L; + matrix.xy = matrix.yx = 0; - switch (render_mode) { - case FT_RENDER_MODE_LCD: - if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) { - rgba = FC_RGBA_BGR; - } else { - rgba = FC_RGBA_RGB; + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_NONE: + bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + bitmap.num_grays = 1; + stride = ((width + 31) & -32) >> 3; + break; + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap.num_grays = 256; + stride = (width + 3) & -4; + break; + case CAIRO_ANTIALIAS_SUBPIXEL: + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_RGB: + case CAIRO_SUBPIXEL_ORDER_BGR: + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + default: + matrix.xx *= 3; + hmul = 3; + subpixel = TRUE; + break; + case CAIRO_SUBPIXEL_ORDER_VRGB: + case CAIRO_SUBPIXEL_ORDER_VBGR: + matrix.yy *= 3; + vmul = 3; + subpixel = TRUE; + break; } - break; - case FT_RENDER_MODE_LCD_V: - if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) { - rgba = FC_RGBA_VBGR; - } else { - rgba = FC_RGBA_VRGB; - } - break; - case FT_RENDER_MODE_MONO: - case FT_RENDER_MODE_LIGHT: - case FT_RENDER_MODE_NORMAL: - case FT_RENDER_MODE_MAX: - default: - break; + FT_Outline_Transform (outline, &matrix); + + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap.num_grays = 256; + stride = (width * hmul + 3) & -4; } -#if HAVE_FT_LIBRARY_SETLCDFILTER - FT_Library_SetLcdFilter (library, lcd_filter); -#endif - - fterror = FT_Render_Glyph (face->glyph, render_mode); - -#if HAVE_FT_LIBRARY_SETLCDFILTER - FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE); -#endif - - if (fterror != 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - bitmap_size = _compute_xrender_bitmap_size (&bitmap, - face->glyph, - render_mode); - if (bitmap_size < 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - bitmap.buffer = calloc (1, bitmap_size); + bitmap.pitch = stride; + bitmap.width = width * hmul; + bitmap.rows = height * vmul; + bitmap.buffer = calloc (stride, bitmap.rows); if (bitmap.buffer == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _fill_xrender_bitmap (&bitmap, face->glyph, render_mode, - (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR)); + FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); + + if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { + free (bitmap.buffer); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - /* Note: - * _get_bitmap_surface will free bitmap.buffer if there is an error - */ status = _get_bitmap_surface (&bitmap, TRUE, 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. Moreover, device - * offsets are position of glyph origin relative to top left while xMin - * and yMax are offsets of top left relative to origin. Another negation. - */ - cairo_surface_set_device_offset (&(*surface)->base, - (double)-glyphslot->bitmap_left, - (double)+glyphslot->bitmap_top); } + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinate of the control box needs to be negated. Moreover, device + * offsets are position of glyph origin relative to top left while xMin + * and yMax are offsets of top left relative to origin. Another negation. + */ + cairo_surface_set_device_offset (&(*surface)->base, + floor (-(double) cbox.xMin / 64.0), + floor (+(double) cbox.yMax / 64.0)); + return CAIRO_STATUS_SUCCESS; } @@ -1562,7 +1322,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) if (antialias) { cairo_subpixel_order_t subpixel_order; - int lcd_filter; /* disable hinting if requested */ if (FcPatternGetBool (pattern, @@ -1598,25 +1357,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; } - if (FcPatternGetInteger (pattern, - FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch) - { - switch (lcd_filter) { - case FC_LCD_NONE: - ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE; - break; - case FC_LCD_DEFAULT: - ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5; - break; - case FC_LCD_LIGHT: - ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3; - break; - case FC_LCD_LEGACY: - ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL; - break; - } - } - #ifdef FC_HINT_STYLE if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) @@ -1717,12 +1457,6 @@ _cairo_ft_options_merge (cairo_ft_options_t *options, if (other->base.hint_style == CAIRO_HINT_STYLE_NONE) options->base.hint_style = CAIRO_HINT_STYLE_NONE; - if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT) - options->base.lcd_filter = other->base.lcd_filter; - - if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE) - options->base.lcd_filter = CAIRO_LCD_FILTER_NONE; - if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { if (options->base.hint_style == CAIRO_HINT_STYLE_NONE) load_flags |= FT_LOAD_NO_HINTING; @@ -1746,11 +1480,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options, case CAIRO_SUBPIXEL_ORDER_DEFAULT: case CAIRO_SUBPIXEL_ORDER_RGB: case CAIRO_SUBPIXEL_ORDER_BGR: - load_target = FT_LOAD_TARGET_LCD; + load_target |= FT_LOAD_TARGET_LCD; break; case CAIRO_SUBPIXEL_ORDER_VRGB: case CAIRO_SUBPIXEL_ORDER_VBGR: - load_target = FT_LOAD_TARGET_LCD_V; + load_target |= FT_LOAD_TARGET_LCD_V; break; } } @@ -2483,6 +2217,7 @@ _cairo_ft_index_to_ucs4(void *abstract_font, const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, + NULL, _cairo_ft_scaled_font_create_toy, _cairo_ft_scaled_font_fini, _cairo_ft_scaled_glyph_init, @@ -2589,6 +2324,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, + NULL, /* direct implementation */ _cairo_ft_font_face_scaled_font_create }; @@ -2693,34 +2429,6 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options, } } - if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT) - { - if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch) - { - int lcd_filter; - - switch (options->lcd_filter) { - case CAIRO_LCD_FILTER_NONE: - lcd_filter = FT_LCD_FILTER_NONE; - break; - case CAIRO_LCD_FILTER_DEFAULT: - case CAIRO_LCD_FILTER_INTRA_PIXEL: - lcd_filter = FT_LCD_FILTER_LEGACY; - break; - case CAIRO_LCD_FILTER_FIR3: - lcd_filter = FT_LCD_FILTER_LIGHT; - break; - default: - case CAIRO_LCD_FILTER_FIR5: - lcd_filter = FT_LCD_FILTER_DEFAULT; - break; - } - - if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT) { if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) @@ -2861,10 +2569,14 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern) * cairo_set_font_face() or cairo_scaled_font_create(). The * #cairo_scaled_font_t returned from cairo_scaled_font_create() is * also for the FreeType backend and can be used with functions such - * as cairo_ft_scaled_font_lock_face(). + * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference + * to the FT_Face alive in a font-cache and the exact lifetime of the reference + * depends highly upon the exact usage pattern and is subject to external + * factors. You must not call FT_Done_Face() before the last reference to the + * #cairo_font_face_t has been dropped. * - * As an example, here is how one might correctly couple the lifetime of - * the FreeType face object to the #cairo_font_face_t: + * As an example, below is how one might correctly couple the lifetime of + * the FreeType face object to the #cairo_font_face_t. * * * static const cairo_user_data_key_t key; diff --git a/gfx/cairo/cairo/src/cairo-glitz-surface.c b/gfx/cairo/cairo/src/cairo-glitz-surface.c index d067e28b64fa..784bff984c48 100644 --- a/gfx/cairo/cairo/src/cairo-glitz-surface.c +++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c @@ -511,6 +511,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_glitz_surface_t *surface = abstract_surface; @@ -522,6 +524,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface, if (src->backend == surface->base.backend) { + *clone_offset_x = 0; + *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; @@ -539,6 +543,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface, _cairo_glitz_surface_create_similar (surface, content, image_src->width, image_src->height); + if (clone == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; if (clone->base.status) return clone->base.status; @@ -802,8 +808,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, _cairo_surface_create_similar_scratch (&dst->base, CAIRO_CONTENT_COLOR_ALPHA, gradient->n_stops, 1); - if (src->base.status) - { + if (src->base.status) { glitz_buffer_destroy (buffer); free (data); return src->base.status; @@ -1276,8 +1281,13 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, _cairo_glitz_surface_create_similar (&dst->base, CAIRO_CONTENT_ALPHA, 2, 1); - if (mask->base.status) - { + if (mask == NULL) { + _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); + if (src_pattern == &tmp_src_pattern.base) + _cairo_pattern_fini (&tmp_src_pattern.base); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + if (mask->base.status) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); if (src_pattern == &tmp_src_pattern.base) _cairo_pattern_fini (&tmp_src_pattern.base); @@ -1385,8 +1395,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, _cairo_surface_create_similar_scratch (&dst->base, CAIRO_CONTENT_ALPHA, width, height); - if (mask->base.status) - { + if (mask->base.status) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); free (data); cairo_surface_destroy (&image->base); @@ -2011,7 +2020,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface, if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH || glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT) - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_UNSUPPORTED; if (scaled_font->surface_private == NULL) { @@ -2244,6 +2253,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, if (!glyph_private || !glyph_private->area) { int glyph_width, glyph_height; + int clone_offset_x, clone_offset_y; image = &scaled_glyphs[i]->surface->base; glyph_width = scaled_glyphs[i]->surface->width; @@ -2255,11 +2265,16 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, 0, glyph_width, glyph_height, + &clone_offset_x, + &clone_offset_y, (cairo_surface_t **) &clone); if (status) goto UNLOCK; + assert (clone_offset_x == 0); + assert (clone_offset_y == 0); + x_offset = scaled_glyphs[i]->surface->base.device_transform.x0; y_offset = scaled_glyphs[i]->surface->base.device_transform.y0; x1 = _cairo_lround (glyphs[i].x - x_offset); @@ -2371,6 +2386,13 @@ _cairo_glitz_surface_is_similar (void *surface_a, glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface); glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface); + /* XXX Disable caching of glitz surfaces by the solid pattern cache. + * Until glitz has a mechanism for releasing resources on connection + * closure, we will attempt to access invalid pointers when evicting + * old surfaces from the solid pattern cache. + */ + return FALSE; + return drawable_a == drawable_b; } diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index 2980770921f6..00f498e03ef3 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -60,7 +60,7 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate); static void _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate); -static void +static cairo_status_t _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, const cairo_glyph_t *glyphs, int num_glyphs, @@ -314,6 +314,8 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child) * _cairo_gstate_is_redirected * @gstate: a #cairo_gstate_t * + * This space left intentionally blank. + * * Return value: %TRUE if the gstate is redirected to a target * different than the original, %FALSE otherwise. **/ @@ -372,6 +374,8 @@ _cairo_gstate_get_original_target (cairo_gstate_t *gstate) * _cairo_gstate_get_clip: * @gstate: a #cairo_gstate_t * + * This space left intentionally blank. + * * Return value: a pointer to the gstate's #cairo_clip_t structure. */ cairo_clip_t * @@ -945,6 +949,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate, cairo_bool_t *inside_ret) { cairo_status_t status; + cairo_box_t limit; cairo_traps_t traps; if (gstate->stroke_style.line_width <= 0.0) { @@ -954,7 +959,13 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate, _cairo_gstate_user_to_backend (gstate, &x, &y); + limit.p1.x = _cairo_fixed_from_double (x) - 1; + limit.p1.y = _cairo_fixed_from_double (y) - 1; + limit.p2.x = limit.p1.x + 2; + limit.p2.y = limit.p1.y + 2; + _cairo_traps_init (&traps); + _cairo_traps_limit (&traps, &limit); status = _cairo_path_fixed_stroke_to_traps (path, &gstate->stroke_style, @@ -1011,11 +1022,18 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate, cairo_bool_t *inside_ret) { cairo_status_t status; + cairo_box_t limit; cairo_traps_t traps; _cairo_gstate_user_to_backend (gstate, &x, &y); + limit.p1.x = _cairo_fixed_from_double (x) - 1; + limit.p1.y = _cairo_fixed_from_double (y) - 1; + limit.p2.x = limit.p1.x + 2; + limit.p2.y = limit.p1.y + 2; + _cairo_traps_init (&traps); + _cairo_traps_limit (&traps, &limit); status = _cairo_path_fixed_fill_to_traps (path, gstate->fill_rule, @@ -1461,16 +1479,16 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate, } cairo_status_t -_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward) +_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, + double x, + double y, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags) { cairo_status_t status; @@ -1482,7 +1500,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward); + cluster_flags); } cairo_status_t @@ -1522,12 +1540,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, return cairo_scaled_font_status (gstate->scaled_font); } -cairo_bool_t -_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate) -{ - return cairo_surface_has_show_text_glyphs (gstate->target); -} - cairo_status_t _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, const char *utf8, @@ -1536,7 +1548,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward) + cairo_text_cluster_flags_t cluster_flags) { cairo_status_t status; cairo_pattern_union_t source_pattern; @@ -1562,10 +1574,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, - transformed_glyphs, &num_glyphs); + status = _cairo_gstate_transform_glyphs_to_backend (gstate, + glyphs, num_glyphs, + transformed_glyphs, + &num_glyphs); - if (!num_glyphs) + if (status || num_glyphs == 0) goto CLEANUP_GLYPHS; status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); @@ -1586,7 +1600,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, * fast rasterizer in cairo, we may want to readjust this. * * Needless to say, do this only if show_text_glyphs is not available. */ - if (_cairo_gstate_has_show_text_glyphs (gstate) || + if (cairo_surface_has_show_text_glyphs (gstate->target) || _cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) { status = _cairo_surface_show_text_glyphs (gstate->target, gstate->op, @@ -1594,18 +1608,16 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, utf8, utf8_len, transformed_glyphs, num_glyphs, clusters, num_clusters, - backward, + cluster_flags, gstate->scaled_font); } else { cairo_path_fixed_t path; _cairo_path_fixed_init (&path); - CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex); status = _cairo_scaled_font_glyph_path (gstate->scaled_font, transformed_glyphs, num_glyphs, &path); - CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex); if (status == CAIRO_STATUS_SUCCESS) status = _cairo_surface_fill (gstate->target, @@ -1649,15 +1661,18 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, if (transformed_glyphs == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, - transformed_glyphs, NULL); + status = _cairo_gstate_transform_glyphs_to_backend (gstate, + glyphs, num_glyphs, + transformed_glyphs, + NULL); + if (status) + goto CLEANUP_GLYPHS; - CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex); status = _cairo_scaled_font_glyph_path (gstate->scaled_font, transformed_glyphs, num_glyphs, path); - CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex); + CLEANUP_GLYPHS: if (transformed_glyphs != stack_transformed_glyphs) cairo_glyph_free (transformed_glyphs); @@ -1697,7 +1712,7 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate) * This also uses information from the scaled font and the surface to * cull/drop glyphs that will not be visible. **/ -static void +static cairo_status_t _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, const cairo_glyph_t *glyphs, int num_glyphs, @@ -1710,20 +1725,24 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, cairo_matrix_t *device_transform = &gstate->target->device_transform; cairo_bool_t drop = FALSE; double x1 = 0, x2 = 0, y1 = 0, y2 = 0; + cairo_status_t status; if (num_transformed_glyphs != NULL) { cairo_rectangle_int_t surface_extents; double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font); drop = TRUE; + status = _cairo_gstate_int_clip_extents (gstate, &surface_extents); + if (_cairo_status_is_error (status)) + return status; - if (_cairo_gstate_int_clip_extents (gstate, &surface_extents)) + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { drop = FALSE; /* unbounded surface */ - else { + } else { if (surface_extents.width == 0 || surface_extents.height == 0) { /* No visible area. Don't draw anything */ *num_transformed_glyphs = 0; - return; + return CAIRO_STATUS_SUCCESS; } /* XXX We currently drop any glyphs that has its position outside * of the surface boundaries by a safety margin depending on the @@ -1803,4 +1822,6 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, } *num_transformed_glyphs = j; } + + return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-hull.c b/gfx/cairo/cairo/src/cairo-hull.c index 77ee7908acb0..008ba7fda30a 100644 --- a/gfx/cairo/cairo/src/cairo-hull.c +++ b/gfx/cairo/cairo/src/cairo-hull.c @@ -78,6 +78,13 @@ _cairo_hull_init (cairo_hull_t *hull, } } +static inline cairo_int64_t +_slope_length (cairo_slope_t *slope) +{ + return _cairo_int64_add (_cairo_int32x32_64_mul (slope->dx, slope->dx), + _cairo_int32x32_64_mul (slope->dy, slope->dy)); +} + static int _cairo_hull_vertex_compare (const void *av, const void *bv) { @@ -87,21 +94,21 @@ _cairo_hull_vertex_compare (const void *av, const void *bv) ret = _cairo_slope_compare (&a->slope, &b->slope); - /* In the case of two vertices with identical slope from the - extremal point discard the nearer point. */ - + /* + * In the case of two vertices with identical slope from the + * extremal point discard the nearer point. + */ if (ret == 0) { - cairo_fixed_48_16_t a_dist, b_dist; - a_dist = ((cairo_fixed_48_16_t) a->slope.dx * a->slope.dx + - (cairo_fixed_48_16_t) a->slope.dy * a->slope.dy); - b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx + - (cairo_fixed_48_16_t) b->slope.dy * b->slope.dy); + int cmp; + + cmp = _cairo_int64_cmp (_slope_length (&a->slope), + _slope_length (&b->slope)); + /* - * Use the point's ids to ensure a total ordering. - * a well-defined ordering, and avoid setting discard on - * both points. + * Use the points' ids to ensure a well-defined ordering, + * and avoid setting discard on both points. */ - if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) { + if (cmp < 0 || (cmp == 0 && a->id < b->id)) { a->discard = 1; ret = -1; } else { diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index 4225548a9a72..4aad77f051de 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -60,6 +60,10 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format) case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4: case PIXMAN_g4: case PIXMAN_g1: case PIXMAN_yuy2: case PIXMAN_yv12: +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) + case PIXMAN_x2b10g10r10: + case PIXMAN_a2b10g10r10: +#endif default: return CAIRO_FORMAT_INVALID; } @@ -81,6 +85,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format) case PIXMAN_a2b2g2r2: case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) + case PIXMAN_a2b10g10r10: +#endif return CAIRO_CONTENT_COLOR_ALPHA; case PIXMAN_x8r8g8b8: case PIXMAN_x8b8g8r8: @@ -103,6 +110,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format) case PIXMAN_g1: case PIXMAN_yuy2: case PIXMAN_yv12: +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) + case PIXMAN_x2b10g10r10: +#endif return CAIRO_CONTENT_COLOR; case PIXMAN_a8: case PIXMAN_a1: @@ -144,7 +154,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, return &surface->base; } -cairo_int_status_t +cairo_bool_t _pixman_format_from_masks (cairo_format_masks_t *masks, pixman_format_code_t *format_ret) { @@ -166,13 +176,13 @@ _pixman_format_from_masks (cairo_format_masks_t *masks, } else if (masks->alpha_mask) { format_type = PIXMAN_TYPE_A; } else { - return CAIRO_INT_STATUS_UNSUPPORTED; + return FALSE; } format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b); if (! pixman_format_supported_destination (format)) - return CAIRO_INT_STATUS_UNSUPPORTED; + return FALSE; /* Sanity check that we got out of PIXMAN_FORMAT exactly what we * expected. This avoid any problems from something bizarre like @@ -185,11 +195,11 @@ _pixman_format_from_masks (cairo_format_masks_t *masks, masks->green_mask != format_masks.green_mask || masks->blue_mask != format_masks.blue_mask) { - return CAIRO_INT_STATUS_UNSUPPORTED; + return FALSE; } *format_ret = format; - return CAIRO_STATUS_SUCCESS; + return TRUE; } /* A mask consisting of N bits set to 1. */ @@ -253,11 +263,9 @@ _cairo_image_surface_create_with_masks (unsigned char *data, int height, int stride) { - cairo_int_status_t status; pixman_format_code_t pixman_format; - status = _pixman_format_from_masks (masks, &pixman_format); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + if (! _pixman_format_from_masks (masks, &pixman_format)) { fprintf (stderr, "Error: Cairo %s does not yet support the requested image format:\n" "\tDepth: %d\n" @@ -265,8 +273,11 @@ _cairo_image_surface_create_with_masks (unsigned char *data, "\tRed mask: 0x%08lx\n" "\tGreen mask: 0x%08lx\n" "\tBlue mask: 0x%08lx\n" +#ifdef PACKAGE_BUGGREPORT "Please file an enhancement request (quoting the above) at:\n" - PACKAGE_BUGREPORT "\n", + PACKAGE_BUGREPORT"\n" +#endif + , cairo_version_string (), masks->bpp, masks->alpha_mask, masks->red_mask, masks->green_mask, masks->blue_mask); @@ -473,6 +484,7 @@ cairo_image_surface_create_for_data (unsigned char *data, int stride) { pixman_format_code_t pixman_format; + int minstride; if (! CAIRO_FORMAT_VALID (format)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); @@ -480,6 +492,17 @@ cairo_image_surface_create_for_data (unsigned char *data, if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); + minstride = cairo_format_stride_for_width (format, width); + if (stride < 0) { + if (stride > -minstride) { + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); + } + } else { + if (stride < minstride) { + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); + } + } + pixman_format = _cairo_format_to_pixman_format_code (format); return _cairo_image_surface_create_with_pixman_format (data, pixman_format, @@ -510,7 +533,8 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data, * inspection or modification. * * Return value: a pointer to the image data of this surface or %NULL - * if @surface is not an image surface. + * if @surface is not an image surface, or if cairo_surface_finish() + * has been called. * * Since: 1.2 **/ @@ -548,8 +572,6 @@ cairo_image_surface_get_format (cairo_surface_t *surface) return 0; } - assert (CAIRO_FORMAT_VALID (image_surface->format)); - return image_surface->format; } @@ -766,11 +788,14 @@ _cairo_image_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_image_surface_t *surface = abstract_surface; if (src->backend == surface->base.backend) { + *clone_offset_x = *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index 9277e7c1f279..ca1832306aa2 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -624,6 +624,35 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix, return FALSE; } +/* By pixel exact here, we mean a matrix that is composed only of + * 90 degree rotations, flips, and integer translations and produces a 1:1 + * mapping between source and destination pixels. If we transform an image + * with a pixel-exact matrix, filtering is not useful. + */ +cairo_private cairo_bool_t +_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix) +{ + cairo_fixed_t x0_fixed, y0_fixed; + + if (matrix->xy == 0.0 && matrix->yx == 0.0) { + if (! (matrix->xx == 1.0 || matrix->xx == -1.0)) + return FALSE; + if (! (matrix->yy == 1.0 || matrix->yy == -1.0)) + return FALSE; + } else if (matrix->xx == 0.0 && matrix->yy == 0.0) { + if (! (matrix->xy == 1.0 || matrix->xy == -1.0)) + return FALSE; + if (! (matrix->yx == 1.0 || matrix->yx == -1.0)) + return FALSE; + } else + return FALSE; + + x0_fixed = _cairo_fixed_from_double (matrix->x0); + y0_fixed = _cairo_fixed_from_double (matrix->y0); + + return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed); +} + /* A circle in user space is transformed into an ellipse in device space. diff --git a/gfx/cairo/cairo/src/cairo-meta-surface-private.h b/gfx/cairo/cairo/src/cairo-meta-surface-private.h index bd16a5be28ec..9a1b169cff19 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h @@ -114,7 +114,7 @@ typedef struct _cairo_command_show_text_glyphs { unsigned int num_glyphs; cairo_text_cluster_t *clusters; int num_clusters; - cairo_bool_t backward; + cairo_text_cluster_flags_t cluster_flags; cairo_scaled_font_t *scaled_font; } cairo_command_show_text_glyphs_t; diff --git a/gfx/cairo/cairo/src/cairo-meta-surface.c b/gfx/cairo/cairo/src/cairo-meta-surface.c index ee52b49190ad..b86cb5136d9c 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface.c +++ b/gfx/cairo/cairo/src/cairo-meta-surface.c @@ -216,32 +216,6 @@ _cairo_meta_surface_release_source_image (void *abstract_surface, cairo_surface_destroy (&image->base); } -static cairo_status_t -_init_pattern_with_snapshot (cairo_pattern_t *pattern, - const cairo_pattern_t *other) -{ - cairo_status_t status; - - status = _cairo_pattern_init_copy (pattern, other); - if (status) - return status; - - 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; - - surface_pattern->surface = _cairo_surface_snapshot (surface); - - cairo_surface_destroy (surface); - - if (surface_pattern->surface->status) - return surface_pattern->surface->status; - } - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _cairo_meta_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -259,7 +233,7 @@ _cairo_meta_surface_paint (void *abstract_surface, command->header.region = CAIRO_META_REGION_ALL; command->op = op; - status = _init_pattern_with_snapshot (&command->source.base, source); + status = _cairo_pattern_init_snapshot (&command->source.base, source); if (status) goto CLEANUP_COMMAND; @@ -300,11 +274,11 @@ _cairo_meta_surface_mask (void *abstract_surface, command->header.region = CAIRO_META_REGION_ALL; command->op = op; - status = _init_pattern_with_snapshot (&command->source.base, source); + status = _cairo_pattern_init_snapshot (&command->source.base, source); if (status) goto CLEANUP_COMMAND; - status = _init_pattern_with_snapshot (&command->mask.base, mask); + status = _cairo_pattern_init_snapshot (&command->mask.base, mask); if (status) goto CLEANUP_SOURCE; @@ -346,7 +320,7 @@ _cairo_meta_surface_stroke (void *abstract_surface, command->header.region = CAIRO_META_REGION_ALL; command->op = op; - status = _init_pattern_with_snapshot (&command->source.base, source); + status = _cairo_pattern_init_snapshot (&command->source.base, source); if (status) goto CLEANUP_COMMAND; @@ -401,7 +375,7 @@ _cairo_meta_surface_fill (void *abstract_surface, command->header.region = CAIRO_META_REGION_ALL; command->op = op; - status = _init_pattern_with_snapshot (&command->source.base, source); + status = _cairo_pattern_init_snapshot (&command->source.base, source); if (status) goto CLEANUP_COMMAND; @@ -444,7 +418,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_status_t status; @@ -459,7 +433,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface, command->header.region = CAIRO_META_REGION_ALL; command->op = op; - status = _init_pattern_with_snapshot (&command->source.base, source); + status = _cairo_pattern_init_snapshot (&command->source.base, source); if (status) goto CLEANUP_COMMAND; @@ -495,7 +469,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface, memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters); } - command->backward = backward; + command->cluster_flags = cluster_flags; command->scaled_font = cairo_scaled_font_reference (scaled_font); @@ -848,7 +822,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface, if (has_device_transform) { cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); cairo_matrix_multiply (&dev_ctm_inverse, - &surface->device_transform_inverse, + &target->device_transform_inverse, &dev_ctm_inverse); } @@ -952,7 +926,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface, command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, dev_glyphs, num_glyphs, command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, - command->show_text_glyphs.backward, + command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font); free (dev_glyphs); diff --git a/gfx/cairo/cairo/src/cairo-misc.c b/gfx/cairo/cairo/src/cairo-misc.c index 5a222b645b00..73126e4c875a 100644 --- a/gfx/cairo/cairo/src/cairo-misc.c +++ b/gfx/cairo/cairo/src/cairo-misc.c @@ -240,7 +240,7 @@ slim_hidden_def (cairo_text_cluster_free); * @num_glyphs: number of glyphs * @clusters: array of cluster mapping information * @num_clusters: number of clusters in the mapping - * @backward: whether the text to glyphs mapping goes backward + * @cluster_flags: cluster flags * * Check that clusters cover the entire glyphs and utf8 arrays, * and that cluster boundaries are UTF-8 boundaries. @@ -257,7 +257,7 @@ _cairo_validate_text_clusters (const char *utf8, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward) + cairo_text_cluster_flags_t cluster_flags) { cairo_status_t status; unsigned int n_bytes = 0; diff --git a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h index db65bd188dc2..239dbbb09cf8 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h @@ -41,10 +41,15 @@ #ifndef CAIRO_MUTEX_IMPL_PRIVATE_H #define CAIRO_MUTEX_IMPL_PRIVATE_H +#include "cairo.h" + #if HAVE_CONFIG_H #include "config.h" #endif +#if HAVE_LOCKDEP +#include +#endif /* A fully qualified no-operation statement */ #define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0) @@ -72,6 +77,9 @@ * cairo_mutex_impl_t _cairo_some_mutex; * * + * - #define %CAIRO_MUTEX_IMPL_ 1 with suitable name for your platform. You + * can later use this symbol in cairo-system.c. + * * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to * proper statement to lock/unlock the mutex object passed in. * You can (and should) assume that the mutex is already @@ -147,16 +155,13 @@ * poke around cairo-mutex-private.h for possible solutions. */ -#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H -#error "Do not include cairo-mutex-impl-private.h directly. Include cairo-mutex-type-private.h instead." -#endif - #if CAIRO_NO_MUTEX /* No mutexes */ typedef int cairo_mutex_impl_t; +# define CAIRO_MUTEX_IMPL_NO 1 # define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP # define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) @@ -168,18 +173,30 @@ typedef pthread_mutex_t cairo_mutex_impl_t; +# define CAIRO_MUTEX_IMPL_PTHREAD 1 +#if HAVE_LOCKDEP +/* expose all mutexes to the validator */ +# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL) +#endif # define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex)) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) +#if HAVE_LOCKDEP +# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex)) +# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex)) +#endif # define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex)) +#if ! HAVE_LOCKDEP # define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP +#endif # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#elif HAVE_WINDOWS_H /*******************************************************/ +#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/ # include typedef CRITICAL_SECTION cairo_mutex_impl_t; +# define CAIRO_MUTEX_IMPL_WIN32 1 # define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex)) @@ -194,6 +211,7 @@ typedef HMTX cairo_mutex_impl_t; +# define CAIRO_MUTEX_IMPL_OS2 1 # define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex) # define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE) @@ -204,6 +222,7 @@ typedef BLocker* cairo_mutex_impl_t; +# define CAIRO_MUTEX_IMPL_BEOS 1 # define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock() # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock() # define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker() diff --git a/gfx/cairo/cairo/src/cairo-mutex-list-private.h b/gfx/cairo/cairo/src/cairo-mutex-list-private.h index 1fe5bd5ae003..6fdb389a27df 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h @@ -31,24 +31,28 @@ * Mathias Hasselmann */ +#ifndef CAIRO_FEATURES_H +/* This block is to just make this header file standalone */ +#define CAIRO_MUTEX_DECLARE(mutex) +#endif -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock); -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock); +CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock) +CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock) -CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex); -CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex); -CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex); +CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex) +CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex) +CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex) #if CAIRO_HAS_FT_FONT -CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex); +CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex) #endif #if CAIRO_HAS_XLIB_SURFACE -CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex); +CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex) #endif -#if !defined (CAIRO_HAS_ATOMIC_OPS) || defined (CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER) -CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex); +#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER) +CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex) #endif /* Undefine, to err on unintended inclusion */ diff --git a/gfx/cairo/cairo/src/cairo-mutex-private.h b/gfx/cairo/cairo/src/cairo-mutex-private.h index d4bf68b139c9..a3a7271f2dfb 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-private.h @@ -41,10 +41,6 @@ #ifndef CAIRO_MUTEX_PRIVATE_H #define CAIRO_MUTEX_PRIVATE_H -#if HAVE_CONFIG_H -#include "config.h" -#endif - #include "cairo-mutex-type-private.h" CAIRO_BEGIN_DECLS @@ -62,7 +58,7 @@ cairo_private void _cairo_mutex_finalize (void); /* Finally, extern the static mutexes and undef */ -#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex +#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex; #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE diff --git a/gfx/cairo/cairo/src/cairo-mutex-type-private.h b/gfx/cairo/cairo/src/cairo-mutex-type-private.h index 2314be1d003a..adf17bbedc5d 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h @@ -90,7 +90,6 @@ #endif /* CAIRO_MUTEX_IMPL_INIT */ - #ifdef CAIRO_MUTEX_IMPL_FINI /* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all @@ -169,6 +168,12 @@ typedef cairo_mutex_impl_t cairo_mutex_t; #define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI #define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER +#ifndef CAIRO_MUTEX_IS_LOCKED +# define CAIRO_MUTEX_IS_LOCKED(name) 1 +#endif +#ifndef CAIRO_MUTEX_IS_UNLOCKED +# define CAIRO_MUTEX_IS_UNLOCKED(name) 1 +#endif /* Debugging support */ diff --git a/gfx/cairo/cairo/src/cairo-mutex.c b/gfx/cairo/cairo/src/cairo-mutex.c index 5149ee83141a..5b6a6e150281 100644 --- a/gfx/cairo/cairo/src/cairo-mutex.c +++ b/gfx/cairo/cairo/src/cairo-mutex.c @@ -35,7 +35,7 @@ #include "cairo-mutex-private.h" -#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER +#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER; #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE @@ -61,7 +61,7 @@ void _cairo_mutex_initialize (void) _cairo_mutex_initialized = TRUE; -#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex) +#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex); #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE } @@ -75,7 +75,7 @@ void _cairo_mutex_finalize (void) _cairo_mutex_initialized = FALSE; -#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex) +#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex); #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE } diff --git a/gfx/cairo/cairo/src/cairo-no-features.h b/gfx/cairo/cairo/src/cairo-no-features.h deleted file mode 100644 index 9b3d86be2637..000000000000 --- a/gfx/cairo/cairo/src/cairo-no-features.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Generated by configure. Do not edit */ -#ifndef CAIRO_NO_FEATURES_H -#define CAIRO_NO_FEATURES_H - -#include - -/* This is a dummy header, to trick gtk-doc only */ - -#define CAIRO_HAS_WIN32_FONT 1 -#define CAIRO_HAS_WIN32_SURFACE 1 - -#endif diff --git a/gfx/cairo/cairo/src/cairo-os2-private.h b/gfx/cairo/cairo/src/cairo-os2-private.h index 6e8eb7bf3b19..5fa282951e9c 100644 --- a/gfx/cairo/cairo/src/cairo-os2-private.h +++ b/gfx/cairo/cairo/src/cairo-os2-private.h @@ -38,6 +38,9 @@ #ifndef CAIRO_OS2_PRIVATE_H #define CAIRO_OS2_PRIVATE_H +#include "cairo-os2.h" +#include "cairoint.h" + #define INCL_DOS #define INCL_DOSSEMAPHORES #define INCL_DOSERRORS @@ -49,9 +52,6 @@ # include #endif -#include "cairo-os2.h" -#include "cairoint.h" - typedef struct _cairo_os2_surface { cairo_surface_t base; diff --git a/gfx/cairo/cairo/src/cairo-os2-surface.c b/gfx/cairo/cairo/src/cairo-os2-surface.c index 80a1cd97bf63..bff649ae812d 100644 --- a/gfx/cairo/cairo/src/cairo-os2-surface.c +++ b/gfx/cairo/cairo/src/cairo-os2-surface.c @@ -232,6 +232,12 @@ void _buffer_free (void *buffer) #endif } +/* XXX + * The cairo_os2_ini() and cairo_os2_fini() functions should be removed and + * the LibMain code moved to cairo-system.c. It should also call + * cairo_debug_reset_static_data() instead of duplicating its logic... + */ + #ifdef BUILD_CAIRO_DLL /* The main DLL entry for DLL initialization and uninitialization */ /* Only include this code if we're about to build a DLL. */ @@ -1202,6 +1208,8 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, * cairo_os2_surface_get_manual_window_refresh: * @surface: the cairo surface to query the refresh mode from * + * This space left intentionally blank. + * * Return value: current refresh mode of the surface (true by default) * * Since: 1.4 diff --git a/gfx/cairo/cairo/src/cairo-output-stream-private.h b/gfx/cairo/cairo/src/cairo-output-stream-private.h index 37239f264443..787d061610da 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream-private.h +++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h @@ -161,6 +161,9 @@ _cairo_memory_stream_copy (cairo_output_stream_t *base, cairo_private int _cairo_memory_stream_length (cairo_output_stream_t *stream); +cairo_private cairo_output_stream_t * +_cairo_null_stream_create (void); + /* cairo-base85-stream.c */ cairo_private cairo_output_stream_t * _cairo_base85_stream_create (cairo_output_stream_t *output); @@ -169,4 +172,5 @@ _cairo_base85_stream_create (cairo_output_stream_t *output); cairo_private cairo_output_stream_t * _cairo_deflate_stream_create (cairo_output_stream_t *output); + #endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-output-stream.c b/gfx/cairo/cairo/src/cairo-output-stream.c index 206ed30bcbd2..bae6ac4fe83b 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -116,6 +116,9 @@ closure_write (cairo_output_stream_t *stream, cairo_output_stream_with_closure_t *stream_with_closure = (cairo_output_stream_with_closure_t *) stream; + if (stream_with_closure->write_func == NULL) + return CAIRO_STATUS_SUCCESS; + return stream_with_closure->write_func (stream_with_closure->closure, data, length); } @@ -583,6 +586,9 @@ _cairo_output_stream_create_for_filename (const char *filename) stdio_stream_t *stream; FILE *file; + if (filename == NULL) + return _cairo_null_stream_create (); + file = fopen (filename, "wb"); if (file == NULL) { switch (errno) { @@ -676,3 +682,26 @@ _cairo_memory_stream_length (cairo_output_stream_t *base) return _cairo_array_num_elements (&stream->array); } + +static cairo_status_t +null_write (cairo_output_stream_t *base, + const unsigned char *data, unsigned int length) +{ + return CAIRO_STATUS_SUCCESS; +} + +cairo_output_stream_t * +_cairo_null_stream_create (void) +{ + cairo_output_stream_t *stream; + + stream = malloc (sizeof *stream); + if (stream == NULL) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_output_stream_t *) &_cairo_output_stream_nil; + } + + _cairo_output_stream_init (stream, null_write, NULL); + + return stream; +} diff --git a/gfx/cairo/cairo/src/cairo-paginated-private.h b/gfx/cairo/cairo/src/cairo-paginated-private.h index 0c042746d4e3..5cb2e48b6c41 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-private.h +++ b/gfx/cairo/cairo/src/cairo-paginated-private.h @@ -65,7 +65,7 @@ struct _cairo_paginated_surface_backend { * before the mode is changed to RENDER. */ cairo_warn cairo_int_status_t - (*set_bounding_box) (void *surface, + (*set_bounding_box) (void *surface, cairo_box_t *bbox); /* Optional. Indicates whether the page requires fallback images. @@ -73,8 +73,11 @@ struct _cairo_paginated_surface_backend { * mode is changed to RENDER. */ cairo_warn cairo_int_status_t - (*set_fallback_images_required)(void *surface, - cairo_bool_t fallbacks_required); + (*set_fallback_images_required) (void *surface, + cairo_bool_t fallbacks_required); + + cairo_bool_t + (*supports_fine_grained_fallbacks) (void *surface); }; /* A #cairo_paginated_surface_t provides a very convenient wrapper that diff --git a/gfx/cairo/cairo/src/cairo-paginated-surface.c b/gfx/cairo/cairo/src/cairo-paginated-surface.c index 2640a8bfcb44..a94ca80a000d 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -108,6 +108,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, return &surface->base; FAIL_CLEANUP_SURFACE: + cairo_surface_destroy (target); free (surface); FAIL: return _cairo_surface_create_in_error (status); @@ -299,8 +300,10 @@ _paint_page (cairo_paginated_surface_t *surface) if (analysis->status) return _cairo_surface_set_error (surface->target, analysis->status); - surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); - status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis); + surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_ANALYZE); + status = _cairo_meta_surface_replay_and_create_regions (surface->meta, + analysis); if (status || analysis->status) { if (status == CAIRO_STATUS_SUCCESS) status = analysis->status; @@ -325,43 +328,31 @@ _paint_page (cairo_paginated_surface_t *surface) goto FAIL; } - surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); - /* Finer grained fallbacks are currently only supported for some * surface types */ - switch (surface->target->type) { - case CAIRO_SURFACE_TYPE_PDF: - case CAIRO_SURFACE_TYPE_PS: - case CAIRO_SURFACE_TYPE_WIN32_PRINTING: - has_supported = _cairo_analysis_surface_has_supported (analysis); - has_page_fallback = FALSE; - has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis); - break; - - case CAIRO_SURFACE_TYPE_IMAGE: - case CAIRO_SURFACE_TYPE_XLIB: - case CAIRO_SURFACE_TYPE_XCB: - case CAIRO_SURFACE_TYPE_GLITZ: - case CAIRO_SURFACE_TYPE_QUARTZ: - case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: - case CAIRO_SURFACE_TYPE_WIN32: - case CAIRO_SURFACE_TYPE_BEOS: - case CAIRO_SURFACE_TYPE_DIRECTFB: - case CAIRO_SURFACE_TYPE_SVG: - case CAIRO_SURFACE_TYPE_OS2: - default: - if (_cairo_analysis_surface_has_unsupported (analysis)) { - has_supported = FALSE; - has_page_fallback = TRUE; - } else { - has_supported = TRUE; - has_page_fallback = FALSE; - } - has_finegrained_fallback = FALSE; - break; + if (surface->backend->supports_fine_grained_fallbacks != NULL && + surface->backend->supports_fine_grained_fallbacks (surface->target)) + { + has_supported = _cairo_analysis_surface_has_supported (analysis); + has_page_fallback = FALSE; + has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis); + } + else + { + if (_cairo_analysis_surface_has_unsupported (analysis)) { + has_supported = FALSE; + has_page_fallback = TRUE; + } else { + has_supported = TRUE; + has_page_fallback = FALSE; + } + has_finegrained_fallback = FALSE; } if (has_supported) { + surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_RENDER); + status = _cairo_meta_surface_replay_region (surface->meta, surface->target, CAIRO_META_REGION_NATIVE); @@ -370,10 +361,12 @@ _paint_page (cairo_paginated_surface_t *surface) goto FAIL; } - if (has_page_fallback) - { + if (has_page_fallback) { cairo_box_int_t box; + surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_FALLBACK); + box.p1.x = 0; box.p1.y = 0; box.p2.x = surface->width; @@ -383,13 +376,13 @@ _paint_page (cairo_paginated_surface_t *surface) goto FAIL; } - if (has_finegrained_fallback) - { + if (has_finegrained_fallback) { cairo_region_t *region; cairo_box_int_t *boxes; int num_boxes, i; - surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK); + surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_FALLBACK); /* Reset clip region before drawing the fall back images */ status = _cairo_surface_intersect_clip_path (surface->target, @@ -622,7 +615,7 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_paginated_surface_t *surface = abstract_surface; @@ -644,14 +637,12 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface, * show_glyphs functions, (which would get less testing and likely * lead to bugs). */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); status = _cairo_surface_show_text_glyphs (surface->meta, op, source, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward, + cluster_flags, scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); return status; } diff --git a/gfx/cairo/cairo/src/cairo-path-fill.c b/gfx/cairo/cairo/src/cairo-path-fill.c index ba33114894ee..1cef20e4aaa6 100644 --- a/gfx/cairo/cairo/src/cairo-path-fill.c +++ b/gfx/cairo/cairo/src/cairo-path-fill.c @@ -215,8 +215,24 @@ _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, cairo_traps_t *traps) { if (_cairo_path_fixed_is_box (path, NULL)) { - return _cairo_traps_tessellate_convex_quad (traps, - path->buf_head.base.points); + cairo_point_t *p = path->buf_head.base.points; + cairo_point_t *top_left, *bot_right; + + top_left = &p[0]; + bot_right = &p[2]; + if (top_left->x > bot_right->x || top_left->y > bot_right->y) { + int n; + + /* not a simple cairo_rectangle() */ + for (n = 0; n < 4; n++) { + if (p[n].x <= top_left->x && p[n].y <= top_left->y) + top_left = &p[n]; + if (p[n].x >= bot_right->x && p[n].y >= bot_right->y) + bot_right = &p[n]; + } + } + + return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right); } return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index 3663ba7aa10d..efccbcfea9c3 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -829,7 +829,6 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point) static cairo_status_t _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) { - cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_stroker_t *stroker = closure; double mag, remain, step_length = 0; double slope_dx, slope_dy; @@ -838,17 +837,19 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) cairo_point_t *p1 = &stroker->current_point; cairo_point_t *p2 = point; cairo_slope_t dev_slope; - cairo_bool_t fully_in_bounds = TRUE; cairo_line_t segment; + cairo_bool_t fully_in_bounds; + cairo_status_t status; stroker->has_initial_sub_path = stroker->dash_starts_on; if (p1->x == p2->x && p1->y == p2->y) return CAIRO_STATUS_SUCCESS; + fully_in_bounds = TRUE; if (stroker->has_bounds && - (!_cairo_box_contains_point (&stroker->bounds, p1) || - !_cairo_box_contains_point (&stroker->bounds, p2))) + (! _cairo_box_contains_point (&stroker->bounds, p1) || + ! _cairo_box_contains_point (&stroker->bounds, p2))) { fully_in_bounds = FALSE; } @@ -858,8 +859,11 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) slope_dx = _cairo_fixed_to_double (p2->x - p1->x); slope_dy = _cairo_fixed_to_double (p2->y - p1->y); - if (!_compute_normalized_device_slope (&slope_dx, &slope_dy, stroker->ctm_inverse, &mag)) + if (! _compute_normalized_device_slope (&slope_dx, &slope_dy, + stroker->ctm_inverse, &mag)) + { return CAIRO_STATUS_SUCCESS; + } remain = mag; segment.p1 = *p1; @@ -872,48 +876,57 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x; segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y; - if (fully_in_bounds || - _cairo_box_intersects_line_segment (&stroker->bounds, &segment)) + if (stroker->dash_on && + (fully_in_bounds || + (! stroker->has_first_face && stroker->dash_starts_on) || + _cairo_box_intersects_line_segment (&stroker->bounds, &segment))) { - if (stroker->dash_on) { - status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, &dev_slope, slope_dx, slope_dy, &sub_start, &sub_end); + status = _cairo_stroker_add_sub_edge (stroker, + &segment.p1, &segment.p2, + &dev_slope, + slope_dx, slope_dy, + &sub_start, &sub_end); + if (status) + return status; + + if (stroker->has_current_face) { + /* Join with final face from previous segment */ + status = _cairo_stroker_join (stroker, + &stroker->current_face, + &sub_start); if (status) return status; - if (stroker->has_current_face) { - /* Join with final face from previous segment */ - status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start); - stroker->has_current_face = FALSE; - if (status) - return status; - } else if (!stroker->has_first_face && stroker->dash_starts_on) { - /* Save sub path's first face in case needed for closing join */ - stroker->first_face = sub_start; - stroker->has_first_face = TRUE; - } else { - /* Cap dash start if not connecting to a previous segment */ - status = _cairo_stroker_add_leading_cap (stroker, &sub_start); - if (status) - return status; - } - - if (remain) { - /* Cap dash end if not at end of segment */ - status = _cairo_stroker_add_trailing_cap (stroker, &sub_end); - if (status) - return status; - } else { - stroker->current_face = sub_end; - stroker->has_current_face = TRUE; - } + stroker->has_current_face = FALSE; + } else if (! stroker->has_first_face && stroker->dash_starts_on) { + /* Save sub path's first face in case needed for closing join */ + stroker->first_face = sub_start; + stroker->has_first_face = TRUE; } else { - if (stroker->has_current_face) { - /* Cap final face from previous segment */ - status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); - if (status) - return status; - stroker->has_current_face = FALSE; - } + /* Cap dash start if not connecting to a previous segment */ + status = _cairo_stroker_add_leading_cap (stroker, &sub_start); + if (status) + return status; + } + + if (remain) { + /* Cap dash end if not at end of segment */ + status = _cairo_stroker_add_trailing_cap (stroker, &sub_end); + if (status) + return status; + } else { + stroker->current_face = sub_end; + stroker->has_current_face = TRUE; + } + } else { + if (stroker->has_current_face) { + /* Cap final face from previous segment */ + status = _cairo_stroker_add_trailing_cap (stroker, + &stroker->current_face); + if (status) + return status; + + stroker->has_current_face = FALSE; } } @@ -921,24 +934,32 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) segment.p1 = segment.p2; } - if (stroker->dash_on && !stroker->has_current_face) { + if (stroker->dash_on && ! stroker->has_current_face) { /* This segment ends on a transition to dash_on, compute a new face - * and add cap for the begining of the next dash_on step. + * and add cap for the beginning of the next dash_on step. * * Note: this will create a degenerate cap if this is not the last line * in the path. Whether this behaviour is desirable or not is debatable. - * On one side these degnerate caps can not be reproduced with regular path stroking. - * On the other side Acroread 7 also produces the degenerate caps. */ - _compute_face (point, &dev_slope, slope_dx, slope_dy, stroker, &stroker->current_face); - stroker->has_current_face = TRUE; - status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face); + * On one side these degenerate caps can not be reproduced with regular + * path stroking. + * On the other hand, Acroread 7 also produces the degenerate caps. + */ + _compute_face (point, &dev_slope, + slope_dx, slope_dy, + stroker, + &stroker->current_face); + + status = _cairo_stroker_add_leading_cap (stroker, + &stroker->current_face); if (status) return status; + + stroker->has_current_face = TRUE; } stroker->current_point = *point; - return status; + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -1257,12 +1278,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker) cairo_status_t status; cairo_line_cap_t line_cap = stroker->stroke_style->line_cap; cairo_fixed_t half_line_width = stroker->half_line_width; - cairo_bool_t lengthen_initial, shorten_final, lengthen_final; - cairo_point_t *a, *b; - cairo_point_t r[4]; int i; for (i = 0; i < stroker->num_segments; i++) { + cairo_point_t *a, *b; + cairo_bool_t lengthen_initial, shorten_final, lengthen_final; + a = &stroker->segments[i].p1; b = &stroker->segments[i].p2; @@ -1315,6 +1336,14 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker) else if (lengthen_final) b->x -= half_line_width; } + + if (a->x > b->x) { + cairo_point_t *t; + + t = a; + a = b; + b = t; + } } else { if (a->y < b->y) { if (lengthen_initial) @@ -1331,27 +1360,27 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker) else if (lengthen_final) b->y -= half_line_width; } + + if (a->y > b->y) { + cairo_point_t *t; + + t = a; + a = b; + b = t; + } } /* Form the rectangle by expanding by half the line width in - * either perdendicular direction. */ - r[0] = *a; - r[1] = *b; - r[2] = *b; - r[3] = *a; + * either perpendicular direction. */ if (a->y == b->y) { - r[0].y -= half_line_width; - r[1].y -= half_line_width; - r[2].y += half_line_width; - r[3].y += half_line_width; + a->y -= half_line_width; + b->y += half_line_width; } else { - r[0].x -= half_line_width; - r[1].x -= half_line_width; - r[2].x += half_line_width; - r[3].x += half_line_width; + a->x -= half_line_width; + b->x += half_line_width; } - status = _cairo_traps_tessellate_convex_quad (stroker->traps, r); + status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b); if (status) return status; } @@ -1439,7 +1468,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, /* This special-case rectilinear stroker only supports * miter-joined lines (not curves) and no dashing and a * translation-only matrix (though it could probably be extended - * to support a matrix with uniform, integer sacling). + * to support a matrix with uniform, integer scaling). * * It also only supports horizontal and vertical line_to * elements. But we don't catch that here, but instead return @@ -1484,11 +1513,10 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker); BAIL: - _cairo_rectilinear_stroker_fini (&rectilinear_stroker); if (status) - _cairo_traps_fini (traps); + _cairo_traps_clear (traps); return status; } diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index 3dfd7c80308d..d83142a95644 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -192,6 +192,36 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } +cairo_status_t +_cairo_pattern_init_snapshot (cairo_pattern_t *pattern, + const cairo_pattern_t *other) +{ + cairo_status_t status; + + /* We don't bother doing any fancy copy-on-write implementation + * for the pattern's data. It's generally quite tiny. */ + status = _cairo_pattern_init_copy (pattern, other); + if (status) + return status; + + /* But we do let the surface snapshot stuff be as fancy as it + * would like to be. */ + 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; + + surface_pattern->surface = _cairo_surface_snapshot (surface); + + cairo_surface_destroy (surface); + + if (surface_pattern->surface->status) + return surface_pattern->surface->status; + } + + return CAIRO_STATUS_SUCCESS; +} + void _cairo_pattern_fini (cairo_pattern_t *pattern) { @@ -784,7 +814,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern, cairo_destroy_func_t destroy) { if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return pattern->status; return _cairo_user_data_array_set_data (&pattern->user_data, key, user_data, destroy); @@ -1217,6 +1247,8 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, pixman_gradient_stop_t pixman_stops_static[2]; pixman_gradient_stop_t *pixman_stops = pixman_stops_static; unsigned int i; + int clone_offset_x, clone_offset_y; + cairo_matrix_t matrix = pattern->base.matrix; if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) { pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t)); @@ -1236,11 +1268,46 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, { cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; pixman_point_fixed_t p1, p2; + cairo_fixed_t xdim, ydim; - p1.x = _cairo_fixed_to_16_16 (linear->p1.x); - p1.y = _cairo_fixed_to_16_16 (linear->p1.y); - p2.x = _cairo_fixed_to_16_16 (linear->p2.x); - p2.y = _cairo_fixed_to_16_16 (linear->p2.y); + xdim = linear->p2.x - linear->p1.x; + ydim = linear->p2.y - linear->p1.y; + + /* + * Transform the matrix to avoid overflow when converting between + * cairo_fixed_t and pixman_fixed_t (without incurring performance + * loss when the transformation is unnecessary). + * + * XXX: Consider converting out-of-range co-ordinates and transforms. + * Having a function to compute the required transformation to + * "normalize" a given bounding box would be generally useful - + * cf linear patterns, gradient patterns, surface patterns... + */ +#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ + if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT || + _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT) + { + double sf; + + if (xdim > ydim) + sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim); + else + sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim); + + p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf); + p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf); + p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf); + p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf); + + cairo_matrix_scale (&matrix, sf, sf); + } + else + { + p1.x = _cairo_fixed_to_16_16 (linear->p1.x); + p1.y = _cairo_fixed_to_16_16 (linear->p1.y); + p2.x = _cairo_fixed_to_16_16 (linear->p2.x); + p2.y = _cairo_fixed_to_16_16 (linear->p2.y); + } pixman_image = pixman_image_create_linear_gradient (&p1, &p2, pixman_stops, @@ -1284,7 +1351,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, } attr->x_offset = attr->y_offset = 0; - attr->matrix = pattern->base.matrix; + attr->matrix = matrix; attr->extend = pattern->base.extend; attr->filter = CAIRO_FILTER_NEAREST; attr->acquired = FALSE; @@ -1332,7 +1399,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, return image->base.status; } - _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform); + _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform); if (!pixman_image_set_transform (pixman_image, &pixman_transform)) { cairo_surface_destroy (&image->base); pixman_image_unref (pixman_image); @@ -1366,7 +1433,10 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, pixman_image_unref (pixman_image); status = _cairo_surface_clone_similar (dst, &image->base, - 0, 0, width, height, out); + 0, 0, width, height, + &clone_offset_x, + &clone_offset_y, + out); cairo_surface_destroy (&image->base); @@ -1628,6 +1698,71 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern) return FALSE; } +/** + * _cairo_pattern_analyze_filter: + * @pattern: surface pattern + * @pad_out: location to store necessary padding in the source image, or %NULL + * Returns: the optimized #cairo_filter_t to use with @pattern. + * + * Analyze the filter to determine how much extra needs to be sampled + * from the source image to account for the filter radius and whether + * we can optimize the filter to a simpler value. + * + * XXX: We don't actually have any way of querying the backend for + * the filter radius, so we just guess base on what we know that + * backends do currently (see bug #10508) + */ +static cairo_filter_t +_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern, + double *pad_out) +{ + double pad; + cairo_filter_t optimized_filter; + + switch (pattern->base.filter) { + case CAIRO_FILTER_GOOD: + case CAIRO_FILTER_BEST: + case CAIRO_FILTER_BILINEAR: + /* If source pixels map 1:1 onto destination pixels, we do + * not need to filter (and do not want to filter, since it + * will cause blurriness) + */ + if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) { + pad = 0.; + optimized_filter = CAIRO_FILTER_NEAREST; + } else { + /* 0.5 is enough for a bilinear filter. It's possible we + * should defensively use more for CAIRO_FILTER_BEST, but + * without a single example, it's hard to know how much + * more would be defensive... + */ + pad = 0.5; + optimized_filter = pattern->base.filter; + } + break; + + case CAIRO_FILTER_FAST: + case CAIRO_FILTER_NEAREST: + case CAIRO_FILTER_GAUSSIAN: + default: + pad = 0.; + optimized_filter = pattern->base.filter; + break; + } + + if (pad_out) + *pad_out = pad; + + return optimized_filter; +} + + +static double +_pixman_nearest_sample (double d) +{ + return ceil (d - .5); +} + static cairo_int_status_t _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, cairo_surface_t *dst, @@ -1640,18 +1775,44 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, { cairo_int_status_t status; int tx, ty; + double pad; attr->acquired = FALSE; attr->extend = pattern->base.extend; - attr->filter = pattern->base.filter; + attr->filter = _cairo_pattern_analyze_filter (pattern, &pad); + if (_cairo_matrix_is_integer_translation (&pattern->base.matrix, &tx, &ty)) { cairo_matrix_init_identity (&attr->matrix); attr->x_offset = tx; attr->y_offset = ty; - attr->filter = CAIRO_FILTER_NEAREST; + } + else if (attr->filter == CAIRO_FILTER_NEAREST) + { + /* + * For NEAREST, we can remove the fractional translation component + * from the transformation - this ensures that the pattern will always + * hit fast-paths in the backends for simple transformations that + * become (almost) identity, without loss of quality. + */ + attr->matrix = pattern->base.matrix; + attr->matrix.x0 = 0; + attr->matrix.y0 = 0; + if (_cairo_matrix_is_pixel_exact (&attr->matrix)) { + /* The rounding here is rather peculiar as it needs to match the + * rounding performed on the sample coordinate used by pixman. + */ + attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0); + attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0); + } else { + attr->matrix.x0 = pattern->base.matrix.x0; + attr->matrix.y0 = pattern->base.matrix.y0; + } + + attr->x_offset = attr->y_offset = 0; + tx = ty = 0; } else { @@ -1734,8 +1895,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, return status; } - if (_cairo_surface_is_image (dst)) - { + if (_cairo_surface_is_image (dst)) { cairo_image_surface_t *image; status = _cairo_surface_acquire_source_image (pattern->surface, @@ -1746,60 +1906,73 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, *out = &image->base; attr->acquired = TRUE; - } - else - { + } else { cairo_rectangle_int_t extents; + status = _cairo_surface_get_extents (pattern->surface, &extents); if (status) return status; - /* If we're repeating, we just play it safe and clone the entire surface. */ - /* If requested width and height are -1, clone the entire surface. - * This is relied on in the svg backend. */ - if (attr->extend == CAIRO_EXTEND_REPEAT || - (width == (unsigned int) -1 && height == (unsigned int) -1)) { - x = extents.x; - y = extents.y; - width = extents.width; - height = extents.height; - } else { + /* If we're repeating, we just play it safe and clone the + * entire surface - i.e. we use the existing extents. + */ + if (attr->extend != CAIRO_EXTEND_REPEAT) { + cairo_rectangle_int_t sampled_area; + /* Otherwise, we first transform the rectangle to the * coordinate space of the source surface so that we can * clone only that portion of the surface that will be - * read. */ - if (! _cairo_matrix_is_identity (&attr->matrix)) { + * read. + */ + if (_cairo_matrix_is_identity (&attr->matrix)) { + sampled_area.x = x; + sampled_area.y = y; + sampled_area.width = width; + sampled_area.height = height; + } else { double x1 = x; double y1 = y; double x2 = x + width; double y2 = y + height; - cairo_bool_t is_tight; _cairo_matrix_transform_bounding_box (&attr->matrix, &x1, &y1, &x2, &y2, - &is_tight); + NULL); + + sampled_area.x = floor (x1 - pad); + sampled_area.y = floor (y1 - pad); + sampled_area.width = ceil (x2 + pad) - sampled_area.x; + sampled_area.height = ceil (y2 + pad) - sampled_area.y; - /* The transform_bounding_box call may have resulted - * in a region larger than the surface, but we never - * want to clone more than the surface itself, (we - * know we're not repeating at this point due to the - * above. - * - * XXX: The one padding here is to account for filter - * radius. It's a workaround right now, until we get a - * proper fix. (see bug #10508) - */ - x = MAX (0, floor (x1) - 1); - y = MAX (0, floor (y1) - 1); - width = MIN (extents.width, ceil (x2) + 1) - x; - height = MIN (extents.height, ceil (y2) + 1) - y; } - x += tx; - y += ty; + + sampled_area.x += tx; + sampled_area.y += ty; + + /* Never acquire a larger area than the source itself */ + _cairo_rectangle_intersect (&extents, &sampled_area); } status = _cairo_surface_clone_similar (dst, pattern->surface, - x, y, width, height, out); + extents.x, extents.y, + extents.width, extents.height, + &x, &y, out); + if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) { + if (_cairo_matrix_is_identity (&attr->matrix)) { + attr->x_offset -= x; + attr->y_offset -= y; + } else { + cairo_matrix_t m; + + x -= attr->x_offset; + y -= attr->y_offset; + attr->x_offset = 0; + attr->y_offset = 0; + + cairo_matrix_init_translate (&m, -x, -y); + cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m); + } + } } return status; @@ -1820,6 +1993,9 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, * A convenience function to obtain a surface to use as the source for * drawing on @dst. * + * Note that this function is only suitable for use when the destination + * surface is pixel based and 1 device unit maps to one pixel. + * * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out. **/ cairo_int_status_t @@ -2049,15 +2225,20 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern, cairo_surface_t *surface = surface_pattern->surface; cairo_matrix_t imatrix; double x1, y1, x2, y2; + double pad; status = _cairo_surface_get_extents (surface, &surface_extents); if (status) return status; - x1 = surface_extents.x; - y1 = surface_extents.y; - x2 = x1 + surface_extents.width; - y2 = y1 + surface_extents.height; + /* The filter can effectively enlarge the extents of the + * pattern, so extend as necessary. + */ + _cairo_pattern_analyze_filter (surface_pattern, &pad); + x1 = surface_extents.x - pad; + y1 = surface_extents.y - pad; + x2 = surface_extents.x + surface_extents.width + pad; + y2 = surface_extents.y + surface_extents.height + pad; imatrix = pattern->matrix; status = cairo_matrix_invert (&imatrix); diff --git a/gfx/cairo/cairo/src/cairo-pdf-operators-private.h b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h index a85839bb1a36..7ff843b1ef1d 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-operators-private.h +++ b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h @@ -159,7 +159,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font); #endif /* CAIRO_PDF_OPERATORS_H */ diff --git a/gfx/cairo/cairo/src/cairo-pdf-operators.c b/gfx/cairo/cairo/src/cairo-pdf-operators.c index 435503cab481..819318a19b6c 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-operators.c +++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c @@ -571,6 +571,16 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators, for (i = 0; i < num_dashes; i += 2) { if (dash[i] == 0.0) { + /* Do not modify the dashes in-place, as we may need to also + * replay this stroke to an image fallback. + */ + if (dash == style->dash) { + dash = _cairo_malloc_ab (num_dashes, sizeof (double)); + if (dash == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + memcpy (dash, style->dash, num_dashes * sizeof (double)); + } + /* If we're at the front of the list, we first rotate * two elements from the end of the list to the front * of the list before folding away the 0.0. Or, if @@ -581,10 +591,10 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators, double last_two[2]; if (num_dashes == 2) { - if (dash != style->dash) - free (dash); + free (dash); return CAIRO_INT_STATUS_NOTHING_TO_DO; } + /* The cases of num_dashes == 0, 1, or 3 elements * cannot exist, so the rotation of 2 elements * will always be safe */ @@ -1251,7 +1261,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators, int utf8_len, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_scaled_font_subsets_glyph_t subset_glyph; @@ -1293,7 +1303,10 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators, /* Fallback to using ActualText to map zero or more glyphs to a * unicode string. */ - _cairo_pdf_operators_flush_glyphs (pdf_operators); + status = _cairo_pdf_operators_flush_glyphs (pdf_operators); + if (status) + return status; + status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len); if (status) return status; @@ -1316,7 +1329,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators, if (status) return status; - if (backward) + if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) cur_glyph--; else cur_glyph++; @@ -1338,7 +1351,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_status_t status; @@ -1357,7 +1370,9 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, pdf_operators->is_new_text_object = FALSE; if (pdf_operators->in_text_object == FALSE) { - _cairo_pdf_operators_begin_text (pdf_operators); + status = _cairo_pdf_operators_begin_text (pdf_operators); + if (status) + return status; /* Force Tm and Tf to be emitted when starting a new text * object.*/ @@ -1376,7 +1391,10 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, if (pdf_operators->is_new_text_object || ! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix)) { - _cairo_pdf_operators_flush_glyphs (pdf_operators); + status = _cairo_pdf_operators_flush_glyphs (pdf_operators); + if (status) + return status; + x = glyphs[0].x; y = glyphs[0].y; cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y); @@ -1391,25 +1409,25 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, if (num_clusters > 0) { cur_text = utf8; - if (backward) + if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) cur_glyph = glyphs + num_glyphs; else cur_glyph = glyphs; for (i = 0; i < num_clusters; i++) { - if (backward) + if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) cur_glyph -= clusters[i].num_glyphs; status = _cairo_pdf_operators_emit_cluster (pdf_operators, cur_text, clusters[i].num_bytes, cur_glyph, clusters[i].num_glyphs, - backward, + cluster_flags, scaled_font); if (status) return status; cur_text += clusters[i].num_bytes; - if (!backward) + if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) cur_glyph += clusters[i].num_glyphs; } } else { diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h index a2962f848dfe..ab222ded87d3 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h @@ -96,7 +96,7 @@ typedef struct _cairo_pdf_smask_group int num_glyphs; cairo_text_cluster_t *clusters; int num_clusters; - cairo_bool_t backward; + cairo_bool_t cluster_flags; cairo_scaled_font_t *scaled_font; } cairo_pdf_smask_group_t; diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c index de64c0c08990..44f0ed839bc0 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -44,10 +44,11 @@ #include "cairo-pdf.h" #include "cairo-pdf-surface-private.h" #include "cairo-pdf-operators-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-paginated-private.h" -#include "cairo-output-stream-private.h" +#include "cairo-analysis-surface-private.h" #include "cairo-meta-surface-private.h" +#include "cairo-output-stream-private.h" +#include "cairo-paginated-private.h" +#include "cairo-scaled-font-subsets-private.h" #include "cairo-type3-glyph-surface-private.h" #include @@ -325,7 +326,10 @@ BAIL0: /** * cairo_pdf_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data + * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL + * to indicate a no-op @write_func. With a no-op @write_func, + * the surface may be queried or used as a source without + * generating any temporary files. * @closure: the closure argument for @write_func * @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) @@ -362,7 +366,10 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, /** * cairo_pdf_surface_create: - * @filename: a filename for the PDF output (must be writable) + * @filename: a filename for the PDF output (must be writable), %NULL may be + * used to specify no output. This will generate a PDF surface that + * may be queried and used as a source, without generating a + * temporary file. * @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) * @@ -1276,8 +1283,8 @@ _cairo_pdf_surface_start_page (void *abstract_surface) } static cairo_int_status_t -_cairo_pdf_surface_has_fallback_images (void *abstract_surface, - cairo_bool_t has_fallbacks) +_cairo_pdf_surface_has_fallback_images (void *abstract_surface, + cairo_bool_t has_fallbacks) { cairo_status_t status; cairo_pdf_surface_t *surface = abstract_surface; @@ -1290,6 +1297,12 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } +static cairo_bool_t +_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface) +{ + return TRUE; +} + /* Emit alpha channel from the image into the given data, providing * an id that can be used to reference the resulting SMask object. * @@ -2609,13 +2622,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface, { cairo_status_t status; int alpha; - cairo_bool_t is_solid_color = FALSE; - cairo_color_t *solid_color; + cairo_color_t *solid_color = NULL; if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; - is_solid_color = TRUE; solid_color = &solid->color; } @@ -2624,13 +2635,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface, { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; - if (gradient->n_stops == 1) { - is_solid_color = TRUE; + if (gradient->n_stops == 1) solid_color = &gradient->stops[0].color; - } } - if (is_solid_color) { + if (solid_color != NULL) { if (surface->current_pattern_is_solid_color == FALSE || surface->current_color_red != solid_color->red || surface->current_color_green != solid_color->green || @@ -2960,7 +2969,11 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface, "<%02x> ", i + 1); } - _cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]); + status = _cairo_pdf_surface_emit_unicode_for_glyph (surface, + font_subset->utf8[i + 1]); + if (status) + return status; + _cairo_output_stream_printf (surface->output, "\n"); } @@ -3480,6 +3493,41 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image, return _cairo_output_stream_get_status (stream); } +static cairo_status_t +_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) +{ + cairo_pdf_surface_t *surface = closure; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status2; + unsigned int i; + cairo_surface_t *type3_surface; + cairo_output_stream_t *null_stream; + + null_stream = _cairo_null_stream_create (); + type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, + null_stream, + _cairo_pdf_emit_imagemask, + surface->font_subsets); + _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface, + _cairo_pdf_surface_add_font, + surface); + + for (i = 0; i < font_subset->num_glyphs; i++) { + status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, + font_subset->glyphs[i]); + if (status) + break; + } + + cairo_surface_destroy (type3_surface); + status2 = _cairo_output_stream_destroy (null_stream); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + + return status; +} + static cairo_status_t _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -3512,9 +3560,14 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } + _cairo_pdf_group_resources_clear (&surface->resources); type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL, - _cairo_pdf_emit_imagemask); + _cairo_pdf_emit_imagemask, + surface->font_subsets); + _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface, + _cairo_pdf_surface_add_font, + surface); for (i = 0; i < font_subset->num_glyphs; i++) { status = _cairo_pdf_surface_open_stream (surface, @@ -3525,18 +3578,11 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, break; glyphs[i] = surface->pdf_stream.self; - if (i == 0) { - status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface, - surface->output, - &bbox, - &widths[i]); - } else { - status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, - surface->output, - font_subset->glyphs[i], - &bbox, - &widths[i]); - } + status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, + surface->output, + font_subset->glyphs[i], + &bbox, + &widths[i]); if (status) break; @@ -3642,6 +3688,10 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, "]\n"); free (widths); + _cairo_output_stream_printf (surface->output, + " /Resources\n"); + _cairo_pdf_surface_emit_group_resources (surface, &surface->resources); + if (to_unicode_stream.id != 0) _cairo_output_stream_printf (surface->output, " /ToUnicode %d 0 R\n", @@ -3713,6 +3763,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) { cairo_status_t status; + status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, + _cairo_pdf_surface_analyze_user_font_subset, + surface); + if (status) + goto BAIL; + status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, _cairo_pdf_surface_emit_unscaled_font_subset, surface); @@ -3722,6 +3778,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, _cairo_pdf_surface_emit_scaled_font_subset, surface); + if (status) + goto BAIL; + + status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, + _cairo_pdf_surface_emit_scaled_font_subset, + surface); BAIL: _cairo_scaled_font_subsets_destroy (surface->font_subsets); @@ -3985,7 +4047,7 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface, group->utf8, group->utf8_len, group->glyphs, group->num_glyphs, group->clusters, group->num_clusters, - group->backward, + group->cluster_flags, group->scaled_font); break; } @@ -4414,19 +4476,21 @@ _cairo_pdf_surface_mask (void *abstract_surface, { cairo_pdf_surface_t *surface = abstract_surface; cairo_pdf_smask_group_t *group; - cairo_status_t status, status2; + cairo_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - status = _cairo_pdf_surface_analyze_operation (surface, op, source); - if (status != CAIRO_STATUS_SUCCESS && - status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - return status; + cairo_status_t source_status, mask_status; - status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask); - if (status2 != CAIRO_STATUS_SUCCESS) - return status2; + source_status = _cairo_pdf_surface_analyze_operation (surface, op, source); + if (_cairo_status_is_error (source_status)) + return source_status; - return status; + mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask); + if (_cairo_status_is_error (mask_status)) + return mask_status; + + return _cairo_analysis_surface_merge_status (source_status, + mask_status); } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { status = _cairo_pdf_surface_start_fallback (surface); if (status) @@ -4756,7 +4820,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_pdf_surface_t *surface = abstract_surface; @@ -4858,7 +4922,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward, + cluster_flags, scaled_font); if (status) return status; @@ -4922,9 +4986,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { _cairo_pdf_surface_show_text_glyphs, }; -static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = { +static const cairo_paginated_surface_backend_t +cairo_pdf_surface_paginated_backend = { _cairo_pdf_surface_start_page, _cairo_pdf_surface_set_paginated_mode, NULL, /* set_bounding_box */ _cairo_pdf_surface_has_fallback_images, + _cairo_pdf_surface_supports_fine_grained_fallbacks, }; diff --git a/gfx/cairo/cairo/src/cairo-png.c b/gfx/cairo/cairo/src/cairo-png.c index d807dac78bcc..06e7cb557502 100644 --- a/gfx/cairo/cairo/src/cairo-png.c +++ b/gfx/cairo/cairo/src/cairo-png.c @@ -524,7 +524,7 @@ read_png (png_rw_ptr read_func, png_get_IHDR (png, info, &png_width, &png_height, &depth, &color_type, &interlace, NULL, NULL); - if (depth != 8 || interlace != PNG_INTERLACE_NONE || + if (depth != 8 || ! (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)) { diff --git a/gfx/cairo/cairo/src/cairo-polygon.c b/gfx/cairo/cairo/src/cairo-polygon.c index 1653f958113f..1392bfa1847d 100644 --- a/gfx/cairo/cairo/src/cairo-polygon.c +++ b/gfx/cairo/cairo/src/cairo-polygon.c @@ -36,11 +36,6 @@ #include "cairoint.h" -/* private functions */ - -static cairo_status_t -_cairo_polygon_grow (cairo_polygon_t *polygon); - void _cairo_polygon_init (cairo_polygon_t *polygon) { @@ -57,31 +52,17 @@ _cairo_polygon_init (cairo_polygon_t *polygon) void _cairo_polygon_fini (cairo_polygon_t *polygon) { - if (polygon->edges && polygon->edges != polygon->edges_embedded) + if (polygon->edges != polygon->edges_embedded) free (polygon->edges); - - polygon->edges = NULL; - polygon->edges_size = 0; - polygon->num_edges = 0; - - polygon->has_current_point = FALSE; -} - -cairo_status_t -_cairo_polygon_status (cairo_polygon_t *polygon) -{ - return polygon->status; } /* make room for at least one more edge */ -static cairo_status_t +static cairo_bool_t _cairo_polygon_grow (cairo_polygon_t *polygon) { cairo_edge_t *new_edges; int old_size = polygon->edges_size; - int new_size = 2 * old_size; - - assert (polygon->num_edges <= polygon->edges_size); + int new_size = 4 * old_size; if (polygon->edges == polygon->edges_embedded) { new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t)); @@ -92,34 +73,34 @@ _cairo_polygon_grow (cairo_polygon_t *polygon) new_size, sizeof (cairo_edge_t)); } - if (new_edges == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (new_edges == NULL) { + polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return FALSE; + } polygon->edges = new_edges; polygon->edges_size = new_size; - return CAIRO_STATUS_SUCCESS; + return TRUE; } -void -_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2) +static void +_cairo_polygon_add_edge (cairo_polygon_t *polygon, + const cairo_point_t *p1, + const cairo_point_t *p2) { cairo_edge_t *edge; - if (polygon->status) - return; - /* drop horizontal edges */ if (p1->y == p2->y) goto DONE; - if (polygon->num_edges >= polygon->edges_size) { - polygon->status = _cairo_polygon_grow (polygon); - if (polygon->status) + if (polygon->num_edges == polygon->edges_size) { + if (! _cairo_polygon_grow (polygon)) return; } - edge = &polygon->edges[polygon->num_edges]; + edge = &polygon->edges[polygon->num_edges++]; if (p1->y < p2->y) { edge->edge.p1 = *p1; edge->edge.p2 = *p2; @@ -130,18 +111,14 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin edge->clockWise = 0; } - polygon->num_edges++; - DONE: _cairo_polygon_move_to (polygon, p2); } void -_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point) +_cairo_polygon_move_to (cairo_polygon_t *polygon, + const cairo_point_t *point) { - if (polygon->status) - return; - if (! polygon->has_current_point) polygon->first_point = *point; @@ -150,24 +127,18 @@ _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point) } void -_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point) +_cairo_polygon_line_to (cairo_polygon_t *polygon, + const cairo_point_t *point) { - if (polygon->status) - return; - - if (polygon->has_current_point) { + if (polygon->has_current_point) _cairo_polygon_add_edge (polygon, &polygon->current_point, point); - } else { + else _cairo_polygon_move_to (polygon, point); - } } void _cairo_polygon_close (cairo_polygon_t *polygon) { - if (polygon->status) - return; - if (polygon->has_current_point) { _cairo_polygon_add_edge (polygon, &polygon->current_point, diff --git a/gfx/cairo/cairo/src/cairo-ps-surface-private.h b/gfx/cairo/cairo/src/cairo-ps-surface-private.h index 79ac983ae294..e78833d05cb3 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h @@ -72,10 +72,7 @@ typedef struct cairo_ps_surface { cairo_bool_t use_string_datasource; cairo_bool_t current_pattern_is_solid_color; - double current_color_red; - double current_color_green; - double current_color_blue; - double current_color_alpha; + cairo_color_t current_color; int num_pages; diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index f2c4b731926b..bfe424dde625 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -40,6 +40,19 @@ * Adrian Johnson */ + +/* + * Design of the PS output: + * + * The PS output is harmonised with the PDF operations using PS procedures + * to emulate the PDF operators. + * + * This has a number of advantages: + * 1. A large chunk of code is shared between the PDF and PS backends. + * See cairo-pdf-operators. + * 2. Using gs to do PS -> PDF and PDF -> PS will always work well. + */ + #define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */ #include "cairoint.h" #include "cairo-ps.h" @@ -173,6 +186,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "/S { stroke } bind def\n" "/f { fill } bind def\n" "/f* { eofill } bind def\n" + "/B { fill stroke } bind def\n" + "/B* { eofill stroke } bind def\n" "/n { newpath } bind def\n" "/W { clip } bind def\n" "/W* { eoclip } bind def\n" @@ -196,12 +211,12 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n" " cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n" "/Tf { pop /cairo_font exch def /cairo_font_matrix where\n" - " { cairo_selectfont } if } bind def\n" + " { pop cairo_selectfont } if } bind def\n" "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n" " /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n" - " /cairo_font where { cairo_selectfont } if } bind def\n" + " /cairo_font where { pop cairo_selectfont } if } bind def\n" "/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n" - " cairo_store_point /cairo_font where { cairo_selectfont } if } bind def\n" + " cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n" "/g { setgray } bind def\n" "/rg { setrgbcolor } bind def\n" "/d1 { setcachedevice } bind def\n"); @@ -426,6 +441,32 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image, return _cairo_output_stream_get_status (stream); } +static cairo_status_t +_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) +{ + cairo_ps_surface_t *surface = closure; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + unsigned int i; + cairo_surface_t *type3_surface; + + type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, + NULL, + _cairo_ps_emit_imagemask, + surface->font_subsets); + + for (i = 0; i < font_subset->num_glyphs; i++) { + status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, + font_subset->glyphs[i]); + if (status) + break; + + } + cairo_surface_destroy (type3_surface); + + return status; +} + static cairo_status_t _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -439,6 +480,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, cairo_surface_t *type3_surface; double width; + if (font_subset->num_glyphs == 0) + return CAIRO_STATUS_SUCCESS; + #if DEBUG_PS _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_type3_font_subset\n"); @@ -453,9 +497,10 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL, - _cairo_ps_emit_imagemask); + _cairo_ps_emit_imagemask, + surface->font_subsets); - for (i = 1; i < font_subset->num_glyphs; i++) { + for (i = 0; i < font_subset->num_glyphs; i++) { if (font_subset->glyph_names != NULL) { _cairo_output_stream_printf (surface->final_stream, "Encoding %d /%s put\n", @@ -472,20 +517,13 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, for (i = 0; i < font_subset->num_glyphs; i++) { _cairo_output_stream_printf (surface->final_stream, " { %% %d\n", i); - if (i == 0) { - status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface, - surface->final_stream, - &bbox, - &width); - } else { - status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, - surface->final_stream, - font_subset->glyphs[i], - &bbox, - &width); - } + status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, + surface->final_stream, + font_subset->glyphs[i], + &bbox, + &width); if (status) - return status; + break; _cairo_output_stream_printf (surface->final_stream, " }\n"); @@ -506,13 +544,16 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, } } cairo_surface_destroy (type3_surface); + if (status) + return status; _cairo_output_stream_printf (surface->final_stream, "] def\n" "/FontBBox [%f %f %f %f] def\n" "/BuildChar {\n" " exch /Glyphs get\n" - " exch get exec\n" + " exch get\n" + " 10 dict begin exec end\n" "} bind def\n" "currentdict\n" "end\n" @@ -586,6 +627,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) "%% _cairo_ps_surface_emit_font_subsets\n"); #endif + status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, + _cairo_ps_surface_analyze_user_font_subset, + surface); + if (status) + goto BAIL; + status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, _cairo_ps_surface_emit_unscaled_font_subset, surface); @@ -595,7 +642,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, _cairo_ps_surface_emit_scaled_font_subset, surface); + if (status) + goto BAIL; + status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, + _cairo_ps_surface_emit_scaled_font_subset, + surface); BAIL: _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; @@ -734,7 +786,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, /** * cairo_ps_surface_create: - * @filename: a filename for the PS output (must be writable) + * @filename: a filename for the PS output (must be writable), %NULL may be + * used to specify no output. This will generate a PS surface that + * may be queried and used as a source, without generating a + * temporary file. * @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) * @@ -774,7 +829,10 @@ cairo_ps_surface_create (const char *filename, /** * cairo_ps_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data + * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL + * to indicate a no-op @write_func. With a no-op @write_func, + * the surface may be queried or used as a source without + * generating any temporary files. * @closure: the closure argument for @write_func * @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) @@ -1422,12 +1480,25 @@ static cairo_bool_t _gradient_pattern_supported (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) { + cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; + uint16_t alpha; cairo_extend_t extend; + unsigned int i; if (surface->ps_level == CAIRO_PS_LEVEL_2) return FALSE; - surface->ps_level_used = CAIRO_PS_LEVEL_3; + if (gradient->n_stops == 0) + return TRUE; + + /* Alpha gradients are only supported (by flattening the alpha) + * if there is no variation in the alpha across the gradient. */ + alpha = gradient->stops[0].color.alpha_short; + for (i = 0; i < gradient->n_stops; i++) { + if (gradient->stops[i].color.alpha_short != alpha) + return FALSE; + } + extend = cairo_pattern_get_extend (pattern); /* Radial gradients are currently only supported when one circle @@ -1454,6 +1525,8 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface, } } + surface->ps_level_used = CAIRO_PS_LEVEL_3; + return TRUE; } @@ -1504,7 +1577,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface, * surface. If the analysis surface determines that there is * anything drawn under this operation, a fallback image will be * used. Otherwise the operation will be replayed during the - * render stage and we blend the transarency into the white + * render stage and we blend the transparency into the white * background to convert the pattern to opaque. */ @@ -2089,21 +2162,19 @@ _cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface, double *green, double *blue) { - *red = color->red; + *red = color->red; *green = color->green; - *blue = color->blue; + *blue = color->blue; - if (!CAIRO_COLOR_IS_OPAQUE(color)) { + if (! CAIRO_COLOR_IS_OPAQUE (color)) { + *red *= color->alpha; + *green *= color->alpha; + *blue *= color->alpha; if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) { - uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8); - - *red = ((color->red_short >> 8) + one_minus_alpha) / 255.0; - *green = ((color->green_short >> 8) + one_minus_alpha) / 255.0; - *blue = ((color->blue_short >> 8) + one_minus_alpha) / 255.0; - } else { - *red = (color->red_short >> 8) / 255.0; - *green = (color->green_short >> 8) / 255.0; - *blue = (color->blue_short >> 8) / 255.0; + double one_minus_alpha = 1. - color->alpha; + *red += one_minus_alpha; + *green += one_minus_alpha; + *blue += one_minus_alpha; } } } @@ -2826,10 +2897,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; if (surface->current_pattern_is_solid_color == FALSE || - surface->current_color_red != solid->color.red || - surface->current_color_green != solid->color.green || - surface->current_color_blue != solid->color.blue || - surface->current_color_alpha != solid->color.alpha) + ! _cairo_color_equal (&surface->current_color, &solid->color)) { status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status) @@ -2838,10 +2906,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); surface->current_pattern_is_solid_color = TRUE; - surface->current_color_red = solid->color.red; - surface->current_color_green = solid->color.green; - surface->current_color_blue = solid->color.blue; - surface->current_color_alpha = solid->color.alpha; + surface->current_color = solid->color; } return CAIRO_STATUS_SUCCESS; @@ -3223,6 +3288,12 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface, return _cairo_output_stream_get_status (surface->stream); } +static cairo_bool_t +_cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface) +{ + return TRUE; +} + static const cairo_surface_backend_t cairo_ps_surface_backend = { CAIRO_SURFACE_TYPE_PS, _cairo_ps_surface_create_similar, @@ -3261,4 +3332,6 @@ static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backen _cairo_ps_surface_start_page, _cairo_ps_surface_set_paginated_mode, _cairo_ps_surface_set_bounding_box, + NULL, /* _cairo_ps_surface_has_fallback_images, */ + _cairo_ps_surface_supports_fine_grained_fallbacks, }; diff --git a/gfx/cairo/cairo/src/cairo-quartz-font.c b/gfx/cairo/cairo/src/cairo-quartz-font.c index c6898008ded3..2bca37200eb2 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-font.c +++ b/gfx/cairo/cairo/src/cairo-quartz-font.c @@ -225,6 +225,7 @@ FINISH: static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = { CAIRO_FONT_TYPE_QUARTZ, _cairo_quartz_font_face_destroy, + NULL, /* direct implementation */ _cairo_quartz_font_face_scaled_font_create }; @@ -277,24 +278,27 @@ _cairo_quartz_scaled_to_face (void *abstract_font) } static cairo_status_t -_cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font_out) +_cairo_quartz_font_get_implementation (cairo_toy_font_face_t *toy_face, + cairo_scaled_font_t **font_face_out) { + static cairo_user_data_key_t impl_font_face_key; + cairo_font_face_t *face; + cairo_status_t status; const char *family = toy_face->family; char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc. CFStringRef cgFontName = NULL; CGFontRef cgFont = NULL; int loop; - cairo_status_t status; - cairo_font_face_t *face; - cairo_scaled_font_t *scaled_font; + face = cairo_font_face_get_user_data (&toy_face->base, + &impl_font_face_key); + if (face) { + *font_face_out = face; + return CAIRO_STATUS_SUCCESS; + } quartz_font_ensure_symbols(); - if (!_cairo_quartz_font_symbols_present) + if (! _cairo_quartz_font_symbols_present) return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* handle CSS-ish faces */ @@ -345,7 +349,7 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face, if (!cgFont) { /* Give up */ - return CAIRO_STATUS_NO_MEMORY; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } face = cairo_quartz_font_face_create_for_cgfont (cgFont); @@ -354,6 +358,35 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face, if (face->status) return face->status; + status = cairo_font_face_set_user_data (&toy_face->base, + &impl_font_face_key, + face, + (cairo_destroy_func_t) cairo_font_face_destroy); + + if (status) { + cairo_font_face_destroy (face); + return status; + } + + *font_face_out = face; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_quartz_font_create_toy (cairo_toy_font_face_t *toy_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **font_out) +{ + cairo_font_face_t *face; + cairo_scaled_font_t *scaled_font; + cairo_status_t status; + + status = _cairo_quartz_font_get_implementation (toy_face, &face); + if (status) + return status; + status = _cairo_quartz_font_face_scaled_font_create (face, font_matrix, ctm, options, @@ -363,7 +396,6 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face, return status; *font_out = scaled_font; - return CAIRO_STATUS_SUCCESS; } @@ -743,6 +775,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font, const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = { CAIRO_FONT_TYPE_QUARTZ, + _cairo_quartz_font_get_implementation, _cairo_quartz_font_create_toy, _cairo_quartz_font_fini, _cairo_quartz_font_scaled_glyph_init, diff --git a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c index 5c35fe35ef17..3eee2c1122bf 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c @@ -36,99 +36,13 @@ #include "cairoint.h" -#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE #include "cairo-quartz-image.h" -#endif - #include "cairo-quartz-private.h" #define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY))) #define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH))) #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT))) -CGImageRef -_cairo_quartz_create_cgimage (cairo_format_t format, - unsigned int width, - unsigned int height, - unsigned int stride, - void *data, - cairo_bool_t interpolate, - CGColorSpaceRef colorSpaceOverride, - CGDataProviderReleaseDataCallback releaseCallback, - void *releaseInfo) -{ - CGImageRef image = NULL; - CGDataProviderRef dataProvider = NULL; - CGColorSpaceRef colorSpace = colorSpaceOverride; - CGBitmapInfo bitinfo; - int bitsPerComponent, bitsPerPixel; - - switch (format) { - case CAIRO_FORMAT_ARGB32: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - case CAIRO_FORMAT_RGB24: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - /* XXX -- should use CGImageMaskCreate! */ - case CAIRO_FORMAT_A8: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceGray(); - bitinfo = kCGImageAlphaNone; - bitsPerComponent = 8; - bitsPerPixel = 8; - break; - - case CAIRO_FORMAT_A1: - default: - return NULL; - } - - dataProvider = CGDataProviderCreateWithData (releaseInfo, - data, - height * stride, - releaseCallback); - - if (!dataProvider) { - // manually release - if (releaseCallback) - releaseCallback (releaseInfo, data, height * stride); - goto FINISH; - } - - image = CGImageCreate (width, height, - bitsPerComponent, - bitsPerPixel, - stride, - colorSpace, - bitinfo, - dataProvider, - NULL, - interpolate, - kCGRenderingIntentDefault); - -FINISH: - - CGDataProviderRelease (dataProvider); - - if (colorSpace != colorSpaceOverride) - CGColorSpaceRelease (colorSpace); - - return image; -} - -#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE - static void DataProviderReleaseCallback (void *info, const void *data, size_t size) { @@ -370,5 +284,3 @@ cairo_quartz_image_surface_get_image (cairo_surface_t *asurface) return (cairo_surface_t*) surface->imageSurface; } - -#endif /* CAIRO_HAS_QUARTZ_IMAGE_SURFACE */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h index f321c5b68f92..8ba896874c9e 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h @@ -40,7 +40,7 @@ #include "cairoint.h" -#ifdef CAIRO_HAS_QUARTZ_SURFACE +#if CAIRO_HAS_QUARTZ_SURFACE #include "cairo-quartz.h" typedef struct cairo_quartz_surface { @@ -95,11 +95,10 @@ _cairo_quartz_create_cgimage (cairo_format_t format, CGFontRef _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont); +#else + +# error Cairo was not compiled with support for the quartz backend + #endif /* CAIRO_HAS_QUARTZ_SURFACE */ -#if CAIRO_HAS_CGFONT_FONT -CGFontRef -_cairo_cgfont_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont); -#endif /* CAIRO_HAS_CGFONT_FONT */ - #endif /* CAIRO_QUARTZ_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index c03b0cee169a..41fde0be150f 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -160,6 +160,87 @@ static void quartz_ensure_symbols(void) _cairo_quartz_symbol_lookup_done = TRUE; } +CGImageRef +_cairo_quartz_create_cgimage (cairo_format_t format, + unsigned int width, + unsigned int height, + unsigned int stride, + void *data, + cairo_bool_t interpolate, + CGColorSpaceRef colorSpaceOverride, + CGDataProviderReleaseDataCallback releaseCallback, + void *releaseInfo) +{ + CGImageRef image = NULL; + CGDataProviderRef dataProvider = NULL; + CGColorSpaceRef colorSpace = colorSpaceOverride; + CGBitmapInfo bitinfo; + int bitsPerComponent, bitsPerPixel; + + switch (format) { + case CAIRO_FORMAT_ARGB32: + if (colorSpace == NULL) + colorSpace = CGColorSpaceCreateDeviceRGB(); + bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; + bitsPerComponent = 8; + bitsPerPixel = 32; + break; + + case CAIRO_FORMAT_RGB24: + if (colorSpace == NULL) + colorSpace = CGColorSpaceCreateDeviceRGB(); + bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; + bitsPerComponent = 8; + bitsPerPixel = 32; + break; + + /* XXX -- should use CGImageMaskCreate! */ + case CAIRO_FORMAT_A8: + if (colorSpace == NULL) + colorSpace = CGColorSpaceCreateDeviceGray(); + bitinfo = kCGImageAlphaNone; + bitsPerComponent = 8; + bitsPerPixel = 8; + break; + + case CAIRO_FORMAT_A1: + default: + return NULL; + } + + dataProvider = CGDataProviderCreateWithData (releaseInfo, + data, + height * stride, + releaseCallback); + + if (!dataProvider) { + // manually release + if (releaseCallback) + releaseCallback (releaseInfo, data, height * stride); + goto FINISH; + } + + image = CGImageCreate (width, height, + bitsPerComponent, + bitsPerPixel, + stride, + colorSpace, + bitinfo, + dataProvider, + NULL, + interpolate, + kCGRenderingIntentDefault); + +FINISH: + + CGDataProviderRelease (dataProvider); + + if (colorSpace != colorSpaceOverride) + CGColorSpaceRelease (colorSpace); + + return image; +} + static inline cairo_bool_t _cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) { if (cgc == NULL) @@ -745,10 +826,13 @@ _cairo_surface_to_cgimage (cairo_surface_t *target, *image_out = NULL; } else { cairo_image_surface_t *isurf_snap = NULL; - isurf_snap = _cairo_surface_snapshot (isurf); + isurf_snap = (cairo_image_surface_t*) _cairo_surface_snapshot ((cairo_surface_t*) isurf); if (isurf_snap == NULL) return CAIRO_STATUS_NO_MEMORY; + if (isurf_snap->base.type != CAIRO_SURFACE_TYPE_IMAGE) + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + image = _cairo_quartz_create_cgimage (isurf_snap->format, isurf_snap->width, isurf_snap->height, @@ -1481,8 +1565,8 @@ _cairo_quartz_surface_create_similar (void *abstract_surface, // verify width and height of surface if (!_cairo_quartz_verify_surface_size(width, height)) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return NULL; + return _cairo_surface_create_in_error (_cairo_error + (CAIRO_STATUS_NO_MEMORY)); } return cairo_quartz_surface_create (format, width, height); @@ -1495,6 +1579,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_quartz_surface_t *new_surface = NULL; @@ -1513,6 +1599,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, width, height); + *clone_offset_x = 0; + *clone_offset_y = 0; return CAIRO_STATUS_SUCCESS; } @@ -1523,6 +1611,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, qsurf->extents.width, qsurf->extents.height); + *clone_offset_x = 0; + *clone_offset_y = 0; return CAIRO_STATUS_SUCCESS; } } @@ -1561,7 +1651,9 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, CGImageRelease (quartz_image); -FINISH: +FINISH: + *clone_offset_x = src_x; + *clone_offset_y = src_y; *clone_out = (cairo_surface_t*) new_surface; return CAIRO_STATUS_SUCCESS; diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h index d34cca6ca153..769b29f485fb 100644 --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h @@ -57,12 +57,12 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, cairo_public CGContextRef cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); +#if CAIRO_HAS_QUARTZ_FONT + /* * Quartz font support */ -#ifdef CAIRO_HAS_QUARTZ_FONT - cairo_public cairo_font_face_t * cairo_quartz_font_face_create_for_cgfont (CGFontRef font); diff --git a/gfx/cairo/cairo/src/cairo-reference-count-private.h b/gfx/cairo/cairo/src/cairo-reference-count-private.h index 8dbc1abcd934..d6adaad9683f 100644 --- a/gfx/cairo/cairo/src/cairo-reference-count-private.h +++ b/gfx/cairo/cairo/src/cairo-reference-count-private.h @@ -37,14 +37,8 @@ #ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H #define CAIRO_REFRENCE_COUNT_PRIVATE_H -#if HAVE_CONFIG_H -#include "config.h" -#endif - #include "cairo-atomic-private.h" -CAIRO_BEGIN_DECLS - /* Encapsulate operations on the object's reference count */ typedef struct { cairo_atomic_int_t ref_count; @@ -65,6 +59,4 @@ typedef struct { #define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0) -CAIRO_END_DECLS - #endif diff --git a/gfx/cairo/cairo/src/cairo-region-private.h b/gfx/cairo/cairo/src/cairo-region-private.h index 1902500de0d2..352a23f991d9 100644 --- a/gfx/cairo/cairo/src/cairo-region-private.h +++ b/gfx/cairo/cairo/src/cairo-region-private.h @@ -37,11 +37,13 @@ #ifndef CAIRO_REGION_PRIVATE_H #define CAIRO_REGION_PRIVATE_H -#include - #include "cairo-compiler-private.h" #include "cairo-types-private.h" +#include + +CAIRO_BEGIN_DECLS + /* #cairo_region_t is defined in cairoint.h */ struct _cairo_region { @@ -109,4 +111,6 @@ cairo_private pixman_region_overlap_t _cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box); +CAIRO_END_DECLS + #endif /* CAIRO_REGION_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h index c7991a7e9796..88dedb59b508 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h @@ -281,6 +281,41 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t cairo_scaled_font_subset_callback_func_t font_subset_callback, void *closure); +/** + * _cairo_scaled_font_subsets_foreach_user: + * @font_subsets: a #cairo_scaled_font_subsets_t + * @font_subset_callback: a function to be called for each font subset + * @closure: closure data for the callback function + * + * Iterate over each unique scaled font subset as created by calls to + * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by + * unique pairs of (font_id, subset_id) as returned by + * _cairo_scaled_font_subsets_map_glyph(). + * + * For each subset, @font_subset_callback will be called and will be + * provided with both a #cairo_scaled_font_subset_t object containing + * all the glyphs in the subset as well as the value of @closure. + * + * The #cairo_scaled_font_subset_t object contains the scaled_font, + * the font_id, and the subset_id corresponding to all glyphs + * belonging to the subset. In addition, it contains an array providing + * a mapping between subset glyph indices and the original scaled font + * glyph indices. + * + * The index of the array corresponds to subset_glyph_index values + * returned by _cairo_scaled_font_subsets_map_glyph() while the + * values of the array correspond to the scaled_font_glyph_index + * values passed as input to the same function. + * + * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero + * value indicating an error. Possible errors include + * %CAIRO_STATUS_NO_MEMORY. + **/ +cairo_private cairo_status_t +_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, + cairo_scaled_font_subset_callback_func_t font_subset_callback, + void *closure); + /** * _cairo_scaled_font_subset_create_glyph_names: * @font_subsets: a #cairo_scaled_font_subsets_t diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c index 939808a050c3..066f63781a7c 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c @@ -57,11 +57,18 @@ typedef enum { CAIRO_SUBSETS_COMPOSITE } cairo_subsets_type_t; +typedef enum { + CAIRO_SUBSETS_FOREACH_UNSCALED, + CAIRO_SUBSETS_FOREACH_SCALED, + CAIRO_SUBSETS_FOREACH_USER +} cairo_subsets_foreach_type_t; + typedef struct _cairo_sub_font { cairo_hash_entry_t base; cairo_bool_t is_scaled; cairo_bool_t is_composite; + cairo_bool_t is_user; cairo_scaled_font_subsets_t *parent; cairo_scaled_font_t *scaled_font; unsigned int font_id; @@ -126,7 +133,7 @@ typedef struct _cairo_string_entry { static cairo_status_t _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, - const char * utf8, + const char * utf8, int utf8_len, cairo_scaled_font_subsets_glyph_t *subset_glyph); @@ -265,6 +272,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, sub_font->is_scaled = is_scaled; sub_font->is_composite = is_composite; + sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face); _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; @@ -282,12 +290,15 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, } sub_font->next = NULL; - /* Reserve first glyph in subset for the .notdef glyph */ - status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph); - if (status) { - _cairo_hash_table_destroy (sub_font->sub_font_glyphs); - free (sub_font); - return status; + /* Reserve first glyph in subset for the .notdef glyph except for + * Type 3 fonts */ + if (! _cairo_font_face_is_user (scaled_font->font_face)) { + status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph); + if (status) { + _cairo_hash_table_destroy (sub_font->sub_font_glyphs); + free (sub_font); + return status; + } } *sub_font_out = sub_font; @@ -437,12 +448,13 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, { cairo_sub_font_glyph_t key, *sub_font_glyph; cairo_status_t status; - cairo_scaled_glyph_t *scaled_glyph; _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, (cairo_hash_entry_t **) &sub_font_glyph)) { + cairo_scaled_glyph_t *scaled_glyph; + if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) { cairo_scaled_font_subsets_glyph_t tmp_subset_glyph; @@ -450,25 +462,33 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; - /* Reserve first glyph in subset for the .notdef glyph */ - status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph); - if (status) - return status; + /* Reserve first glyph in subset for the .notdef glyph + * except for Type 3 fonts */ + if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) { + status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph); + if (status) + return status; + } } + _cairo_scaled_font_freeze_cache (sub_font->scaled_font); status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (status) + if (status) { + _cairo_scaled_font_thaw_cache (sub_font->scaled_font); return status; + } sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, sub_font->current_subset, sub_font->num_glyphs_in_current_subset, scaled_glyph->metrics.x_advance, scaled_glyph->metrics.y_advance); + _cairo_scaled_font_thaw_cache (sub_font->scaled_font); + if (sub_font_glyph == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -641,7 +661,7 @@ cairo_status_t _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, - const char * utf8, + const char * utf8, int utf8_len, cairo_scaled_font_subsets_glyph_t *subset_glyph) { @@ -691,13 +711,16 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates * empty glyphs in this case so we can put the glyph in a unscaled * subset. */ - if (scaled_font_glyph_index == 0) { + if (scaled_font_glyph_index == 0 || + _cairo_font_face_is_user (scaled_font->font_face)) { status = CAIRO_STATUS_SUCCESS; } else { + _cairo_scaled_font_freeze_cache (scaled_font); status = _cairo_scaled_glyph_lookup (scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_PATH, &scaled_glyph); + _cairo_scaled_font_thaw_cache (scaled_font); } if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) return status; @@ -744,6 +767,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, subset_glyph->is_scaled, subset_glyph->is_composite, &sub_font); + if (status) { cairo_scaled_font_destroy (unscaled_font); return status; @@ -805,19 +829,32 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, } return _cairo_sub_font_map_glyph (sub_font, - scaled_font_glyph_index, + scaled_font_glyph_index, utf8, utf8_len, - subset_glyph); + subset_glyph); } static cairo_status_t _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets, cairo_scaled_font_subset_callback_func_t font_subset_callback, void *closure, - cairo_bool_t is_scaled) + cairo_subsets_foreach_type_t type) { cairo_sub_font_collection_t collection; cairo_sub_font_t *sub_font; + cairo_bool_t is_scaled, is_user; + + is_scaled = FALSE; + is_user = FALSE; + + if (type == CAIRO_SUBSETS_FOREACH_USER) + is_user = TRUE; + + if (type == CAIRO_SUBSETS_FOREACH_SCALED || + type == CAIRO_SUBSETS_FOREACH_USER) + { + is_scaled = TRUE; + } if (is_scaled) collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; @@ -848,7 +885,9 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t sub_font = font_subsets->unscaled_sub_fonts_list; while (sub_font) { - _cairo_sub_font_collect (sub_font, &collection); + if (sub_font->is_user == is_user) + _cairo_sub_font_collect (sub_font, &collection); + sub_font = sub_font->next; } free (collection.utf8); @@ -865,7 +904,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon return _cairo_scaled_font_subsets_foreach_internal (font_subsets, font_subset_callback, closure, - TRUE); + CAIRO_SUBSETS_FOREACH_SCALED); } cairo_status_t @@ -876,7 +915,18 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *fo return _cairo_scaled_font_subsets_foreach_internal (font_subsets, font_subset_callback, closure, - FALSE); + CAIRO_SUBSETS_FOREACH_UNSCALED); +} + +cairo_status_t +_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, + cairo_scaled_font_subset_callback_func_t font_subset_callback, + void *closure) +{ + return _cairo_scaled_font_subsets_foreach_internal (font_subsets, + font_subset_callback, + closure, + CAIRO_SUBSETS_FOREACH_USER); } static cairo_bool_t @@ -937,23 +987,27 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset goto CLEANUP_HASH; } - subset->glyph_names[0] = strdup (".notdef"); - if (subset->glyph_names[0] == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_HASH; + i = 0; + if (! _cairo_font_face_is_user (subset->scaled_font->font_face)) { + subset->glyph_names[0] = strdup (".notdef"); + if (subset->glyph_names[0] == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_HASH; + } + + status = create_string_entry (subset->glyph_names[0], &entry); + if (status) + goto CLEANUP_HASH; + + status = _cairo_hash_table_insert (names, &entry->base); + if (status) { + free (entry); + goto CLEANUP_HASH; + } + i++; } - status = create_string_entry (subset->glyph_names[0], &entry); - if (status) - goto CLEANUP_HASH; - - status = _cairo_hash_table_insert (names, &entry->base); - if (status) { - free (entry); - goto CLEANUP_HASH; - } - - for (i = 1; i < subset->num_glyphs; i++) { + for (; i < subset->num_glyphs; i++) { utf8 = subset->utf8[i]; utf16 = NULL; utf16_len = 0; diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c index 385bdf03d5f4..3ec07d545c17 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -145,6 +145,9 @@ * and note that glyph origin = device-space origin. */ +static void +_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font); + static cairo_bool_t _cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b) { @@ -377,11 +380,11 @@ _cairo_scaled_font_map_destroy (void) font_map->num_holdovers--; - /* release the lock to avoid the possibility of a recursive - * deadlock when the scaled font destroy closure gets called */ - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + /* This releases the font_map lock to avoid the possibility of a + * recursive deadlock when the scaled font destroy closure gets + * called + */ _cairo_scaled_font_fini (scaled_font); - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); free (scaled_font); } @@ -407,22 +410,26 @@ _cairo_scaled_font_map_destroy (void) * * The reason we have to create a fake scaled font instead of just using * scaled_font is for lifecycle management: we need to (or rather, - * other code needs to) reference the scaked_font in the hash. + * other code needs to) reference the scaled_font in the hash table. * We can't do that on the input scaled_font as it may be freed by * font backend upon error. */ -void +cairo_status_t _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font) { - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status; cairo_scaled_font_t *placeholder_scaled_font; + assert (CAIRO_MUTEX_IS_LOCKED (_cairo_scaled_font_map_mutex)); + + status = scaled_font->status; + if (status) + return status; + placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t)); - if (!placeholder_scaled_font) { - status = CAIRO_STATUS_NO_MEMORY; - goto FREE; - } + if (placeholder_scaled_font == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* full initialization is wasteful, but who cares... */ status = _cairo_scaled_font_init (placeholder_scaled_font, @@ -432,32 +439,26 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t &scaled_font->options, NULL); if (status) - goto FINI; + goto FREE_PLACEHOLDER; placeholder_scaled_font->placeholder = TRUE; - CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex); - status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table, &placeholder_scaled_font->hash_entry); if (status) - goto UNLOCK_KEY; + goto FINI_PLACEHOLDER; - goto UNLOCK; + CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex); - UNLOCK_KEY: - CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex); + return CAIRO_STATUS_SUCCESS; - FINI: - _cairo_scaled_font_fini (placeholder_scaled_font); - - FREE: + FINI_PLACEHOLDER: + _cairo_scaled_font_fini_internal (placeholder_scaled_font); + FREE_PLACEHOLDER: free (placeholder_scaled_font); - status = _cairo_scaled_font_set_error (scaled_font, status); - - UNLOCK: - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + return _cairo_scaled_font_set_error (scaled_font, status); } void @@ -473,33 +474,36 @@ _cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t (cairo_hash_entry_t**) &placeholder_scaled_font); assert (found); assert (placeholder_scaled_font->placeholder); + assert (CAIRO_MUTEX_IS_LOCKED (placeholder_scaled_font->mutex)); _cairo_hash_table_remove (cairo_scaled_font_map->hash_table, &scaled_font->hash_entry); - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + + CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex); cairo_scaled_font_destroy (placeholder_scaled_font); + CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); } static void -_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *scaled_font) +_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font) { /* reference the place holder so it doesn't go away */ - cairo_scaled_font_reference (scaled_font); + cairo_scaled_font_reference (placeholder_scaled_font); /* now unlock the fontmap mutex so creation has a chance to finish */ CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); /* wait on placeholder mutex until we are awaken */ - CAIRO_MUTEX_LOCK (scaled_font->mutex); + CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex); /* ok, creation done. just clean up and back out */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); + CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex); + cairo_scaled_font_destroy (placeholder_scaled_font); + CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); - cairo_scaled_font_destroy (scaled_font); } /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) @@ -569,11 +573,11 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_ sizeof(cairo_matrix_t)) == 0 && memcmp ((unsigned char *)(&key_a->ctm.xx), (unsigned char *)(&key_b->ctm.xx), - sizeof(double) * 4) == 0 && + sizeof(cairo_matrix_t)) == 0 && cairo_font_options_equal (&key_a->options, &key_b->options)); } -/* XXX: This 256 number is arbitary---we've never done any measurement +/* XXX: This 256 number is arbitrary---we've never done any measurement * of this. In fact, having a per-font glyph caches each managed * separately is probably not what we want anyway. Would probably be * much better to have a single cache for glyphs with random @@ -656,6 +660,10 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, void _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font) { + /* ensure we do not modify an error object */ + assert (scaled_font->status == CAIRO_STATUS_SUCCESS); + + CAIRO_MUTEX_LOCK (scaled_font->mutex); _cairo_cache_freeze (scaled_font->glyphs); } @@ -663,11 +671,14 @@ void _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) { _cairo_cache_thaw (scaled_font->glyphs); + CAIRO_MUTEX_UNLOCK (scaled_font->mutex); } void _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font) { + assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex)); + _cairo_cache_destroy (scaled_font->glyphs); scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, _cairo_scaled_glyph_destroy, @@ -701,8 +712,8 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, return CAIRO_STATUS_SUCCESS; } -void -_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) +static void +_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) { scaled_font->finished = TRUE; @@ -724,6 +735,16 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) _cairo_user_data_array_fini (&scaled_font->user_data); } +void +_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) +{ + /* Release the lock to avoid the possibility of a recursive + * deadlock when the scaled font destroy closure gets called. */ + CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + _cairo_scaled_font_fini_internal (scaled_font); + CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); +} + /** * cairo_scaled_font_create: * @font_face: a #cairo_font_face_t @@ -735,8 +756,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) * @ctm: user to device transformation matrix with which the font will * be used. * @options: options to use when getting metrics for the font and - * rendering with it. A %NULL pointer will be interpreted as - * meaning the default options. + * rendering with it. * * Creates a #cairo_scaled_font_t object from a font face and matrices that * describe the size of the font and the environment in which it will @@ -752,6 +772,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, const cairo_font_options_t *options) { cairo_status_t status; + cairo_font_face_t *impl_face; cairo_scaled_font_map_t *font_map; cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL; @@ -765,11 +786,19 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, /* Note that degenerate ctm or font_matrix *are* allowed. * We want to support a font size of 0. */ + if (font_face->backend->get_implementation != NULL) { + /* indirect implementation, lookup the face that is used for the key */ + status = font_face->backend->get_implementation (font_face, &impl_face); + if (status) + return _cairo_scaled_font_create_in_error (status); + } else + impl_face = font_face; + font_map = _cairo_scaled_font_map_lock (); if (font_map == NULL) return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - _cairo_scaled_font_init_key (&key, font_face, + _cairo_scaled_font_init_key (&key, impl_face, font_matrix, ctm, options); scaled_font = font_map->mru_scaled_font; if (scaled_font != NULL && @@ -876,7 +905,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, /* We can't call _cairo_scaled_font_destroy here since it expects * that the font has already been successfully inserted into the * hash table. */ - _cairo_scaled_font_fini (scaled_font); + _cairo_scaled_font_fini_internal (scaled_font); free (scaled_font); return _cairo_scaled_font_create_in_error (status); } @@ -980,6 +1009,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) cairo_scaled_font_t *lru = NULL; cairo_scaled_font_map_t *font_map; + assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex)); + if (scaled_font == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) return; @@ -1020,7 +1051,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) } - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + _cairo_scaled_font_map_unlock (); /* If we pulled an item from the holdovers array, (while the font * map lock was held, of course), then there is no way that anyone @@ -1029,7 +1060,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) * as we never want to call into any backend function with a lock * held. */ if (lru) { - _cairo_scaled_font_fini (lru); + _cairo_scaled_font_fini_internal (lru); free (lru); } } @@ -1103,12 +1134,19 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, cairo_destroy_func_t destroy) { if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return scaled_font->status; return _cairo_user_data_array_set_data (&scaled_font->user_data, key, user_data, destroy); } +static cairo_bool_t +_cairo_scaled_font_is_frozen (cairo_scaled_font_t *scaled_font) +{ + return CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex) && + scaled_font->glyphs->freeze_count > 0; +} + /* Public font API follows. */ /** @@ -1122,6 +1160,15 @@ void cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *extents) { + if (scaled_font->status) { + extents->ascent = 0.0; + extents->descent = 0.0; + extents->height = 0.0; + extents->max_x_advance = 0.0; + extents->max_y_advance = 0.0; + return; + } + *extents = scaled_font->extents; } slim_hidden_def (cairo_scaled_font_extents); @@ -1169,8 +1216,10 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font, &glyphs, &num_glyphs, NULL, NULL, NULL); - if (status) + if (status) { + status = _cairo_scaled_font_set_error (scaled_font, status); goto ZERO_EXTENTS; + } cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents); free (glyphs); @@ -1241,7 +1290,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, return; } - CAIRO_MUTEX_LOCK (scaled_font->mutex); _cairo_scaled_font_freeze_cache (scaled_font); for (i = 0; i < num_glyphs; i++) { @@ -1310,7 +1358,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, UNLOCK: _cairo_scaled_font_thaw_cache (scaled_font); - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); } slim_hidden_def (cairo_scaled_font_glyph_extents); @@ -1325,8 +1372,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * @num_glyphs: pointer to number of glyphs * @clusters: pointer to array of cluster mapping information to fill, or %NULL * @num_clusters: pointer to number of clusters, or %NULL - * @backward: pointer to whether the text to glyphs mapping goes backward, or - * %NULL + * @cluster_flags: pointer to location to store cluster flags corresponding to the + * output @clusters, or %NULL * * Converts UTF-8 text to an array of glyphs, optionally with cluster * mapping, that can be used to render later using @scaled_font. @@ -1336,11 +1383,12 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * entries available there. If the provided glyph array is too short for * the conversion, a new glyph array is allocated using cairo_glyph_allocate() * and placed in @glyphs. Upon return, @num_glyphs always contains the - * number of generated glyphs. If the value @glyphs points at has changed + * number of generated glyphs. If the value @glyphs points to has changed * after the call, the user is responsible for freeing the allocated glyph - * array using cairo_glyph_free(). + * array using cairo_glyph_free(). This may happen even if the provided + * array was large enough. * - * If @clusters is not %NULL, @num_clusters and @backward should not be %NULL, + * If @clusters is not %NULL, @num_clusters and @cluster_flags should not be %NULL, * and cluster mapping will be computed. * The semantics of how cluster array allocation works is similar to the glyph * array. That is, @@ -1351,7 +1399,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * and placed in @clusters. Upon return, @num_clusters always contains the * number of generated clusters. If the value @clusters points at has changed * after the call, the user is responsible for freeing the allocated cluster - * array using cairo_text_cluster_free(). + * array using cairo_text_cluster_free(). This may happen even if the provided + * array was large enough. * * In the simplest case, @glyphs and @clusters can point to %NULL initially * and a suitable array will be allocated. In code: @@ -1362,21 +1411,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * int num_glyphs; * cairo_text_cluster_t *clusters = NULL; * int num_clusters; - * cairo_bool_t backward; + * cairo_text_cluster_flags_t cluster_flags; * * status = cairo_scaled_font_text_to_glyphs (scaled_font, * x, y, * utf8, utf8_len, * &glyphs, &num_glyphs, - * &clusters, &num_clusters, - * &backward); + * &clusters, &num_clusters, &cluster_flags); * * if (status == CAIRO_STATUS_SUCCESS) { * cairo_show_text_glyphs (cr, * utf8, utf8_len, * *glyphs, *num_glyphs, - * *clusters, *num_clusters, - * *backward); + * *clusters, *num_clusters, *cluster_flags); * * cairo_glyph_free (*glyphs); * cairo_text_cluster_free (*clusters); @@ -1414,21 +1461,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * cairo_text_cluster_t stack_clusters[40]; * cairo_text_cluster_t *clusters = stack_clusters; * int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]); - * cairo_bool_t backward; + * cairo_text_cluster_flags_t cluster_flags; * * status = cairo_scaled_font_text_to_glyphs (scaled_font, * x, y, * utf8, utf8_len, * &glyphs, &num_glyphs, - * &clusters, &num_clusters, - * &backward); + * &clusters, &num_clusters, &cluster_flags); * * if (status == CAIRO_STATUS_SUCCESS) { * cairo_show_text_glyphs (cr, * utf8, utf8_len, * *glyphs, *num_glyphs, - * *clusters, *num_clusters, - * *backward); + * *clusters, *num_clusters, *cluster_flags); * * if (glyphs != stack_glyphs) * cairo_glyph_free (*glyphs); @@ -1437,7 +1482,7 @@ slim_hidden_def (cairo_scaled_font_glyph_extents); * } * * - * For details of how @clusters, @num_clusters, and @backward map input + * For details of how @clusters, @num_clusters, and @cluster_flags map input * UTF-8 text to the output glyphs see cairo_show_text_glyphs(). * * The output values can be readily passed to cairo_show_text_glyphs() @@ -1461,7 +1506,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, int *num_glyphs, cairo_text_cluster_t **clusters, int *num_clusters, - cairo_bool_t *backward) + cairo_text_cluster_flags_t *cluster_flags) { int i; int num_chars = 0; @@ -1488,9 +1533,9 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, utf8_len = 0; /* No NULLs for non-NULLs! */ - if ((utf8_len && utf8 == NULL) || - (clusters && num_clusters == NULL) || - (clusters && backward == NULL)) { + if ((utf8_len && utf8 == NULL) || + (clusters && num_clusters == NULL) || + (clusters && cluster_flags == NULL)) { status = CAIRO_STATUS_NULL_POINTER; goto BAIL; } @@ -1511,12 +1556,12 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, num_clusters = NULL; } - if (backward) { - *backward = FALSE; + if (cluster_flags) { + *cluster_flags = FALSE; } - if (!clusters && backward) { - backward = NULL; + if (!clusters && cluster_flags) { + cluster_flags = NULL; } /* Apart from that, no negatives */ @@ -1537,7 +1582,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, if (status) goto BAIL; - CAIRO_MUTEX_LOCK (scaled_font->mutex); _cairo_scaled_font_freeze_cache (scaled_font); orig_glyphs = *glyphs; @@ -1549,7 +1593,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward); + cluster_flags); if (status != CAIRO_INT_STATUS_UNSUPPORTED) { @@ -1583,7 +1627,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, status = _cairo_validate_text_clusters (utf8, utf8_len, *glyphs, *num_glyphs, *clusters, *num_clusters, - *backward); + *cluster_flags); } } @@ -1643,7 +1687,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, DONE: /* error that should be logged on scaled_font happened */ _cairo_scaled_font_thaw_cache (scaled_font); - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); if (status) { *num_glyphs = 0; @@ -1692,6 +1735,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, if (scaled_font->status) return scaled_font->status; + _cairo_scaled_font_freeze_cache (scaled_font); + for (i = 0; i < num_glyphs; i++) { cairo_scaled_glyph_t *scaled_glyph; int left, top; @@ -1703,7 +1748,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) - return _cairo_scaled_font_set_error (scaled_font, status); + break; /* XXX glyph images are snapped to pixel locations */ x = _cairo_lround (glyphs[i].x); @@ -1719,6 +1764,11 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, if (top < min.y) min.y = top; if (bottom > max.y) max.y = bottom; } + + _cairo_scaled_font_thaw_cache (scaled_font); + if (status) + return _cairo_scaled_font_set_error (scaled_font, status); + if (min.x < max.x && min.y < max.y) { extents->x = min.x; extents->width = max.x - min.x; @@ -1728,6 +1778,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, extents->x = extents->y = 0; extents->width = extents->height = 0; } + return CAIRO_STATUS_SUCCESS; } @@ -1784,7 +1835,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, _cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); - _cairo_cache_freeze (scaled_font->glyphs); + _cairo_scaled_font_freeze_cache (scaled_font); for (i = 0; i < num_glyphs; i++) { int x, y; @@ -1904,7 +1955,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, _cairo_pattern_fini (&mask_pattern.base); CLEANUP_MASK: - _cairo_cache_thaw (scaled_font->glyphs); + _cairo_scaled_font_thaw_cache (scaled_font); _cairo_pattern_fini (&white_pattern.base); @@ -2256,9 +2307,19 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph, * @index: the glyph to create * @info: a #cairo_scaled_glyph_info_t marking which portions of * the glyph should be filled in. - * @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph + * @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph * is returned. * + * If the desired info is not available, (for example, when trying to + * get INFO_PATH with a bitmapped font), this function will return + * %CAIRO_INT_STATUS_UNSUPPORTED. + * + * Note: This function must be called with the scaled font frozen, and it must + * remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled + * font was not frozen, then there is no guarantee that the glyph would not be + * evicted before you tried to access it.) See + * _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache(). + * * Returns: a glyph with the requested portions filled in. Glyph * lookup is cached and glyph will be automatically freed along * with the scaled_font so no explicit free is required. @@ -2266,12 +2327,6 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph, * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space - * - * If the desired info is not available, (for example, when trying to - * get INFO_PATH with a bitmapped font), this function will return - * %CAIRO_INT_STATUS_UNSUPPORTED. - * - * Note: This function must be called with scaled_font->mutex held. **/ cairo_int_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, @@ -2287,6 +2342,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, if (scaled_font->status) return scaled_font->status; + assert (_cairo_scaled_font_is_frozen (scaled_font)); + key.hash = index; /* * Check cache for glyph diff --git a/gfx/cairo/cairo/src/cairo-skiplist.c b/gfx/cairo/cairo/src/cairo-skiplist.c index ebeb52c812b4..e2b793e157ee 100644 --- a/gfx/cairo/cairo/src/cairo-skiplist.c +++ b/gfx/cairo/cairo/src/cairo-skiplist.c @@ -322,16 +322,20 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique) /* * Find links along each chain */ + elt = NULL; next = list->chains; for (i = list->max_level; --i >= 0; ) { - for (; (elt = next[i]); next = elt->next) + if (elt != next[i]) { - int cmp = list->compare (list, ELT_DATA(elt), data); - if (unique && 0 == cmp) - return ELT_DATA(elt); - if (cmp > 0) - break; + for (; (elt = next[i]); next = elt->next) + { + int cmp = list->compare (list, ELT_DATA(elt), data); + if (unique && 0 == cmp) + return ELT_DATA(elt); + if (cmp > 0) + break; + } } update[i] = next; if (next != list->chains) diff --git a/gfx/cairo/cairo/src/cairo-slope.c b/gfx/cairo/cairo/src/cairo-slope.c index d3f0db42e43d..35c537221e87 100644 --- a/gfx/cairo/cairo/src/cairo-slope.c +++ b/gfx/cairo/cairo/src/cairo-slope.c @@ -37,7 +37,9 @@ #include "cairoint.h" void -_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b) +_cairo_slope_init (cairo_slope_t *slope, + const cairo_point_t *a, + const cairo_point_t *b) { slope->dx = b->x - a->x; slope->dy = b->y - a->y; @@ -62,17 +64,15 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b) > 0 => a more positive than b */ int -_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b) +_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b) { - cairo_fixed_48_16_t diff; + cairo_int64_t ady_bdx = _cairo_int32x32_64_mul (a->dy, b->dx); + cairo_int64_t bdy_adx = _cairo_int32x32_64_mul (b->dy, a->dx); + int cmp; - diff = ((cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx - - (cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx); - - if (diff > 0) - return 1; - if (diff < 0) - return -1; + cmp = _cairo_int64_cmp (ady_bdx, bdy_adx); + if (cmp) + return cmp; /* special-case zero vectors. the intended logic here is: * zero vectors all compare equal, and more positive than any diff --git a/gfx/cairo/cairo/src/cairo-surface-fallback-private.h b/gfx/cairo/cairo/src/cairo-surface-fallback-private.h index 82c56256b8d5..2e10241c22a9 100644 --- a/gfx/cairo/cairo/src/cairo-surface-fallback-private.h +++ b/gfx/cairo/cairo/src/cairo-surface-fallback-private.h @@ -124,6 +124,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out); #endif diff --git a/gfx/cairo/cairo/src/cairo-surface-fallback.c b/gfx/cairo/cairo/src/cairo-surface-fallback.c index eb5a23cd83c5..c44dfafae268 100644 --- a/gfx/cairo/cairo/src/cairo-surface-fallback.c +++ b/gfx/cairo/cairo/src/cairo-surface-fallback.c @@ -527,16 +527,14 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src, cairo_rectangle_int_t extents; cairo_composite_traps_info_t traps_info; - if (traps->num_traps == 0) + if (_cairo_operator_bounded_by_mask (op) && traps->num_traps == 0) return CAIRO_STATUS_SUCCESS; status = _cairo_surface_get_extents (dst, &extents); - if (status) return status; status = _cairo_traps_extract_region (traps, &trap_region); - if (CAIRO_INT_STATUS_UNSUPPORTED == status) { has_trap_region = FALSE; } else if (status) { @@ -697,14 +695,9 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface, if (status) return status; - box.p1.x = _cairo_fixed_from_int (extents.x); - box.p1.y = _cairo_fixed_from_int (extents.y); - box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); - box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); + _cairo_box_from_rectangle (&box, &extents); - status = _cairo_traps_init_box (&traps, &box); - if (status) - return status; + _cairo_traps_init_box (&traps, &box); status = _clip_and_composite_trapezoids (source, op, @@ -821,13 +814,12 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, if (status) return status; - box.p1.x = _cairo_fixed_from_int (extents.x); - box.p1.y = _cairo_fixed_from_int (extents.y); - box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); - box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); + if (extents.width == 0 || extents.height == 0) + return CAIRO_STATUS_SUCCESS; + + _cairo_box_from_rectangle (&box, &extents); _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); status = _cairo_path_fixed_stroke_to_traps (path, @@ -835,10 +827,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, ctm, ctm_inverse, tolerance, &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } + if (status) + goto FAIL; status = _clip_and_composite_trapezoids (source, op, @@ -847,6 +837,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, surface->clip, antialias); +FAIL: _cairo_traps_fini (&traps); return status; @@ -883,13 +874,12 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface, if (status) return status; - box.p1.x = _cairo_fixed_from_int (extents.x); - box.p1.y = _cairo_fixed_from_int (extents.y); - box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); - box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); + if (extents.width == 0 || extents.height == 0) + return CAIRO_STATUS_SUCCESS; + + _cairo_box_from_rectangle (&box, &extents); _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); status = _cairo_path_fixed_fill_to_traps (path, @@ -998,6 +988,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t glyph_extents; + status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, @@ -1259,6 +1250,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_status_t status; @@ -1288,9 +1281,11 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface, status = cairo_status (cr); cairo_destroy (cr); - if (status == CAIRO_STATUS_SUCCESS) + if (status == CAIRO_STATUS_SUCCESS) { + *clone_offset_x = src_x; + *clone_offset_y = src_y; *clone_out = new_surface; - else + } else cairo_surface_destroy (new_surface); return status; diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index db920a35a808..d1df1869df04 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -73,7 +73,6 @@ const cairo_surface_t name = { \ FALSE, /* has_font_options */ \ { CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ - CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \ CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \ } /* font_options */ \ @@ -239,12 +238,8 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, if (other->backend->create_similar) { surface = other->backend->create_similar (other, content, width, height); - /* It's not an error if the backend didn't create a valid - * surface---it may just not be supported. */ - if (surface && surface->status) { - cairo_surface_destroy (surface); - surface = NULL; - } + if (surface != NULL && surface->status) + return surface; } if (surface == NULL) @@ -584,7 +579,7 @@ cairo_surface_set_user_data (cairo_surface_t *surface, cairo_destroy_func_t destroy) { if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return surface->status; return _cairo_user_data_array_set_data (&surface->user_data, key, user_data, destroy); @@ -611,11 +606,11 @@ _cairo_surface_set_font_options (cairo_surface_t *surface, { cairo_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); @@ -709,6 +704,9 @@ slim_hidden_def (cairo_surface_flush); void cairo_surface_mark_dirty (cairo_surface_t *surface) { + if (surface->status) + return; + assert (! surface->is_snapshot); cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1); @@ -739,11 +737,11 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, { cairo_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; @@ -797,11 +795,11 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface, { cairo_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; @@ -812,10 +810,10 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface, surface->device_transform.xy = 0.0; surface->device_transform.yx = 0.0; - surface->device_transform_inverse.xx = 1.0 / sx; - surface->device_transform_inverse.yy = 1.0 / sy; - surface->device_transform_inverse.xy = 0.0; - surface->device_transform_inverse.yx = 0.0; + surface->device_transform_inverse = surface->device_transform; + status = cairo_matrix_invert (&surface->device_transform_inverse); + /* should always be invertible unless given pathological input */ + assert (status == CAIRO_STATUS_SUCCESS); } /** @@ -843,11 +841,11 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, { cairo_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; @@ -856,8 +854,10 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, surface->device_transform.x0 = x_offset; surface->device_transform.y0 = y_offset; - surface->device_transform_inverse.x0 = - x_offset; - surface->device_transform_inverse.y0 = - y_offset; + surface->device_transform_inverse = surface->device_transform; + status = cairo_matrix_invert (&surface->device_transform_inverse); + /* should always be invertible unless given pathological input */ + assert (status == CAIRO_STATUS_SUCCESS); } slim_hidden_def (cairo_surface_set_device_offset); @@ -924,11 +924,11 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface, { cairo_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; @@ -990,11 +990,11 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface, cairo_image_surface_t **image_out, void **image_extra) { - assert (!surface->finished); - if (surface->status) return surface->status; + assert (!surface->finished); + if (surface->backend->acquire_source_image == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1059,11 +1059,11 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface, cairo_rectangle_int_t *image_rect, void **image_extra) { - assert (!surface->finished); - if (surface->status) return surface->status; + assert (!surface->finished); + if (surface->backend->acquire_dest_image == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1128,6 +1128,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -1141,8 +1143,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); if (surface->backend->clone_similar) { - status = surface->backend->clone_similar (surface, src, src_x, src_y, - width, height, clone_out); + status = surface->backend->clone_similar (surface, src, + src_x, src_y, + width, height, + clone_offset_x, + clone_offset_y, + clone_out); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { /* If we failed, try again with an image surface */ @@ -1152,6 +1158,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, surface->backend->clone_similar (surface, &image->base, src_x, src_y, width, height, + clone_offset_x, + clone_offset_y, clone_out); _cairo_surface_release_source_image (src, image, image_extra); @@ -1162,8 +1170,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, /* If we're still unsupported, hit our fallback path to get a clone */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) status = - _cairo_surface_fallback_clone_similar (surface, src, src_x, src_y, - width, height, clone_out); + _cairo_surface_fallback_clone_similar (surface, src, + src_x, src_y, + width, height, + clone_offset_x, + clone_offset_y, + clone_out); /* We should never get UNSUPPORTED here, so if we have an error, bail. */ if (status) @@ -1172,8 +1184,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, /* Update the clone's device_transform (which the underlying surface * backend knows nothing about) */ if (*clone_out != src) { - (*clone_out)->device_transform = src->device_transform; - (*clone_out)->device_transform_inverse = src->device_transform_inverse; + (*clone_out)->device_transform = src->device_transform; + (*clone_out)->device_transform_inverse = src->device_transform_inverse; } return status; @@ -1256,8 +1268,6 @@ _cairo_surface_composite (cairo_operator_t op, { cairo_int_status_t status; - assert (! dst->is_snapshot); - if (mask) { /* These operators aren't interpreted the same way by the backends; * they are implemented in terms of other operators in cairo-gstate.c @@ -1268,6 +1278,8 @@ _cairo_surface_composite (cairo_operator_t op, if (dst->status) return dst->status; + assert (! dst->is_snapshot); + if (dst->finished) return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); @@ -1317,11 +1329,11 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface, { cairo_rectangle_int_t rect; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + if (surface->finished) return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); @@ -1359,11 +1371,11 @@ _cairo_surface_fill_region (cairo_surface_t *surface, cairo_status_t status; int i; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + num_boxes = _cairo_region_num_boxes (region); if (num_boxes == 0) @@ -1431,11 +1443,11 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface, { cairo_int_status_t status; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + if (surface->finished) return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); @@ -1462,11 +1474,11 @@ _cairo_surface_paint (cairo_surface_t *surface, cairo_status_t status; cairo_pattern_t *dev_source; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); @@ -1495,11 +1507,11 @@ _cairo_surface_mask (cairo_surface_t *surface, cairo_pattern_t *dev_source; cairo_pattern_t *dev_mask; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) goto FINISH; @@ -1607,11 +1619,11 @@ _cairo_surface_stroke (cairo_surface_t *surface, cairo_matrix_t dev_ctm = *ctm; cairo_matrix_t dev_ctm_inverse = *ctm_inverse; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); @@ -1651,11 +1663,11 @@ _cairo_surface_fill (cairo_surface_t *surface, cairo_status_t status; cairo_pattern_t *dev_source; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); @@ -1695,8 +1707,6 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op, { cairo_int_status_t status; - assert (! dst->is_snapshot); - /* These operators aren't interpreted the same way by the backends; * they are implemented in terms of other operators in cairo-gstate.c */ @@ -1705,6 +1715,8 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op, if (dst->status) return dst->status; + assert (! dst->is_snapshot); + if (dst->finished) return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); @@ -1748,11 +1760,11 @@ cairo_surface_copy_page (cairo_surface_t *surface) { cairo_status_t status_ignored; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status_ignored = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); @@ -1785,11 +1797,11 @@ cairo_surface_show_page (cairo_surface_t *surface) { cairo_status_t status_ignored; - assert (! surface->is_snapshot); - if (surface->status) return; + assert (! surface->is_snapshot); + if (surface->finished) { status_ignored = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); @@ -1809,10 +1821,12 @@ slim_hidden_def (cairo_surface_show_page); * _cairo_surface_get_current_clip_serial: * @surface: the #cairo_surface_t to return the serial number for * + * This space left intentionally blank. + * * Returns: the serial number associated with the current * clip in the surface. All gstate functions must * verify that the correct clip is set in the surface before - * invoking any surface drawing function + * invoking any surface drawing function. */ unsigned int _cairo_surface_get_current_clip_serial (cairo_surface_t *surface) @@ -1904,9 +1918,6 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface, if (surface->status) return surface->status; - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - assert (surface->backend->set_clip_region != NULL); surface->current_clip_serial = serial; @@ -2163,9 +2174,6 @@ _cairo_surface_get_extents (cairo_surface_t *surface, * function to avoid computing UTF-8 text and cluster mapping if the * target surface does not use it. * - * There is a convenience function for this that takes a #cairo_t, - * namely cairo_has_show_text_glyphs(). - * * Return value: %TRUE if @surface supports * cairo_show_text_glyphs(), %FALSE otherwise * @@ -2217,18 +2225,18 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { cairo_status_t status; cairo_scaled_font_t *dev_scaled_font = scaled_font; cairo_pattern_t *dev_source; - assert (! surface->is_snapshot); - if (surface->status) return surface->status; + assert (! surface->is_snapshot); + if (!num_glyphs && !utf8_len) return CAIRO_STATUS_SUCCESS; @@ -2259,8 +2267,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); } - CAIRO_MUTEX_LOCK (dev_scaled_font->mutex); - status = CAIRO_INT_STATUS_UNSUPPORTED; /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and @@ -2272,8 +2278,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, status = surface->backend->show_text_glyphs (surface, op, dev_source, utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - backward, + clusters, num_clusters, cluster_flags, dev_scaled_font); } if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) { @@ -2311,8 +2316,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, status = surface->backend->show_text_glyphs (surface, op, dev_source, utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - backward, + clusters, num_clusters, cluster_flags, dev_scaled_font); } } @@ -2322,8 +2326,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, glyphs, num_glyphs, dev_scaled_font); - CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex); - if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); @@ -2353,11 +2355,11 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, { cairo_status_t status; - assert (! dst->is_snapshot); - if (dst->status) return dst->status; + assert (! dst->is_snapshot); + if (dst->finished) return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); @@ -2477,11 +2479,11 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst, cairo_rectangle_int_t *src_rectangle = NULL; cairo_rectangle_int_t *mask_rectangle = NULL; - assert (! dst->is_snapshot); - if (dst->status) return dst->status; + assert (! dst->is_snapshot); + /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, * non-repeating sources and masks. Other sources and masks can be ignored. */ @@ -2555,11 +2557,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, cairo_rectangle_int_t *src_rectangle = NULL; cairo_rectangle_int_t *mask_rectangle = NULL; - assert (! dst->is_snapshot); - if (dst->status) return dst->status; + assert (! dst->is_snapshot); + /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, * non-repeating sources and masks. Other sources and masks can be ignored. */ diff --git a/gfx/cairo/cairo/src/cairo-svg-surface.c b/gfx/cairo/cairo/src/cairo-svg-surface.c index 97ceedd54cce..f392c8ed22ae 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface.c +++ b/gfx/cairo/cairo/src/cairo-svg-surface.c @@ -42,12 +42,13 @@ #define _BSD_SOURCE /* for snprintf() */ #include "cairoint.h" #include "cairo-svg.h" +#include "cairo-analysis-surface-private.h" #include "cairo-svg-surface-private.h" -#include "cairo-path-fixed-private.h" #include "cairo-meta-surface-private.h" +#include "cairo-output-stream-private.h" +#include "cairo-path-fixed-private.h" #include "cairo-paginated-private.h" #include "cairo-scaled-font-subsets-private.h" -#include "cairo-output-stream-private.h" typedef struct cairo_svg_page cairo_svg_page_t; @@ -154,7 +155,10 @@ static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backe /** * cairo_svg_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data + * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL + * to indicate a no-op @write_func. With a no-op @write_func, + * the surface may be queried or used as a source without + * generating any temporary files. * @closure: the closure argument for @write_func * @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) @@ -189,7 +193,10 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, /** * cairo_svg_surface_create: - * @filename: a filename for the SVG output (must be writable) + * @filename: a filename for the SVG output (must be writable), %NULL may be + * used to specify no output. This will generate a SVG surface that + * may be queried and used as a source, without generating a + * temporary file. * @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) * @@ -366,8 +373,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, if (content == CAIRO_CONTENT_COLOR) { _cairo_output_stream_printf (surface->xml_node, "\n", + "style=\"opacity:1;stroke:none;" + "fill:rgb(0,0,0);\"/>\n", width, height); status = _cairo_output_stream_get_status (surface->xml_node); if (status) @@ -631,7 +638,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, return status; _cairo_output_stream_printf (document->xml_node_glyphs, - "xml_node_glyphs, scaled_glyph->path, NULL); if (status) @@ -706,8 +713,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, _cairo_output_stream_printf (document->xml_node_glyphs, "\n", - font_id, - subset_glyph_index); + font_id, + subset_glyph_index); status = _cairo_svg_document_emit_outline_glyph_data (document, scaled_font, @@ -732,6 +739,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, unsigned int i; cairo_status_t status = CAIRO_STATUS_SUCCESS; + _cairo_scaled_font_freeze_cache (font_subset->scaled_font); for (i = 0; i < font_subset->num_glyphs; i++) { status = _cairo_svg_document_emit_glyph (document, font_subset->scaled_font, @@ -740,6 +748,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, if (status) break; } + _cairo_scaled_font_thaw_cache (font_subset->scaled_font); return status; } @@ -752,14 +761,48 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document) status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets, _cairo_svg_document_emit_font_subset, document); + if (status) + goto FAIL; + status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets, + _cairo_svg_document_emit_font_subset, + document); + + FAIL: _cairo_scaled_font_subsets_destroy (document->font_subsets); document->font_subsets = NULL; return status; } -static cairo_bool_t cairo_svg_force_fallbacks = FALSE; +static char const * +_cairo_svg_surface_operators[] = { + "clear", + + "src", "src-over", "src-in", + "src-out", "src-atop", + + "dst", "dst-over", "dst-in", + "dst-out", "dst-atop", + + "xor", "plus", + "color-dodge", /* FIXME: saturate ? */ +}; + +static cairo_bool_t +_cairo_svg_surface_analyze_operator (cairo_svg_surface_t *surface, + cairo_operator_t op) +{ + /* guard against newly added operators */ + if (op >= ARRAY_LENGTH (_cairo_svg_surface_operators)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* allow operators being NULL if they are unsupported */ + if (_cairo_svg_surface_operators[op] == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + return CAIRO_STATUS_SUCCESS; +} static cairo_int_status_t _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, @@ -768,8 +811,11 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, { cairo_svg_document_t *document = surface->document; - if (cairo_svg_force_fallbacks) - return FALSE; + if (surface->force_fallbacks && + surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + { + return CAIRO_INT_STATUS_UNSUPPORTED; + } /* SVG doesn't support extend reflect for image pattern */ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE && @@ -777,7 +823,7 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; if (document->svg_version >= CAIRO_SVG_VERSION_1_2) - return CAIRO_STATUS_SUCCESS; + return _cairo_svg_surface_analyze_operator (surface, op); if (op == CAIRO_OPERATOR_OVER) return CAIRO_STATUS_SUCCESS; @@ -960,31 +1006,49 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, return status; } +static void +_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, + cairo_svg_surface_t *surface, + cairo_operator_t op) +{ + if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && + op != CAIRO_OPERATOR_OVER) { + _cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op]); + if (!_cairo_operator_bounded_by_source (op)) + _cairo_output_stream_printf (output, " clip-to-self=\"true\""); + } +} + +static void +_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output, + cairo_svg_surface_t *surface, + cairo_operator_t op) +{ + if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && + op != CAIRO_OPERATOR_OVER) { + _cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op]); + if (!_cairo_operator_bounded_by_source (op)) + _cairo_output_stream_printf (output, "clip-to-self:true;"); + } +} + static cairo_status_t _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output, cairo_svg_surface_t *svg_surface, + cairo_operator_t op, cairo_surface_pattern_t *pattern, int pattern_id, const cairo_matrix_t *parent_matrix, const char *extra_attributes) { - cairo_surface_t *surface; - cairo_surface_attributes_t surface_attr; cairo_rectangle_int_t extents; cairo_status_t status; cairo_matrix_t p2u; - status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern, - (cairo_surface_t *)svg_surface, - 0, 0, (unsigned int)-1, (unsigned int)-1, - &surface, &surface_attr); + status = _cairo_surface_get_extents (pattern->surface, &extents); if (status) return status; - status = _cairo_surface_get_extents (surface, &extents); - if (status) - goto FAIL; - p2u = pattern->base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ @@ -1005,25 +1069,23 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output " surface, output); _cairo_output_stream_printf (output, "\"/>\n"); if (pattern_id != invalid_pattern_id) _cairo_output_stream_printf (output, "\n"); - FAIL: - _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, - surface, &surface_attr); - return status; } @@ -1159,6 +1221,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, static cairo_status_t _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, cairo_svg_surface_t *surface, + cairo_operator_t op, cairo_surface_pattern_t *pattern, int pattern_id, const cairo_matrix_t *parent_matrix, @@ -1197,8 +1260,10 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, "surface)) { - return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern, + return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern, pattern_id, parent_matrix, extra_attributes); } - return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern, + return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern, pattern_id, parent_matrix, extra_attributes); } -static void -_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - char const *op_str[] = { - "clear", - - "src", "src-over", "src-in", - "src-out", "src-atop", - - "dst", "dst-over", "dst-in", - "dst-out", "dst-atop", - - "xor", "plus", - "color-dodge" /* FIXME: saturate ? */ - }; - - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) - _cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]); -} - static cairo_status_t _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, cairo_solid_pattern_t *pattern, @@ -1258,8 +1302,8 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, cairo_bool_t is_stroke) { _cairo_output_stream_printf (style, is_stroke ? - "stroke: rgb(%f%%,%f%%,%f%%); stroke-opacity: %f;": - "fill: rgb(%f%%,%f%%,%f%%); fill-opacity: %f;", + "stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;": + "fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;", pattern->color.red * 100.0, pattern->color.green * 100.0, pattern->color.blue * 100.0, @@ -1281,13 +1325,13 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, pattern_id = document->pattern_id++; status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, - surface, pattern, + surface, CAIRO_OPERATOR_SOURCE, pattern, pattern_id, parent_matrix, NULL); if (status) return status; _cairo_output_stream_printf (style, - "%s: url(#pattern%d);", + "%s:url(#pattern%d);", is_stroke ? "stroke" : "fill", pattern_id); @@ -1312,8 +1356,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, if (pattern->n_stops == 1) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", pattern->stops[0].offset, pattern->stops[0].color.red * 100.0, pattern->stops[0].color.green * 100.0, @@ -1359,8 +1403,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, offset = start_offset + (1 - start_offset ) * stops[i].offset; _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1411,8 +1455,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset_color_start.red * 100.0, offset_color_start.green * 100.0, offset_color_start.blue * 100.0, @@ -1420,8 +1464,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, for (i = offset_index; i < n_stops; i++) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", stops[i].offset + start_offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1431,8 +1475,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, for (i = 0; i < offset_index; i++) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", 1.0 + stops[i].offset + start_offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1442,8 +1486,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset_color_stop.red * 100.0, offset_color_stop.green * 100.0, offset_color_stop.blue * 100.0, @@ -1517,7 +1561,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, "\n"); _cairo_output_stream_printf (style, - "%s: url(#linear%d);", + "%s:url(#linear%d);", is_stroke ? "stroke" : "fill", document->linear_pattern_id); @@ -1588,13 +1632,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (extend == CAIRO_EXTEND_NONE || n_stops < 1) _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); else { _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity %f;\"/>\n", pattern->base.stops[0].color.red * 100.0, pattern->base.stops[0].color.green * 100.0, pattern->base.stops[0].color.blue * 100.0, @@ -1602,8 +1646,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (n_stops > 1) _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", pattern->base.stops[n_stops - 1].color.red * 100.0, pattern->base.stops[n_stops - 1].color.green * 100.0, pattern->base.stops[n_stops - 1].color.blue * 100.0, @@ -1675,13 +1719,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (extend == CAIRO_EXTEND_NONE) { _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); if (r0 != 0.0) _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n", r0 / r1); } status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, @@ -1694,15 +1738,15 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (pattern->base.base.extend == CAIRO_EXTEND_NONE) _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); } _cairo_output_stream_printf (document->xml_node_defs, "\n"); _cairo_output_stream_printf (style, - "%s: url(#radial%d);", + "%s:url(#radial%d);", is_stroke ? "stroke" : "fill", document->radial_pattern_id); @@ -1747,10 +1791,10 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output, cairo_matrix_t *parent_matrix) { _cairo_output_stream_printf (output, - "fill-rule: %s; ", + "fill-rule:%s;", fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix); } @@ -1795,9 +1839,9 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, } _cairo_output_stream_printf (output, - "stroke-width: %f; " - "stroke-linecap: %s; " - "stroke-linejoin: %s; ", + "stroke-width:%f;" + "stroke-linecap:%s;" + "stroke-linejoin:%s;", stroke_style->line_width, line_cap, line_join); @@ -1806,27 +1850,27 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, if (status) return status; - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); if (stroke_style->num_dashes > 0) { - _cairo_output_stream_printf (output, "stroke-dasharray: "); + _cairo_output_stream_printf (output, "stroke-dasharray:"); for (i = 0; i < stroke_style->num_dashes; i++) { _cairo_output_stream_printf (output, "%f", stroke_style->dash[i]); if (i + 1 < stroke_style->num_dashes) _cairo_output_stream_printf (output, ","); else - _cairo_output_stream_printf (output, "; "); + _cairo_output_stream_printf (output, ";"); } if (stroke_style->dash_offset != 0.0) { _cairo_output_stream_printf (output, - "stroke-dashoffset: %f; ", + "stroke-dashoffset:%f;", stroke_style->dash_offset); } } _cairo_output_stream_printf (output, - "stroke-miterlimit: %f; ", + "stroke-miterlimit:%f;", stroke_style->miter_limit); return CAIRO_STATUS_SUCCESS; @@ -1931,6 +1975,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output, cairo_svg_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, + cairo_pattern_t *mask_source, const char *extra_attributes) { cairo_status_t status; @@ -1938,23 +1983,24 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output, if (source->type == CAIRO_PATTERN_TYPE_SURFACE && source->extend == CAIRO_EXTEND_NONE) return _cairo_svg_surface_emit_composite_pattern (output, - surface, - (cairo_surface_pattern_t *) source, - invalid_pattern_id, - NULL, - extra_attributes); + surface, + op, + (cairo_surface_pattern_t *) source, + invalid_pattern_id, + mask_source ? &mask_source->matrix :NULL, + extra_attributes); _cairo_output_stream_printf (output, "width, surface->height); - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL); if (status) return status; - _cairo_output_stream_printf (output, " stroke: none;\""); + _cairo_output_stream_printf (output, "stroke:none;\""); if (extra_attributes) _cairo_output_stream_printf (output, " %s", extra_attributes); @@ -1975,15 +2021,7 @@ _cairo_svg_surface_paint (void *abstract_surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _cairo_svg_surface_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 - * 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 (_cairo_svg_surface_operation_supported (surface, op, source)); - */ /* Emulation of clear and source operators, when no clipping region * is defined. We just delete existing content of surface root node, @@ -1992,11 +2030,8 @@ _cairo_svg_surface_paint (void *abstract_surface, * above always return FALSE. In order to make it work, we need a way * to know if there's an active clipping path. * Optimization of CLEAR works because of a test in paginated surface, - * and an optimiszation in meta surface. */ - if (surface->clip_level == 0 && - (op == CAIRO_OPERATOR_CLEAR || - op == CAIRO_OPERATOR_SOURCE)) - { + * and an optimization in meta surface. */ + if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) { status = _cairo_output_stream_destroy (surface->xml_node); if (status) { surface->xml_node = NULL; @@ -2015,16 +2050,17 @@ _cairo_svg_surface_paint (void *abstract_surface, _cairo_output_stream_printf (surface->xml_node, "\n", + "style=\"opacity:1;" + "stroke:none;" + "fill:rgb(0,0,0);\"/>\n", surface->width, surface->height); } return CAIRO_STATUS_SUCCESS; } } - return _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL); + return _cairo_svg_surface_emit_paint (surface->xml_node, + surface, op, source, 0, NULL); } static cairo_int_status_t @@ -2041,10 +2077,23 @@ _cairo_svg_surface_mask (void *abstract_surface, cairo_bool_t discard_filter = FALSE; unsigned int mask_id; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + cairo_status_t source_status, mask_status; + + source_status = _cairo_svg_surface_analyze_operation (surface, op, source); + if (_cairo_status_is_error (source_status)) + return source_status; + + mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask); + if (_cairo_status_is_error (mask_status)) + return mask_status; + + return _cairo_analysis_surface_merge_status (source_status, + mask_status); + } assert (_cairo_svg_surface_operation_supported (surface, op, source)); + assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask)); if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask; @@ -2070,7 +2119,7 @@ _cairo_svg_surface_mask (void *abstract_surface, "%s", mask_id, discard_filter ? "" : " \n"); - status = _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL); + status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL); if (status) { cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream); return status; @@ -2089,7 +2138,7 @@ _cairo_svg_surface_mask (void *abstract_surface, snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"", mask_id); - status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer); + status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, buffer); if (status) return status; @@ -2115,7 +2164,7 @@ _cairo_svg_surface_stroke (void *abstract_dst, assert (_cairo_svg_surface_operation_supported (surface, op, source)); - _cairo_output_stream_printf (surface->xml_node, "xml_node, "xml_node, surface, op, source, stroke_style, ctm_inverse); if (status) @@ -2169,6 +2218,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, if (status) return status; + _cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op); + _cairo_output_stream_printf (surface->xml_node, "\">\n"); for (i = 0; i < num_glyphs; i++) { @@ -2418,6 +2469,28 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) if (document->finished) return CAIRO_STATUS_SUCCESS; + /* + * Should we add DOCTYPE? + * + * Google says no. + * + * http://tech.groups.yahoo.com/group/svg-developers/message/48562: + * There's a bunch of issues, but just to pick a few: + * - they'll give false positives. + * - they'll give false negatives. + * - they're namespace-unaware. + * - they don't wildcard. + * So when they say OK they really haven't checked anything, when + * they say NOT OK they might be on crack, and like all + * namespace-unaware things they're a dead branch of the XML tree. + * + * http://jwatt.org/svg/authoring/: + * Unfortunately the SVG DTDs are a source of so many issues that the + * SVG WG has decided not to write one for the upcoming SVG 1.2 + * standard. In fact SVG WG members are even telling people not to use + * a DOCTYPE declaration in SVG 1.0 and 1.1 documents. + */ + _cairo_output_stream_printf (output, "\n" "paginated_mode = paginated_mode; } +static cairo_bool_t +_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface) +{ + cairo_svg_surface_t *surface = abstract_surface; + cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + + if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) { + status = _cairo_svg_surface_analyze_operator (surface, + CAIRO_OPERATOR_SOURCE); + } + + return status == CAIRO_STATUS_SUCCESS; +} + static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = { NULL /*_cairo_svg_surface_start_page*/, - _cairo_svg_surface_set_paginated_mode + _cairo_svg_surface_set_paginated_mode, + NULL, /* _cairo_svg_surface_set_bounding_box */ + NULL, /* _cairo_svg_surface_set_fallback_images_required */ + _cairo_svg_surface_supports_fine_grained_fallbacks, + }; diff --git a/gfx/cairo/cairo/src/cairo-win32.c b/gfx/cairo/cairo/src/cairo-system.c similarity index 58% rename from gfx/cairo/cairo/src/cairo-win32.c rename to gfx/cairo/cairo/src/cairo-system.c index a656ff8e6a6e..85c74876eb2a 100644 --- a/gfx/cairo/cairo/src/cairo-win32.c +++ b/gfx/cairo/cairo/src/cairo-system.c @@ -1,7 +1,7 @@ /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* Cairo - a vector graphics library with display and print output * - * Copyright © 2007 Adrian Johnson + * 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 @@ -28,12 +28,30 @@ * * The Original Code is the cairo graphics library. * - * The Initial Developer of the Original Code is Adrian Johnson. + * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): - * Adrian Johnson + * Owen Taylor + * Stuart Parmenter + * Vladimir Vukicevic */ +/* This file should include code that is system-specific, not + * feature-specific. For example, the DLL initialization/finalization + * code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c). + * Same about possible ELF-specific code. + * + * And no other function should live here. + */ + + +#include "cairoint.h" + + + +#if CAIRO_MUTEX_IMPL_WIN32 +#if !CAIRO_WIN32_STATIC_BUILD + #define WIN32_LEAN_AND_MEAN /* We require Windows 2000 features such as ETO_PDY */ #if !defined(WINVER) || (WINVER < 0x0500) @@ -43,56 +61,37 @@ # define _WIN32_WINNT 0x0500 #endif -#include "cairoint.h" +#include "cairo-clip-private.h" +#include "cairo-paginated-private.h" +#include "cairo-win32-private.h" +#include "cairo-scaled-font-subsets-private.h" #include -#include -/* tmpfile() replacment for Windows. - * - * On Windows tmpfile() creates the file in the root directory. This - * may fail due to unsufficient privileges. - */ -FILE * -_cairo_win32_tmpfile (void) +/* declare to avoid "no previous prototype for 'DllMain'" warning */ +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved); + +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) { - DWORD path_len; - WCHAR path_name[MAX_PATH + 1]; - WCHAR file_name[MAX_PATH + 1]; - HANDLE handle; - int fd; - FILE *fp; + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + CAIRO_MUTEX_INITIALIZE (); + break; - path_len = GetTempPathW (MAX_PATH, path_name); - if (path_len <= 0 || path_len >= MAX_PATH) - return NULL; - - if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) - return NULL; - - handle = CreateFileW (file_name, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - DeleteFileW (file_name); - return NULL; + case DLL_PROCESS_DETACH: + CAIRO_MUTEX_FINALIZE (); + break; } - fd = _open_osfhandle((intptr_t) handle, 0); - if (fd < 0) { - CloseHandle (handle); - return NULL; - } - - fp = fdopen(fd, "w+b"); - if (fp == NULL) { - _close(fd); - return NULL; - } - - return fp; + return TRUE; } + +#endif +#endif + diff --git a/gfx/cairo/cairo/src/cairo-traps.c b/gfx/cairo/cairo/src/cairo-traps.c index fcb0208859a6..b76e9089cd05 100644 --- a/gfx/cairo/cairo/src/cairo-traps.c +++ b/gfx/cairo/cairo/src/cairo-traps.c @@ -41,13 +41,6 @@ /* private functions */ -static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps); - -static void -_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_line_t *left, cairo_line_t *right); - static int _compare_point_fixed_by_y (const void *av, const void *bv); @@ -83,15 +76,21 @@ _cairo_traps_get_limit (cairo_traps_t *traps, return traps->has_limits; } +void +_cairo_traps_clear (cairo_traps_t *traps) +{ + traps->status = CAIRO_STATUS_SUCCESS; + + traps->num_traps = 0; + traps->extents.p1.x = traps->extents.p1.y = INT32_MAX; + traps->extents.p2.x = traps->extents.p2.y = INT32_MIN; +} + void _cairo_traps_fini (cairo_traps_t *traps) { - if (traps->traps && traps->traps != traps->traps_embedded) + if (traps->traps != traps->traps_embedded) free (traps->traps); - - traps->traps = NULL; - traps->traps_size = 0; - traps->num_traps = 0; } /** @@ -103,9 +102,9 @@ _cairo_traps_fini (cairo_traps_t *traps) * Initializes a #cairo_traps_t to contain a single rectangular * trapezoid. **/ -cairo_status_t +void _cairo_traps_init_box (cairo_traps_t *traps, - cairo_box_t *box) + const cairo_box_t *box) { _cairo_traps_init (traps); @@ -123,25 +122,41 @@ _cairo_traps_init_box (cairo_traps_t *traps, traps->traps[0].right.p2 = box->p2; traps->extents = *box; - - return traps->status; } -cairo_status_t -_cairo_traps_status (cairo_traps_t *traps) +/* make room for at least one more trap */ +static cairo_bool_t +_cairo_traps_grow (cairo_traps_t *traps) { - return traps->status; + cairo_trapezoid_t *new_traps; + int new_size = 2 * MAX (traps->traps_size, 16); + + if (traps->traps == traps->traps_embedded) { + new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); + if (new_traps != NULL) + memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); + } else { + new_traps = _cairo_realloc_ab (traps->traps, + new_size, sizeof (cairo_trapezoid_t)); + } + + if (new_traps == NULL) { + traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return FALSE; + } + + traps->traps = new_traps; + traps->traps_size = new_size; + return TRUE; } -static void -_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, +void +_cairo_traps_add_trap (cairo_traps_t *traps, + cairo_fixed_t top, cairo_fixed_t bottom, cairo_line_t *left, cairo_line_t *right) { cairo_trapezoid_t *trap; - if (traps->status) - return; - /* Note: With the goofy trapezoid specification, (where an * arbitrary two points on the lines can specified for the left * and right edges), these limit checks would not work in @@ -170,6 +185,10 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo return; } + /* And reject if the trapezoid is entirely above or below */ + if (top > traps->limits.p2.y || bottom < traps->limits.p1.y) + return; + /* Otherwise, clip the trapezoid to the limits. We only clip * where an edge is entirely outside the limits. If we wanted * to be more clever, we could handle cases where a trapezoid @@ -182,28 +201,34 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo if (bottom > traps->limits.p2.y) bottom = traps->limits.p2.y; - if (left->p1.x < traps->limits.p1.x && - left->p2.x < traps->limits.p1.x) + if (left->p1.x <= traps->limits.p1.x && + left->p2.x <= traps->limits.p1.x) { left->p1.x = traps->limits.p1.x; left->p2.x = traps->limits.p1.x; } - if (right->p1.x > traps->limits.p2.x && - right->p2.x > traps->limits.p2.x) + if (right->p1.x >= traps->limits.p2.x && + right->p2.x >= traps->limits.p2.x) { right->p1.x = traps->limits.p2.x; right->p2.x = traps->limits.p2.x; } } - if (top >= bottom) { + /* Trivial discards for empty trapezoids that are likely to be produced + * by our tessellators (most notably convex_quad when given a simple + * rectangle). + */ + if (top >= bottom) + return; + /* cheap colinearity check */ + if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y && + right->p2.x <= left->p2.x && right->p2.y == left->p2.y) return; - } - if (traps->num_traps >= traps->traps_size) { - traps->status = _cairo_traps_grow (traps); - if (traps->status) + if (traps->num_traps == traps->traps_size) { + if (! _cairo_traps_grow (traps)) return; } @@ -238,51 +263,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo traps->num_traps++; } -void -_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_point_t left_p1, cairo_point_t left_p2, - cairo_point_t right_p1, cairo_point_t right_p2) -{ - cairo_line_t left; - cairo_line_t right; - - if (traps->status) - return; - - left.p1 = left_p1; - left.p2 = left_p2; - - right.p1 = right_p1; - right.p2 = right_p2; - - _cairo_traps_add_trap (traps, top, bottom, &left, &right); -} - -/* make room for at least one more trap */ -static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps) -{ - cairo_trapezoid_t *new_traps; - int new_size = 2 * MAX (traps->traps_size, 16); - - if (traps->traps == traps->traps_embedded) { - new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); - if (new_traps) - memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); - } else { - new_traps = _cairo_realloc_ab (traps->traps, - new_size, sizeof (cairo_trapezoid_t)); - } - - if (new_traps == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - traps->traps = new_traps; - traps->traps_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - static int _compare_point_fixed_by_y (const void *av, const void *bv) { @@ -371,7 +351,8 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, * quadrilateral. We would not benefit from having any distinct * implementation of triangle vs. quadrilateral tessellation here. */ cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) +_cairo_traps_tessellate_triangle (cairo_traps_t *traps, + const cairo_point_t t[3]) { cairo_point_t quad[4]; @@ -384,12 +365,33 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) } cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) +_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, + const cairo_point_t *top_left, + const cairo_point_t *bottom_right) +{ + cairo_line_t left; + cairo_line_t right; + + left.p1.x = left.p2.x = top_left->x; + left.p1.y = right.p1.y = top_left->y; + right.p1.x = right.p2.x = bottom_right->x; + left.p2.y = right.p2.y = bottom_right->y; + + _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right); + + return traps->status; +} + +cairo_status_t +_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, + const cairo_point_t q[4]) { int a, b, c, d; int i; cairo_slope_t ab, ad; cairo_bool_t b_left_of_d; + cairo_line_t left; + cairo_line_t right; /* Choose a as a point with minimal y */ a = 0; @@ -454,15 +456,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * | / \| \ \ c.y d.y cd ad * d d d */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[b], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[c].y, - q[b], q[c], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[c].y, q[d].y, - q[c], q[d], q[a], q[d]); + left.p1 = q[a]; left.p2 = q[b]; + right.p1 = q[a]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + left.p1 = q[b]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); + left.p1 = q[c]; left.p2 = q[d]; + _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); } else { /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) * @@ -474,15 +474,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * / / |/ \ | c.y d.y ad cd * d d d */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[d], q[a], q[b]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[c].y, - q[a], q[d], q[b], q[c]); - _cairo_traps_add_trap_from_points (traps, - q[c].y, q[d].y, - q[a], q[d], q[c], q[d]); + left.p1 = q[a]; left.p2 = q[d]; + right.p1 = q[a]; right.p2 = q[b]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + right.p1 = q[b]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); + right.p1 = q[c]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); } } else { if (b_left_of_d) { @@ -496,15 +494,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * // \ / \| d.y c.y bc dc * c c c */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[b], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[d].y, - q[b], q[c], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[d].y, q[c].y, - q[b], q[c], q[d], q[c]); + left.p1 = q[a]; left.p2 = q[b]; + right.p1 = q[a]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + left.p1 = q[b]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); + right.p1 = q[d]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); } else { /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) * @@ -516,15 +512,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * |/ \ / \\ d.y c.y dc bc * c c c */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[d], q[a], q[b]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[d].y, - q[a], q[d], q[b], q[c]); - _cairo_traps_add_trap_from_points (traps, - q[d].y, q[c].y, - q[d], q[c], q[b], q[c]); + left.p1 = q[a]; left.p2 = q[d]; + right.p1 = q[a]; right.p2 = q[b]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + right.p1 = q[b]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); + left.p1 = q[d]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); } } @@ -581,8 +575,21 @@ _cairo_traps_extents (const cairo_traps_t *traps, if (traps->num_traps == 0) { extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0); extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0); - } else + } else { *extents = traps->extents; + if (traps->has_limits) { + /* clip the traps to the imposed limits */ + if (extents->p1.x < traps->limits.p1.x) + extents->p1.x = traps->limits.p1.x; + if (extents->p2.x > traps->limits.p2.x) + extents->p2.x = traps->limits.p2.x; + + if (extents->p1.y < traps->limits.p1.y) + extents->p1.y = traps->limits.p1.y; + if (extents->p2.y > traps->limits.p2.y) + extents->p2.y = traps->limits.p2.y; + } + } } /** diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c index d432c4c86724..e8be4b44429e 100644 --- a/gfx/cairo/cairo/src/cairo-truetype-subset.c +++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c @@ -1220,6 +1220,12 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, goto fail; num_segments = be16_to_cpu (map->segCountX2)/2; + + /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of + * uint16_t each num_segments long. */ + if (size < (8 + 4*num_segments)*sizeof(uint16_t)) + return CAIRO_INT_STATUS_UNSUPPORTED; + end_code = map->endCount; start_code = &(end_code[num_segments + 1]); delta = &(start_code[num_segments]); @@ -1246,13 +1252,17 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, uint16_t g_id_be = cpu_to_be16 (index); int j; - if (range_size > 0) + if (range_size > 0) { + if ((char*)glyph_ids + 2*range_size > (char*)map + size) + return CAIRO_INT_STATUS_UNSUPPORTED; + for (j = 0; j < range_size; j++) { if (glyph_ids[j] == g_id_be) { *ucs4 = be16_to_cpu (start_code[i]) + j; goto found; } } + } } } diff --git a/gfx/cairo/cairo/src/cairo-type1-fallback.c b/gfx/cairo/cairo/src/cairo-type1-fallback.c index 75503103a4f8..83ddc448a460 100644 --- a/gfx/cairo/cairo/src/cairo-type1-fallback.c +++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c @@ -444,18 +444,21 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font, "2 index /CharStrings %d dict dup begin\n", font->scaled_font_subset->num_glyphs + 1); + _cairo_scaled_font_freeze_cache (font->type1_scaled_font); for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { _cairo_array_truncate (&data, 0); /* four "random" bytes required by encryption algorithm */ status = _cairo_array_append_multiple (&data, zeros, 4); if (status) goto fail; + status = cairo_type1_font_create_charstring (font, i, font->scaled_font_subset->glyphs[i], CAIRO_CHARSTRING_TYPE1, &data); if (status) goto fail; + charstring_encrypt (&data); length = _cairo_array_num_elements (&data); if (font->scaled_font_subset->glyph_names != NULL) { @@ -474,6 +477,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font, } fail: + _cairo_scaled_font_thaw_cache (font->type1_scaled_font); _cairo_array_fini (&data); return status; } @@ -823,6 +827,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, goto fail1; } + _cairo_scaled_font_freeze_cache (font->type1_scaled_font); for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { _cairo_array_init (&charstring, sizeof (unsigned char)); status = _cairo_array_grow_by (&charstring, 32); @@ -840,6 +845,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, if (status) goto fail2; } + _cairo_scaled_font_thaw_cache (font->type1_scaled_font); for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) type2_subset->widths[i] = font->widths[i]; @@ -854,6 +860,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, return cairo_type1_font_destroy (font); fail2: + _cairo_scaled_font_thaw_cache (font->type1_scaled_font); _cairo_array_fini (&charstring); _cairo_type2_charstrings_fini (type2_subset); fail1: diff --git a/gfx/cairo/cairo/src/cairo-type1-subset.c b/gfx/cairo/cairo/src/cairo-type1-subset.c index 8e1d3292a23d..ddc4ce7652b8 100644 --- a/gfx/cairo/cairo/src/cairo-type1-subset.c +++ b/gfx/cairo/cairo/src/cairo-type1-subset.c @@ -61,7 +61,6 @@ #include typedef struct _cairo_type1_font_subset { - cairo_scaled_font_subset_t *scaled_font_subset; struct { @@ -76,7 +75,6 @@ typedef struct _cairo_type1_font_subset { unsigned long header_size; unsigned long data_size; unsigned long trailer_size; - } base; FT_Face face; @@ -115,15 +113,14 @@ typedef struct _cairo_type1_font_subset { static cairo_status_t -_cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, - cairo_type1_font_subset_t **subset_return, - cairo_bool_t hex_encode) +_cairo_type1_font_subset_init (cairo_type1_font_subset_t *font, + cairo_unscaled_font_t *unscaled_font, + cairo_bool_t hex_encode) { cairo_ft_unscaled_font_t *ft_unscaled_font; cairo_status_t status; FT_Face face; PS_FontInfoRec font_info; - cairo_type1_font_subset_t *font; int i, j; ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; @@ -145,12 +142,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, } #endif - font = calloc (sizeof (cairo_type1_font_subset_t), 1); - if (font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - + memset (font, 0, sizeof (font)); font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); font->base.num_glyphs = face->num_glyphs; font->base.x_min = face->bbox.xMin; @@ -189,8 +181,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - *subset_return = font; - return CAIRO_STATUS_SUCCESS; fail3: @@ -198,7 +188,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, free (font->base.base_font); fail2: _cairo_unscaled_font_destroy (unscaled_font); - free (font); fail1: _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); @@ -1225,10 +1214,15 @@ cairo_type1_font_subset_generate (void *abstract_font, goto fail; } - if (font->face->stream->read) { - ret = font->face->stream->read (font->face->stream, 0, - (unsigned char *) font->type1_data, - font->type1_length); + if (font->face->stream->read != NULL) { + /* Note that read() may be implemented as a macro, thanks POSIX!, so we + * need to wrap the following usage in parentheses in order to + * disambiguate it for the pre-processor - using the verbose function + * pointer dereference for clarity. + */ + ret = (* font->face->stream->read) (font->face->stream, 0, + (unsigned char *) font->type1_data, + font->type1_length); if (ret != font->type1_length) { status = _cairo_error (CAIRO_STATUS_READ_ERROR); goto fail; @@ -1261,9 +1255,8 @@ cairo_type1_font_subset_generate (void *abstract_font, } static void -cairo_type1_font_subset_destroy (void *abstract_font) +_cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font) { - cairo_type1_font_subset_t *font = abstract_font; unsigned int i; /* If the subset generation failed, some of the pointers below may @@ -1282,17 +1275,15 @@ cairo_type1_font_subset_destroy (void *abstract_font) if (font->base.base_font) free (font->base.base_font); free (font->glyphs); - free (font); } - cairo_status_t _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, const char *name, cairo_scaled_font_subset_t *scaled_font_subset, cairo_bool_t hex_encode) { - cairo_type1_font_subset_t *font = NULL; /* hide compiler warning */ + cairo_type1_font_subset_t font; cairo_status_t status; unsigned long parent_glyph, length; unsigned int i; @@ -1308,21 +1299,21 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); - status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode); + status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode); if (status) return status; for (i = 0; i < scaled_font_subset->num_glyphs; i++) { parent_glyph = scaled_font_subset->glyphs[i]; - cairo_type1_font_subset_use_glyph (font, parent_glyph); + cairo_type1_font_subset_use_glyph (&font, parent_glyph); } - status = cairo_type1_font_subset_generate (font, name); + status = cairo_type1_font_subset_generate (&font, name); if (status) goto fail1; - if (font->base.base_font) { - type1_subset->base_font = strdup (font->base.base_font); + if (font.base.base_font) { + type1_subset->base_font = strdup (font.base.base_font); } else { snprintf(buf, sizeof (buf), "CairoFont-%u-%u", scaled_font_subset->font_id, scaled_font_subset->subset_id); @@ -1331,37 +1322,38 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, if (type1_subset->base_font == NULL) goto fail1; - type1_subset->widths = calloc (sizeof (int), font->num_glyphs); + type1_subset->widths = calloc (sizeof (int), font.num_glyphs); if (type1_subset->widths == NULL) goto fail2; - for (i = 0; i < font->base.num_glyphs; i++) { - if (font->glyphs[i].subset_index < 0) + for (i = 0; i < font.base.num_glyphs; i++) { + if (font.glyphs[i].subset_index < 0) continue; - type1_subset->widths[font->glyphs[i].subset_index] = - font->glyphs[i].width; + type1_subset->widths[font.glyphs[i].subset_index] = + font.glyphs[i].width; } - type1_subset->x_min = font->base.x_min; - type1_subset->y_min = font->base.y_min; - type1_subset->x_max = font->base.x_max; - type1_subset->y_max = font->base.y_max; - type1_subset->ascent = font->base.ascent; - type1_subset->descent = font->base.descent; + type1_subset->x_min = font.base.x_min; + type1_subset->y_min = font.base.y_min; + type1_subset->x_max = font.base.x_max; + type1_subset->y_max = font.base.y_max; + type1_subset->ascent = font.base.ascent; + type1_subset->descent = font.base.descent; - length = font->base.header_size + font->base.data_size + - font->base.trailer_size; + length = font.base.header_size + + font.base.data_size + + font.base.trailer_size; type1_subset->data = malloc (length); if (type1_subset->data == NULL) goto fail3; memcpy (type1_subset->data, - _cairo_array_index (&font->contents, 0), length); + _cairo_array_index (&font.contents, 0), length); - type1_subset->header_length = font->base.header_size; - type1_subset->data_length = font->base.data_size; - type1_subset->trailer_length = font->base.trailer_size; + type1_subset->header_length = font.base.header_size; + type1_subset->data_length = font.base.data_size; + type1_subset->trailer_length = font.base.trailer_size; - cairo_type1_font_subset_destroy (font); + _cairo_type1_font_subset_fini (&font); return CAIRO_STATUS_SUCCESS; @@ -1370,7 +1362,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, fail2: free (type1_subset->base_font); fail1: - cairo_type1_font_subset_destroy (font); + _cairo_type1_font_subset_fini (&font); return status; } diff --git a/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h b/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h index 47aba01c894c..33314ae9e690 100644 --- a/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h @@ -60,13 +60,17 @@ typedef struct cairo_type3_glyph_surface { cairo_private cairo_surface_t * _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, cairo_output_stream_t *stream, - cairo_type3_glyph_surface_emit_image_t emit_image); + cairo_type3_glyph_surface_emit_image_t emit_image, + cairo_scaled_font_subsets_t *font_subsets); + +cairo_private void +_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface, + cairo_pdf_operators_use_font_subset_t use_font_subset, + void *closure); cairo_private cairo_status_t -_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface, - cairo_output_stream_t *stream, - cairo_box_t *bbox, - double *width); +_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, + unsigned long glyph_index); cairo_private cairo_status_t _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, diff --git a/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c b/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c index 4c3afb40a2e8..c84f5f05e5d0 100644 --- a/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c +++ b/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c @@ -41,13 +41,15 @@ #include "cairo-type3-glyph-surface-private.h" #include "cairo-output-stream-private.h" #include "cairo-meta-surface-private.h" +#include "cairo-analysis-surface-private.h" static const cairo_surface_backend_t cairo_type3_glyph_surface_backend; cairo_surface_t * _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, cairo_output_stream_t *stream, - cairo_type3_glyph_surface_emit_image_t emit_image) + cairo_type3_glyph_surface_emit_image_t emit_image, + cairo_scaled_font_subsets_t *font_subsets) { cairo_type3_glyph_surface_t *surface; cairo_matrix_t invert_y_axis; @@ -74,7 +76,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, _cairo_pdf_operators_init (&surface->pdf_operators, surface->stream, &surface->cairo_to_pdf, - NULL); + font_subsets); return &surface->base; } @@ -263,10 +265,37 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font, int *remaining_glyphs) { - /* XXX: Some refactoring is required before we can add font - * subsets in the middle of emitting all the subsets. */ + cairo_type3_glyph_surface_t *surface = abstract_surface; + cairo_int_status_t status; + cairo_scaled_font_t *font; + cairo_matrix_t new_ctm, ctm_inverse; + int i; - return CAIRO_INT_STATUS_IMAGE_FALLBACK; + for (i = 0; i < num_glyphs; i++) + cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y); + + /* We require the matrix to be invertable. */ + ctm_inverse = scaled_font->ctm; + status = cairo_matrix_invert (&ctm_inverse); + if (status) + return CAIRO_INT_STATUS_IMAGE_FALLBACK; + + cairo_matrix_multiply (&new_ctm, &scaled_font->ctm, &ctm_inverse); + font = cairo_scaled_font_create (scaled_font->font_face, + &scaled_font->font_matrix, + &new_ctm, + &scaled_font->options); + + status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, + NULL, 0, + glyphs, num_glyphs, + NULL, 0, + FALSE, + font); + + cairo_scaled_font_destroy (font); + + return status; } static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = { @@ -316,7 +345,7 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur cairo_status_t status; cairo_image_surface_t *image; cairo_matrix_t mat; - double width, height, x, y; + double x, y; status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, @@ -332,14 +361,10 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y); - width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); - height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y); - mat.xx = width; + mat.xx = image->width; mat.xy = 0; mat.yx = 0; - mat.yy = height; + mat.yy = image->height; mat.x0 = x; mat.y0 = y; cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse); @@ -348,20 +373,65 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur return _cairo_type3_glyph_surface_emit_image (surface, image, &mat); } -cairo_status_t -_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface, - cairo_output_stream_t *stream, - cairo_box_t *bbox, - double *width) +void +_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface, + cairo_pdf_operators_use_font_subset_t use_font_subset, + void *closure) { - bbox->p1.x = 0; - bbox->p1.y = 0; - bbox->p2.x = 0; - bbox->p2.y = 0; - *width = 0.0; - _cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n"); + cairo_type3_glyph_surface_t *surface = abstract_surface; - return CAIRO_STATUS_SUCCESS; + _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators, + use_font_subset, + closure); +} + +cairo_status_t +_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, + unsigned long glyph_index) +{ + cairo_type3_glyph_surface_t *surface = abstract_surface; + cairo_scaled_glyph_t *scaled_glyph; + cairo_status_t status, status2; + cairo_output_stream_t *null_stream; + + null_stream = _cairo_null_stream_create (); + _cairo_type3_glyph_surface_set_stream (surface, null_stream); + + _cairo_scaled_font_freeze_cache (surface->scaled_font); + status = _cairo_scaled_glyph_lookup (surface->scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS | + CAIRO_SCALED_GLYPH_INFO_META_SURFACE, + &scaled_glyph); + + if (_cairo_status_is_error (status)) + goto cleanup; + + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + status = CAIRO_STATUS_SUCCESS; + goto cleanup; + } + + status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, + &surface->base); + if (status) + goto cleanup; + + status2 = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + + if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) + status = CAIRO_STATUS_SUCCESS; + +cleanup: + _cairo_scaled_font_thaw_cache (surface->scaled_font); + + status2 = _cairo_output_stream_destroy (null_stream); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + + return status; } cairo_status_t @@ -379,23 +449,24 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, cairo_matrix_t font_matrix_inverse; _cairo_type3_glyph_surface_set_stream (surface, stream); + + _cairo_scaled_font_freeze_cache (surface->scaled_font); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_META_SURFACE, &scaled_glyph); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); - if (status) - return status; - - status = CAIRO_INT_STATUS_IMAGE_FALLBACK; + if (status == CAIRO_STATUS_SUCCESS) + status = CAIRO_INT_STATUS_IMAGE_FALLBACK; + } + if (_cairo_status_is_error (status)) { + _cairo_scaled_font_thaw_cache (surface->scaled_font); + return status; } x_advance = scaled_glyph->metrics.x_advance; @@ -429,7 +500,12 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, _cairo_output_stream_printf (surface->stream, "q\n"); status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, - &surface->base); + &surface->base); + + status2 = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + _cairo_output_stream_printf (surface->stream, "Q\n"); _cairo_type3_glyph_surface_set_stream (surface, stream); @@ -437,13 +513,15 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, _cairo_memory_stream_copy (mem_stream, stream); status2 = _cairo_output_stream_destroy (mem_stream); - if (status2) - return status2; + if (status == CAIRO_STATUS_SUCCESS) + status = status2; } if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index); + _cairo_scaled_font_thaw_cache (surface->scaled_font); + return status; } diff --git a/gfx/cairo/cairo/src/cairo-types-private.h b/gfx/cairo/cairo/src/cairo-types-private.h index 91bfa8a5d4de..12e1a20e5c1d 100644 --- a/gfx/cairo/cairo/src/cairo-types-private.h +++ b/gfx/cairo/cairo/src/cairo-types-private.h @@ -39,8 +39,6 @@ #ifndef CAIRO_TYPES_PRIVATE_H #define CAIRO_TYPES_PRIVATE_H -/* This is the only header file not including cairoint.h. It only contains - * typedefs.*/ #include "cairo.h" #include "cairo-fixed-type-private.h" @@ -118,7 +116,6 @@ struct _cairo_array { struct _cairo_font_options { cairo_antialias_t antialias; cairo_subpixel_order_t subpixel_order; - cairo_lcd_filter_t lcd_filter; cairo_hint_style_t hint_style; cairo_hint_metrics_t hint_metrics; }; @@ -134,6 +131,24 @@ struct _cairo_cache { int freeze_count; }; +/* XXX: Right now, the _cairo_color structure puts unpremultiplied + color in the doubles and premultiplied color in the shorts. Yes, + this is crazy insane, (but at least we don't export this + madness). I'm still working on a cleaner API, but in the meantime, + at least this does prevent precision loss in color when changing + alpha. */ +struct _cairo_color { + double red; + double green; + double blue; + double alpha; + + unsigned short red_short; + unsigned short green_short; + unsigned short blue_short; + unsigned short alpha_short; +}; + typedef enum _cairo_paginated_mode { CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */ CAIRO_PAGINATED_MODE_RENDER, /* render page contents */ diff --git a/gfx/cairo/cairo/src/cairo-unicode.c b/gfx/cairo/cairo/src/cairo-unicode.c index 39d37b8e8e3e..b1567d42d6e0 100644 --- a/gfx/cairo/cairo/src/cairo-unicode.c +++ b/gfx/cairo/cairo/src/cairo-unicode.c @@ -230,7 +230,7 @@ _cairo_utf8_get_char_validated (const char *p, } /** - * _cairo_utf8_to_utf32: + * _cairo_utf8_to_ucs4: * @str: an UTF-8 string * @len: length of @str in bytes, or -1 if it is nul-terminated. * If @len is supplied and the string has an embedded nul @@ -247,7 +247,7 @@ _cairo_utf8_get_char_validated (const char *p, * * Return value: %CAIRO_STATUS_SUCCESS if the entire string was * successfully converted. %CAIRO_STATUS_INVALID_STRING if an - * an invalid sequence was found. + * invalid sequence was found. **/ cairo_status_t _cairo_utf8_to_ucs4 (const char *str, @@ -302,6 +302,8 @@ _cairo_utf8_to_ucs4 (const char *str, * @utf8: buffer to write utf8 string into. Must have at least 4 bytes * space available. Or %NULL. * + * This space left intentionally blank. + * * Return value: Number of bytes in the utf8 string or 0 if an invalid * unicode character **/ diff --git a/gfx/cairo/cairo/src/cairo-user-font.c b/gfx/cairo/cairo/src/cairo-user-font.c index f49943b68d15..ddcbc77c8b65 100644 --- a/gfx/cairo/cairo/src/cairo-user-font.c +++ b/gfx/cairo/cairo/src/cairo-user-font.c @@ -96,8 +96,6 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo return cr; } -static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend; - static cairo_int_status_t _cairo_user_scaled_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, @@ -153,9 +151,14 @@ _cairo_user_scaled_glyph_init (void *abstract_font, null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface)); analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1); cairo_surface_destroy (null_surface); + status = analysis_surface->status; + if (status) + return status; - _cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale); - status = _cairo_meta_surface_replay (meta_surface, analysis_surface); + _cairo_analysis_surface_set_ctm (analysis_surface, + &scaled_font->extent_scale); + status = _cairo_meta_surface_replay (meta_surface, + analysis_surface); _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox); cairo_surface_destroy (analysis_surface); @@ -271,16 +274,16 @@ _cairo_user_ucs4_to_index (void *abstract_font, } static cairo_int_status_t -_cairo_user_text_to_glyphs (void *abstract_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward) +_cairo_user_text_to_glyphs (void *abstract_font, + double x, + double y, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags) { cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -290,18 +293,22 @@ _cairo_user_text_to_glyphs (void *abstract_font, if (face->scaled_font_methods.text_to_glyphs) { int i; + cairo_glyph_t *orig_glyphs = *glyphs; int orig_num_glyphs = *num_glyphs; status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base, utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - backward); + clusters, num_clusters, cluster_flags); if (status != CAIRO_STATUS_SUCCESS) return status; if (*num_glyphs < 0) { + if (orig_glyphs != *glyphs) { + cairo_glyph_free (*glyphs); + *glyphs = orig_glyphs; + } *num_glyphs = orig_num_glyphs; return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -322,16 +329,79 @@ _cairo_user_text_to_glyphs (void *abstract_font, return status; } -static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend = { +static cairo_status_t +_cairo_user_font_face_scaled_font_create (void *abstract_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **scaled_font); + +static cairo_status_t +_cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face, + cairo_font_face_t **font_face_out) +{ + static cairo_user_data_key_t twin_font_face_key; + + cairo_font_face_t *face; + cairo_status_t status; + + face = cairo_font_face_get_user_data (&toy_face->base, + &twin_font_face_key); + if (!face) { + face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base), + cairo_toy_font_face_get_weight (&toy_face->base)); + + status = cairo_font_face_set_user_data (&toy_face->base, + &twin_font_face_key, + face, + (cairo_destroy_func_t) cairo_font_face_destroy); + + if (status) { + cairo_font_face_destroy (face); + return status; + } + } + + *font_face_out = face; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_user_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *font_options, + cairo_scaled_font_t **font) +{ + cairo_font_face_t *face; + cairo_status_t status; + + status = _cairo_user_scaled_font_get_implementation (toy_face, &face); + if (status) + return status; + + status = _cairo_user_font_face_scaled_font_create (face, + font_matrix, + ctm, + font_options, + font); + if (status) + return status; + + return CAIRO_STATUS_SUCCESS; +} + +const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = { CAIRO_FONT_TYPE_USER, - NULL, /* create_toy */ + _cairo_user_scaled_font_get_implementation, + _cairo_user_scaled_font_create_toy, /* create_toy */ NULL, /* scaled_font_fini */ _cairo_user_scaled_glyph_init, _cairo_user_text_to_glyphs, _cairo_user_ucs4_to_index, NULL, /* show_glyphs */ NULL, /* load_truetype_table */ - NULL, /* map_glyphs_to_unicode */ + NULL /* index_to_ucs4 */ }; /* #cairo_user_font_face_t */ @@ -352,12 +422,12 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t)); if (user_scaled_font == NULL) - return CAIRO_STATUS_NO_MEMORY; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _cairo_scaled_font_init (&user_scaled_font->base, &font_face->base, font_matrix, ctm, options, - &cairo_user_scaled_font_backend); + &_cairo_user_scaled_font_backend); if (status) { free (user_scaled_font); @@ -397,29 +467,31 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ } } - if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) { - - cairo_t *cr; - + if (status == CAIRO_STATUS_SUCCESS && + font_face->scaled_font_methods.init != NULL) + { /* Lock the scaled_font mutex such that user doesn't accidentally try * to use it just yet. */ CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex); /* Give away fontmap lock such that user-font can use other fonts */ - _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); + status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); + if (status == CAIRO_STATUS_SUCCESS) { + cairo_t *cr; - cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font); + cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font); - status = font_face->scaled_font_methods.init (&user_scaled_font->base, - cr, - &font_extents); + status = font_face->scaled_font_methods.init (&user_scaled_font->base, + cr, + &font_extents); - if (status == CAIRO_STATUS_SUCCESS) - status = cairo_status (cr); + if (status == CAIRO_STATUS_SUCCESS) + status = cairo_status (cr); - cairo_destroy (cr); + cairo_destroy (cr); - _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base); + _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base); + } CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex); } @@ -427,7 +499,6 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ if (status == CAIRO_STATUS_SUCCESS) status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents); - if (status != CAIRO_STATUS_SUCCESS) { _cairo_scaled_font_fini (&user_scaled_font->base); free (user_scaled_font); @@ -448,6 +519,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ static const cairo_font_face_backend_t _cairo_user_font_face_backend = { CAIRO_FONT_TYPE_USER, NULL, /* destroy */ + NULL, /* direct implementation */ _cairo_user_font_face_scaled_font_create }; @@ -497,6 +569,7 @@ cairo_user_font_face_create (void) return &font_face->base; } +slim_hidden_def(cairo_user_font_face_create); /* User-font method setters */ @@ -520,17 +593,24 @@ void cairo_user_font_face_set_init_func (cairo_font_face_t *font_face, cairo_user_scaled_font_init_func_t init_func) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return; } + + user_font_face = (cairo_user_font_face_t *) font_face; if (user_font_face->immutable) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) return; } user_font_face->scaled_font_methods.init = init_func; } +slim_hidden_def(cairo_user_font_face_set_init_func); /** * cairo_user_font_face_set_render_glyph_func: @@ -555,17 +635,24 @@ void cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face, cairo_user_scaled_font_render_glyph_func_t render_glyph_func) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return; } + + user_font_face = (cairo_user_font_face_t *) font_face; if (user_font_face->immutable) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) return; } user_font_face->scaled_font_methods.render_glyph = render_glyph_func; } +slim_hidden_def(cairo_user_font_face_set_render_glyph_func); /** * cairo_user_font_face_set_text_to_glyphs_func: @@ -586,11 +673,17 @@ void cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face, cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return; } + + user_font_face = (cairo_user_font_face_t *) font_face; if (user_font_face->immutable) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) return; @@ -617,17 +710,23 @@ void cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face, cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + if (font_face->status) + return; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return; } + + user_font_face = (cairo_user_font_face_t *) font_face; if (user_font_face->immutable) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) return; } user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func; } +slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func); /* User-font method getters */ @@ -638,18 +737,24 @@ cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t * Gets the scaled-font initialization function of a user-font. * * Return value: The init callback of @font_face - * or %NULL if none set. + * or %NULL if none set or an error has occurred. * * Since: 1.8 **/ cairo_user_scaled_font_init_func_t cairo_user_font_face_get_init_func (cairo_font_face_t *font_face) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return NULL; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return NULL; } + + user_font_face = (cairo_user_font_face_t *) font_face; return user_font_face->scaled_font_methods.init; } @@ -660,18 +765,24 @@ cairo_user_font_face_get_init_func (cairo_font_face_t *font_face) * Gets the glyph rendering function of a user-font. * * Return value: The render_glyph callback of @font_face - * or %NULL if none set. + * or %NULL if none set or an error has occurred. * * Since: 1.8 **/ cairo_user_scaled_font_render_glyph_func_t cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return NULL; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return NULL; } + + user_font_face = (cairo_user_font_face_t *) font_face; return user_font_face->scaled_font_methods.render_glyph; } @@ -682,18 +793,24 @@ cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face) * Gets the text-to-glyphs conversion function of a user-font. * * Return value: The text_to_glyphs callback of @font_face - * or %NULL if none set. + * or %NULL if none set or an error occurred. * * Since: 1.8 **/ cairo_user_scaled_font_text_to_glyphs_func_t cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return NULL; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return NULL; } + + user_font_face = (cairo_user_font_face_t *) font_face; return user_font_face->scaled_font_methods.text_to_glyphs; } @@ -704,17 +821,23 @@ cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face) * Gets the unicode-to-glyph conversion function of a user-font. * * Return value: The unicode_to_glyph callback of @font_face - * or %NULL if none set. + * or %NULL if none set or an error occurred. * * Since: 1.8 **/ cairo_user_scaled_font_unicode_to_glyph_func_t cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face) { - cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face; + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return NULL; + if (! _cairo_font_face_is_user (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return NULL; } + + user_font_face = (cairo_user_font_face_t *) font_face; return user_font_face->scaled_font_methods.unicode_to_glyph; } diff --git a/gfx/cairo/cairo/src/cairo-wideint-private.h b/gfx/cairo/cairo/src/cairo-wideint-private.h index 412fc00365f9..f5aac284818f 100644 --- a/gfx/cairo/cairo/src/cairo-wideint-private.h +++ b/gfx/cairo/cairo/src/cairo-wideint-private.h @@ -47,7 +47,7 @@ * as a pair of 32-bit ints */ -#define I cairo_private +#define I cairo_private cairo_const #if !HAVE_UINT64_T @@ -61,8 +61,10 @@ cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift); cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift); cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift); int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b); +int I _cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b); int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b); cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a); +#define _cairo_uint64_is_zero(a) ((a).hi == 0 && (a).lo == 0) #define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0) cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a); @@ -75,7 +77,9 @@ cairo_int64_t I _cairo_int32_to_int64(int32_t i); #define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b) #define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b) cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b); -int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b); +int I _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b); +int I _cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b); +#define _cairo_int64_is_zero(a) _cairo_uint64_is_zero (a) #define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b) #define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b) #define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b) @@ -96,6 +100,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b); #define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b)) #define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b))) #define _cairo_uint64_lt(a,b) ((a) < (b)) +#define _cairo_uint64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) +#define _cairo_uint64_is_zero(a) ((a) == 0) #define _cairo_uint64_eq(a,b) ((a) == (b)) #define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a))) #define _cairo_uint64_negative(a) ((int64_t) (a) < 0) @@ -111,6 +117,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b); #define _cairo_int64_mul(a,b) ((a) * (b)) #define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b)) #define _cairo_int64_lt(a,b) ((a) < (b)) +#define _cairo_int64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) +#define _cairo_int64_is_zero(a) ((a) == 0) #define _cairo_int64_eq(a,b) ((a) == (b)) #define _cairo_int64_lsl(a,b) ((a) << (b)) #define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b))) @@ -165,7 +173,9 @@ cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift); cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift); cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift); int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b); +int I _cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b); int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b); +#define _cairo_uint128_is_zero(a) (_cairo_uint64_is_zero ((a).hi) && _cairo_uint64_is_zero ((a).lo)) cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a); #define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi)) cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a); @@ -181,10 +191,13 @@ cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i); #define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b) #define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b) cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b); +#define _cairo_int64x32_128_mul(a, b) _cairo_int64x64_128_mul(a, _cairo_int32_to_int64(b)) #define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b) #define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b) #define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b) int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b); +int I _cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b); +#define _cairo_int128_is_zero(a) _cairo_uint128_is_zero (a) #define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b) #define _cairo_int128_negate(a) _cairo_uint128_negate(a) #define _cairo_int128_negative(a) (_cairo_uint128_negative(a)) @@ -204,6 +217,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b); #define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b)) #define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b))) #define _cairo_uint128_lt(a,b) ((a) < (b)) +#define _cairo_uint128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) +#define _cairo_uint128_is_zero(a) ((a) == 0) #define _cairo_uint128_eq(a,b) ((a) == (b)) #define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a))) #define _cairo_uint128_negative(a) ((int128_t) (a) < 0) @@ -221,6 +236,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b); #define _cairo_int128_mul(a,b) ((a) * (b)) #define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b)) #define _cairo_int128_lt(a,b) ((a) < (b)) +#define _cairo_int128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) +#define _cairo_int128_is_zero(a) ((a) == 0) #define _cairo_int128_eq(a,b) ((a) == (b)) #define _cairo_int128_lsl(a,b) ((a) << (b)) #define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b))) diff --git a/gfx/cairo/cairo/src/cairo-wideint-type-private.h b/gfx/cairo/cairo/src/cairo-wideint-type-private.h index fdcfe1d303c4..3d241502a338 100644 --- a/gfx/cairo/cairo/src/cairo-wideint-type-private.h +++ b/gfx/cairo/cairo/src/cairo-wideint-type-private.h @@ -37,6 +37,8 @@ #ifndef CAIRO_WIDEINT_TYPE_H #define CAIRO_WIDEINT_TYPE_H +#include "cairo.h" + #if HAVE_CONFIG_H #include "config.h" #endif diff --git a/gfx/cairo/cairo/src/cairo-wideint.c b/gfx/cairo/cairo/src/cairo-wideint.c index e8d3ab69aa57..45655938679b 100644 --- a/gfx/cairo/cairo/src/cairo-wideint.c +++ b/gfx/cairo/cairo/src/cairo-wideint.c @@ -235,6 +235,32 @@ _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b) return _cairo_uint64_lt (a, b); } +int +_cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b) +{ + if (a.hi < b.hi) + return -1; + else if (a.hi > b.hi) + return 1; + else if (a.lo < b.lo) + return -1; + else if (a.lo > b.lo) + return 1; + else + return 0; +} + +int +_cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b) +{ + if (_cairo_int64_negative (a) && !_cairo_int64_negative (b)) + return -1; + if (!_cairo_int64_negative (a) && _cairo_int64_negative (b)) + return 1; + + return _cairo_uint64_cmp (a, b); +} + cairo_uint64_t _cairo_uint64_not (cairo_uint64_t a) { @@ -569,6 +595,28 @@ _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b) return _cairo_uint128_lt (a, b); } +int +_cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b) +{ + int cmp; + + cmp = _cairo_uint64_cmp (a.hi, b.hi); + if (cmp) + return cmp; + return _cairo_uint64_cmp (a.lo, b.lo); +} + +int +_cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b) +{ + if (_cairo_int128_negative (a) && !_cairo_int128_negative (b)) + return -1; + if (!_cairo_int128_negative (a) && _cairo_int128_negative (b)) + return 1; + + return _cairo_uint128_cmp (a, b); +} + int _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b) { diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index f82d52887ea5..879cfac79d40 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -640,21 +640,25 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW"); - goto FAIL2; + goto FAIL3; } *num_glyphs = n16; *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t)); if (!*glyphs) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; + goto FAIL3; } x_pos = x; y_pos = y; + mat = scaled_font->base.ctm; status = cairo_matrix_invert (&mat); assert (status == CAIRO_STATUS_SUCCESS); + + _cairo_scaled_font_freeze_cache (&scaled_font->base); + for (i = 0; i < n16; i++) { cairo_scaled_glyph_t *scaled_glyph; @@ -668,7 +672,8 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled &scaled_glyph); if (status) { free (*glyphs); - goto FAIL2; + *glyphs = NULL; + break; } x = scaled_glyph->x_advance; @@ -678,8 +683,10 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled y_pos += y; } - cairo_win32_scaled_font_done_font (&scaled_font->base); + _cairo_scaled_font_thaw_cache (&scaled_font->base); +FAIL3: + cairo_win32_scaled_font_done_font (&scaled_font->base); FAIL2: free (glyph_indices); FAIL1: @@ -1829,6 +1836,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = { CAIRO_FONT_TYPE_WIN32, + NULL, _cairo_win32_scaled_font_create_toy, _cairo_win32_scaled_font_fini, _cairo_win32_scaled_font_glyph_init, @@ -1898,6 +1906,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, + NULL, /* direct implementation */ _cairo_win32_font_face_scaled_font_create }; diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c index 55d5b196caef..2c2f061d95a9 100644 --- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c @@ -490,7 +490,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf { cairo_status_t status; cairo_extend_t extend; - cairo_surface_t *pat_surface; cairo_surface_attributes_t pat_attr; cairo_image_surface_t *image; void *image_extra; @@ -516,25 +515,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf background_color = CAIRO_COLOR_BLACK; extend = cairo_pattern_get_extend (&pattern->base); - status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern, - (cairo_surface_t *)surface, - 0, 0, -1, -1, - &pat_surface, &pat_attr); + + status = _cairo_surface_acquire_source_image (pattern->surface, + &image, &image_extra); if (status) return status; - status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra); - if (status) - goto FINISH; - if (image->base.status) { status = image->base.status; - goto FINISH2; + goto CLEANUP_IMAGE; } if (image->width == 0 || image->height == 0) { status = CAIRO_STATUS_SUCCESS; - goto FINISH2; + goto CLEANUP_IMAGE; } if (image->format != CAIRO_FORMAT_RGB24) { @@ -545,7 +539,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf image->height); if (opaque_surface->status) { status = opaque_surface->status; - goto FINISH3; + goto CLEANUP_OPAQUE_IMAGE; } _cairo_pattern_init_for_surface (&opaque_pattern, &image->base); @@ -557,7 +551,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf image->width, image->height); if (status) { _cairo_pattern_fini (&opaque_pattern.base); - goto FINISH3; + goto CLEANUP_OPAQUE_IMAGE; } status = _cairo_surface_composite (CAIRO_OPERATOR_OVER, @@ -571,7 +565,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf image->height); if (status) { _cairo_pattern_fini (&opaque_pattern.base); - goto FINISH3; + goto CLEANUP_OPAQUE_IMAGE; } _cairo_pattern_fini (&opaque_pattern.base); @@ -602,8 +596,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf SaveDC (surface->dc); _cairo_matrix_to_win32_xform (&m, &xform); - if (!SetWorldTransform (surface->dc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); + if (! SetWorldTransform (surface->dc, &xform)) { + status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); + goto CLEANUP_OPAQUE_IMAGE; + } oldmode = SetStretchBltMode(surface->dc, HALFTONE); @@ -635,19 +631,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf &bi, DIB_RGB_COLORS, SRCCOPY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); + { + status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); + goto CLEANUP_OPAQUE_IMAGE; + } } } SetStretchBltMode(surface->dc, oldmode); RestoreDC (surface->dc, -1); -FINISH3: +CLEANUP_OPAQUE_IMAGE: if (opaque_image != image) cairo_surface_destroy (opaque_surface); -FINISH2: - _cairo_surface_release_source_image (pat_surface, image, image_extra); -FINISH: - _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr); +CLEANUP_IMAGE: + _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; } @@ -1525,6 +1522,12 @@ _cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface, surface->paginated_mode = paginated_mode; } +static cairo_bool_t +_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface) +{ + return TRUE; +} + /** * cairo_win32_printing_surface_create: * @hdc: the DC to create a surface for @@ -1645,4 +1648,6 @@ static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_bac _cairo_win32_printing_surface_start_page, _cairo_win32_printing_surface_set_paginated_mode, NULL, /* set_bounding_box */ + NULL, /* _cairo_win32_printing_surface_has_fallback_images, */ + _cairo_win32_printing_surface_supports_fine_grained_fallbacks, }; diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index 7a2dc06a0dbf..a87287efb5ed 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -160,6 +160,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out); static inline void diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index 2a8c0723488c..a0031a060445 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -435,6 +435,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_content_t src_content; @@ -444,10 +446,16 @@ _cairo_win32_surface_clone_similar (void *abstract_surface, src_content = cairo_surface_get_content(src); new_surface = - _cairo_win32_surface_create_similar_internal (abstract_surface, src_content, width, height, FALSE); + _cairo_win32_surface_create_similar_internal (abstract_surface, + src_content, + width, height, + FALSE); + if (new_surface == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; - if (cairo_surface_status(new_surface)) - return cairo_surface_status(new_surface); + status = new_surface->status; + if (status) + return status; _cairo_pattern_init_for_surface (&pattern, src); @@ -462,9 +470,11 @@ _cairo_win32_surface_clone_similar (void *abstract_surface, _cairo_pattern_fini (&pattern.base); - if (status == CAIRO_STATUS_SUCCESS) + if (status == CAIRO_STATUS_SUCCESS) { + *clone_offset_x = src_x; + *clone_offset_y = src_y; *clone_out = new_surface; - else + } else cairo_surface_destroy (new_surface); return status; @@ -512,8 +522,10 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, local = (cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal (surface, content, width, height, TRUE); + if (local == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; if (local->base.status) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return local->base.status; status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -2005,34 +2017,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = { */ -#if !defined(CAIRO_WIN32_STATIC_BUILD) - -/* declare to avoid "no previous prototype for 'DllMain'" warning */ -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved); - -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - CAIRO_MUTEX_INITIALIZE (); - break; - - case DLL_PROCESS_DETACH: - CAIRO_MUTEX_FINALIZE (); - break; - } - - return TRUE; -} - -#endif - cairo_int_status_t _cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface) { diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h index 8bd7a9740532..cb517bc87bda 100644 --- a/gfx/cairo/cairo/src/cairo-win32.h +++ b/gfx/cairo/cairo/src/cairo-win32.h @@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface); cairo_public cairo_surface_t * cairo_win32_surface_get_image (cairo_surface_t *surface); +#if CAIRO_HAS_WIN32_FONT + +/* + * Win32 font support + */ + cairo_public cairo_font_face_t * cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont); @@ -95,6 +101,8 @@ cairo_public void cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, cairo_matrix_t *device_to_logical); +#endif /* CAIRO_HAS_WIN32_FONT */ + CAIRO_END_DECLS #else /* CAIRO_HAS_WIN32_SURFACE */ diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c index 7251824b8298..1760bcbcf13d 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c @@ -197,7 +197,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src, xrender_format, width, height); if (surface->base.status) - return surface; + return &surface->base; surface->owns_pixmap = TRUE; @@ -695,6 +695,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_xcb_surface_t *surface = abstract_surface; @@ -704,6 +706,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface, cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src; if (_cairo_xcb_surface_same_screen(surface, xcb_src)) { + *clone_offset_x = 0; + *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; @@ -711,19 +715,29 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface, } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; cairo_content_t content = _cairo_content_from_format (image_src->format); + cairo_status_t status; if (surface->base.status) return surface->base.status; clone = (cairo_xcb_surface_t *) - _cairo_xcb_surface_create_similar (surface, content, - image_src->width, image_src->height); + _cairo_xcb_surface_create_similar (surface, content, width, height); + if (clone == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; if (clone->base.status) return clone->base.status; - _draw_image_surface (clone, image_src, src_x, src_y, - width, height, src_x, src_y); + status = _draw_image_surface (clone, image_src, + src_x, src_y, + width, height, + 0, 0); + if (status) { + cairo_surface_destroy (&clone->base); + return status; + } + *clone_offset_x = src_x; + *clone_offset_y = src_y; *clone_out = &clone->base; return CAIRO_STATUS_SUCCESS; @@ -879,7 +893,9 @@ _surfaces_compatible (cairo_xcb_surface_t *dst, return FALSE; /* if Render is supported, match picture formats */ - if (src->xrender_format.id != XCB_NONE && src->xrender_format.id == dst->xrender_format.id) + if (src->xrender_format.id != dst->xrender_format.id) + return FALSE; + else if (src->xrender_format.id != XCB_NONE) return TRUE; /* Without Render, match visuals instead */ @@ -1111,6 +1127,7 @@ _cairo_xcb_surface_composite (cairo_operator_t op, cairo_int_status_t status; composite_operation_t operation; int itx, ity; + cairo_bool_t is_integer_translation; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1200,7 +1217,9 @@ _cairo_xcb_surface_composite (cairo_operator_t op, */ _cairo_xcb_surface_ensure_gc (dst); - _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity); + is_integer_translation = + _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity); + assert (is_integer_translation == TRUE); { uint32_t mask = XCB_GC_FILL_STYLE | XCB_GC_TILE | XCB_GC_TILE_STIPPLE_ORIGIN_X @@ -1319,7 +1338,7 @@ _create_a8_picture (cairo_xcb_surface_t *surface, /* Creates a temporary mask for the trapezoids covering the area * [@dst_x, @dst_y, @width, @height] of the destination surface. */ -static xcb_render_picture_t +static cairo_status_t _create_trapezoid_mask (cairo_xcb_surface_t *dst, cairo_trapezoid_t *traps, int num_traps, @@ -1327,7 +1346,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst, int dst_y, int width, int height, - xcb_render_pictforminfo_t *pict_format) + xcb_render_pictforminfo_t *pict_format, + xcb_render_picture_t *mask_picture_out) { xcb_render_color_t transparent = { 0, 0, 0, 0 }; xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff }; @@ -1346,10 +1366,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst, solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE); offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t)); - if (!offset_traps) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return XCB_NONE; - } + if (offset_traps == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); for (i = 0; i < num_traps; i++) { offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y; @@ -1373,7 +1391,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst, xcb_render_free_picture (dst->dpy, solid_picture); free (offset_traps); - return mask_picture; + *mask_picture_out = mask_picture; + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -1460,13 +1479,14 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op, * bounds and clip. (xcb_render_add_traps() could be used to make creating * the mask somewhat cheaper.) */ - xcb_render_picture_t mask_picture = _create_trapezoid_mask (dst, traps, num_traps, - dst_x, dst_y, width, height, - render_format); - if (!mask_picture) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + xcb_render_picture_t mask_picture = 0; /* silence compiler */ + + status = _create_trapezoid_mask (dst, traps, num_traps, + dst_x, dst_y, width, height, + render_format, + &mask_picture); + if (status) goto BAIL; - } xcb_render_composite (dst->dpy, _render_operator (op), @@ -1639,6 +1659,12 @@ _cairo_xcb_surface_is_similar (void *surface_a, cairo_xcb_surface_t *b = surface_b; xcb_render_pictforminfo_t *xrender_format; + /* XXX: disable caching by the solid pattern cache until we implement + * display notification to avoid issuing xcb calls from the wrong thread + * or accessing the surface after the Display has been closed. + */ + return FALSE; + if (! _cairo_xcb_surface_same_screen (a, b)) return FALSE; @@ -1959,9 +1985,10 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface, int height) { cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) abstract_surface; + cairo_status_t status_ignored; if (! _cairo_surface_is_xcb (abstract_surface)) { - _cairo_surface_set_error (abstract_surface, + status_ignored = _cairo_surface_set_error (abstract_surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return; } @@ -2305,14 +2332,121 @@ typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t) (cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int, const cairo_glyph_t *, int, cairo_scaled_font_t *); +static cairo_bool_t +_cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst, + cairo_scaled_font_t *scaled_font) +{ + cairo_xcb_surface_font_private_t *font_private; + + font_private = scaled_font->surface_private; + if ((scaled_font->surface_backend != NULL && + scaled_font->surface_backend != &cairo_xcb_surface_backend) || + (font_private != NULL && font_private->dpy != dst->dpy)) + { + return FALSE; + } + + return TRUE; +} + + + +static cairo_status_t +_cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_operator_t op, + cairo_xcb_surface_t *src, + cairo_surface_attributes_t *attributes, + int *remaining_glyphs) +{ + cairo_scaled_glyph_t *scaled_glyph; + int i, o; + unsigned long max_index = 0; + cairo_status_t status; + cairo_glyph_t *output_glyphs; + const cairo_glyph_t *glyphs_chunk; + int glyphs_remaining, chunk_size, max_chunk_size; + cairo_xcb_surface_show_glyphs_func_t show_glyphs_func; + + /* We make a copy of the glyphs so that we can elide any size-zero + * glyphs to workaround an X server bug, (present in at least Xorg + * 7.1 without EXA). */ + output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); + if (output_glyphs == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + for (i = 0, o = 0; i < num_glyphs; i++) { + if (glyphs[i].index > max_index) + max_index = glyphs[i].index; + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + if (status) { + free (output_glyphs); + return status; + } + + /* Don't put any size-zero glyphs into output_glyphs to avoid + * an X server bug which stops rendering glyphs after the + * first size-zero glyph. */ + if (scaled_glyph->surface->width && scaled_glyph->surface->height) { + output_glyphs[o++] = glyphs[i]; + if (scaled_glyph->surface_private == NULL) { + _cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); + scaled_glyph->surface_private = (void *) 1; + } + } + } + num_glyphs = o; + + _cairo_xcb_surface_ensure_dst_picture (dst); + + max_chunk_size = xcb_get_maximum_request_length (dst->dpy); + if (max_index < 256) { + /* XXX: these are all the same size! (28) */ + max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t); + show_glyphs_func = _cairo_xcb_surface_show_glyphs_8; + } else if (max_index < 65536) { + max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t); + show_glyphs_func = _cairo_xcb_surface_show_glyphs_16; + } else { + max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t); + show_glyphs_func = _cairo_xcb_surface_show_glyphs_32; + } + /* XXX: I think this is wrong; this is only the header size (2 longs) */ + /* but should also include the glyph (1 long) */ + /* max_chunk_size /= sz_xGlyphElt; */ + max_chunk_size /= 3*sizeof(uint32_t); + + for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs; + glyphs_remaining; + glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) + { + chunk_size = MIN (glyphs_remaining, max_chunk_size); + + status = show_glyphs_func (dst, op, src, + attributes->x_offset, attributes->y_offset, + glyphs_chunk, chunk_size, scaled_font); + if (status) { + free (output_glyphs); + return status; + } + } + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t _cairo_xcb_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) + cairo_operator_t op, + cairo_pattern_t *src_pattern, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + int *remaining_glyphs) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_xcb_surface_t *dst = abstract_dst; @@ -2321,17 +2455,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst, cairo_surface_attributes_t attributes; cairo_xcb_surface_t *src = NULL; - cairo_glyph_t *output_glyphs; - const cairo_glyph_t *glyphs_chunk; - int glyphs_remaining, chunk_size, max_chunk_size; - cairo_scaled_glyph_t *scaled_glyph; - cairo_xcb_surface_font_private_t *font_private; - - int i, o; - unsigned long max_index = 0; - - cairo_xcb_surface_show_glyphs_func_t show_glyphs_func; - cairo_solid_pattern_t solid_pattern; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE) @@ -2365,29 +2488,16 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst, if (operation == DO_UNSUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; - font_private = scaled_font->surface_private; - if ((scaled_font->surface_backend != NULL && - scaled_font->surface_backend != &cairo_xcb_surface_backend) || - (font_private != NULL && font_private->dpy != dst->dpy)) + if (! _cairo_xcb_surface_owns_font (dst, scaled_font)) return CAIRO_INT_STATUS_UNSUPPORTED; - /* We make a copy of the glyphs so that we can elide any size-zero - * glyphs to workaround an X server bug, (present in at least Xorg - * 7.1 without EXA). */ - output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (output_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - /* After passing all those tests, we're now committed to rendering * these glyphs or to fail trying. We first upload any glyphs to * the X server that it doesn't have already, then we draw * them. We tie into the scaled_font's glyph cache and remove * glyphs from the X server when they are ejected from the - * scaled_font cache. Because of this we first freeze the - * scaled_font's cache so that we don't cause any of our glyphs to - * be ejected and removed from the X server before we have a - * chance to render them. */ - _cairo_scaled_font_freeze_cache (scaled_font); + * scaled_font cache. + */ /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore * the mask (the glyphs). This code below was executed as a side effect @@ -2437,64 +2547,21 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst, goto BAIL; /* Send all unsent glyphs to the server, and count the max of the glyph indices */ - for (i = 0, o = 0; i < num_glyphs; i++) { - if (glyphs[i].index > max_index) - max_index = glyphs[i].index; - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status != CAIRO_STATUS_SUCCESS) - goto BAIL; - /* Don't put any size-zero glyphs into output_glyphs to avoid - * an X server bug which stops rendering glyphs after the - * first size-zero glyph. */ - if (scaled_glyph->surface->width && scaled_glyph->surface->height) { - output_glyphs[o++] = glyphs[i]; - if (scaled_glyph->surface_private == NULL) { - _cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); - scaled_glyph->surface_private = (void *) 1; - } - } - } - num_glyphs = o; + _cairo_scaled_font_freeze_cache (scaled_font); - _cairo_xcb_surface_ensure_dst_picture (dst); - - max_chunk_size = xcb_get_maximum_request_length (dst->dpy); - if (max_index < 256) { - /* XXX: these are all the same size! (28) */ - max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_8; - } else if (max_index < 65536) { - max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_16; - } else { - max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_32; - } - /* XXX: I think this is wrong; this is only the header size (2 longs) */ - /* but should also include the glyph (1 long) */ - /* max_chunk_size /= sz_xGlyphElt; */ - max_chunk_size /= 3*sizeof(uint32_t); - - for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs; - glyphs_remaining; - glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) - { - chunk_size = MIN (glyphs_remaining, max_chunk_size); - - status = show_glyphs_func (dst, op, src, - attributes.x_offset, attributes.y_offset, - glyphs_chunk, chunk_size, scaled_font); - if (status != CAIRO_STATUS_SUCCESS) - break; - } + if (_cairo_xcb_surface_owns_font (dst, scaled_font)) + status = _cairo_xcb_surface_emit_glyphs (dst, + glyphs, num_glyphs, + scaled_font, + op, + src, + &attributes, + remaining_glyphs); + else + status = CAIRO_INT_STATUS_UNSUPPORTED; + _cairo_scaled_font_thaw_cache (scaled_font); BAIL: - _cairo_scaled_font_thaw_cache (scaled_font); - free (output_glyphs); - if (src) _cairo_pattern_release_surface (src_pattern, &src->base, &attributes); if (src_pattern == &solid_pattern.base) diff --git a/gfx/cairo/cairo/src/cairo-xlib-screen.c b/gfx/cairo/cairo/src/cairo-xlib-screen.c index 4a26eee5f68f..f670b8ae7fbd 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-screen.c +++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c @@ -150,22 +150,13 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in cairo_bool_t xft_antialias; int xft_hintstyle; int xft_rgba; - int xft_lcdfilter; cairo_antialias_t antialias; cairo_subpixel_order_t subpixel_order; - cairo_lcd_filter_t lcd_filter; cairo_hint_style_t hint_style; if (!get_boolean_default (dpy, "antialias", &xft_antialias)) xft_antialias = TRUE; - if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) { - /* -1 is an non-existant Fontconfig constant used to differentiate - * the case when no lcdfilter property is available. - */ - xft_lcdfilter = -1; - } - if (!get_boolean_default (dpy, "hinting", &xft_hinting)) xft_hinting = TRUE; @@ -248,24 +239,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; } - switch (xft_lcdfilter) { - case FC_LCD_NONE: - lcd_filter = CAIRO_LCD_FILTER_NONE; - break; - case FC_LCD_DEFAULT: - lcd_filter = CAIRO_LCD_FILTER_FIR5; - break; - case FC_LCD_LIGHT: - lcd_filter = CAIRO_LCD_FILTER_FIR3; - break; - case FC_LCD_LEGACY: - lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL; - break; - default: - lcd_filter = CAIRO_LCD_FILTER_DEFAULT; - break; - } - if (xft_antialias) { if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT) antialias = CAIRO_ANTIALIAS_GRAY; @@ -278,7 +251,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in cairo_font_options_set_hint_style (&info->font_options, hint_style); cairo_font_options_set_antialias (&info->font_options, antialias); cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order); - cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter); cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON); } diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index d6f41099f331..619eb36d7c19 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -147,7 +147,7 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src, return NULL; xrender_format = _cairo_xlib_display_get_xrender_format ( - src->screen_info->display, + src->display, format); if (xrender_format == NULL) return NULL; @@ -211,7 +211,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY)); - _cairo_xlib_display_notify (src->screen_info->display); + _cairo_xlib_display_notify (src->display); /* Start by examining the surface's XRenderFormat, or if it * doesn't have one, then look one up through its visual (in the @@ -259,9 +259,7 @@ static cairo_status_t _cairo_xlib_surface_finish (void *abstract_surface) { cairo_xlib_surface_t *surface = abstract_surface; - cairo_xlib_display_t *display = surface->screen_info ? - surface->screen_info->display : - NULL; + cairo_xlib_display_t *display = surface->display; cairo_status_t status = CAIRO_STATUS_SUCCESS; if (surface->owns_pixmap) { @@ -345,7 +343,7 @@ _swap_ximage_2bytes (XImage *ximage) char *line = ximage->data; for (j = ximage->height; j; j--) { - uint16_t *p = (uint16_t *)line; + uint16_t *p = (uint16_t *) line; for (i = ximage->width; i; i--) { *p = bswap_16 (*p); p++; @@ -355,6 +353,26 @@ _swap_ximage_2bytes (XImage *ximage) } } +static void +_swap_ximage_3bytes (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint8_t *p = (uint8_t *) line; + for (i = ximage->width; i; i--) { + uint8_t tmp; + tmp = p[2]; + p[2] = p[0]; + p[0] = tmp; + p += 3; + } + + line += ximage->bytes_per_line; + } +} + static void _swap_ximage_4bytes (XImage *ximage) { @@ -362,7 +380,7 @@ _swap_ximage_4bytes (XImage *ximage) char *line = ximage->data; for (j = ximage->height; j; j--) { - uint32_t *p = (uint32_t *)line; + uint32_t *p = (uint32_t *) line; for (i = ximage->width; i; i--) { *p = bswap_32 (*p); p++; @@ -372,6 +390,23 @@ _swap_ximage_4bytes (XImage *ximage) } } +static void +_swap_ximage_nibbles (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint8_t *p = (uint8_t *) line; + for (i = (ximage->width + 1) / 2; i; i--) { + *p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf); + p++; + } + + line += ximage->bytes_per_line; + } +} + static void _swap_ximage_bits (XImage *ximage) { @@ -404,7 +439,8 @@ _swap_ximage_to_native (XImage *ximage) int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; if (ximage->bits_per_pixel == 1 && - ximage->bitmap_bit_order != native_byte_order) { + ximage->bitmap_bit_order != native_byte_order) + { _swap_ximage_bits (ximage); if (ximage->bitmap_bit_order == ximage->byte_order) return; @@ -417,25 +453,32 @@ _swap_ximage_to_native (XImage *ximage) case 1: unit_bytes = ximage->bitmap_unit / 8; break; + case 4: + _swap_ximage_nibbles (ximage); + /* fall-through */ case 8: case 16: + case 20: + case 24: + case 28: + case 30: case 32: - unit_bytes = ximage->bits_per_pixel / 8; + unit_bytes = (ximage->bits_per_pixel + 7) / 8; break; default: - /* This could be hit on some uncommon but possible cases, - * such as bpp=4. These are cases that libpixman can't deal - * with in any case. - */ + /* This could be hit on some rare but possible cases. */ ASSERT_NOT_REACHED; } switch (unit_bytes) { case 1: - return; + break; case 2: _swap_ximage_2bytes (ximage); break; + case 3: + _swap_ximage_3bytes (ximage); + break; case 4: _swap_ximage_4bytes (ximage); break; @@ -678,8 +721,11 @@ _get_image_surface (cairo_xlib_surface_t *surface, xlib_masks.green_mask = surface->g_mask; xlib_masks.blue_mask = surface->b_mask; - status = _pixman_format_from_masks (&xlib_masks, &pixman_format); - if (xlib_masks.bpp >= 24 &&status == CAIRO_STATUS_SUCCESS) { + if (_pixman_format_from_masks (&xlib_masks, &pixman_format) && + xlib_masks.bpp >= 24 && + ximage->bitmap_unit == 32 && + ximage->bitmap_pad == 32) + { image = (cairo_image_surface_t*) _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data, pixman_format, @@ -1009,7 +1055,14 @@ _draw_image_surface (cairo_xlib_surface_t *surface, else in_pixel = row[x]; - a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift); + /* If the incoming image has no alpha channel, then the input + * is opaque and the output should have the maximum alpha value. + * For all other channels, their absence implies 0. + */ + if (image_masks.alpha_mask == 0x0) + a = 0xff; + else + a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift); r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift); g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift); b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift); @@ -1054,7 +1107,7 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf cairo_image_surface_t *image; cairo_status_t status; - _cairo_xlib_display_notify (surface->screen_info->display); + _cairo_xlib_display_notify (surface->display); status = _get_image_surface (surface, NULL, &image, NULL); if (status) @@ -1085,7 +1138,7 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac cairo_image_surface_t *image; cairo_status_t status; - _cairo_xlib_display_notify (surface->screen_info->display); + _cairo_xlib_display_notify (surface->display); status = _get_image_surface (surface, interest_rect, &image, image_rect_out); if (status) @@ -1134,18 +1187,22 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_xlib_surface_t *surface = abstract_surface; cairo_xlib_surface_t *clone; cairo_status_t status; - _cairo_xlib_display_notify (surface->screen_info->display); + _cairo_xlib_display_notify (surface->display); if (src->backend == surface->base.backend ) { cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src; if (_cairo_xlib_surface_same_screen (surface, xlib_src)) { + *clone_offset_x = 0; + *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; @@ -1156,25 +1213,30 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, if (! CAIRO_FORMAT_VALID (image_src->format)) return CAIRO_INT_STATUS_UNSUPPORTED; - if (image_src->width > XLIB_COORD_MAX || image_src->height > XLIB_COORD_MAX) - return CAIRO_STATUS_NO_MEMORY; + if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); clone = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_similar_with_format (surface, image_src->format, - image_src->width, image_src->height); + _cairo_xlib_surface_create_similar_with_format (surface, + image_src->format, + width, height); if (clone == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; if (clone->base.status) return clone->base.status; - status = _draw_image_surface (clone, image_src, src_x, src_y, - width, height, src_x, src_y); + status = _draw_image_surface (clone, image_src, + src_x, src_y, + width, height, + 0, 0); if (status) { cairo_surface_destroy (&clone->base); return status; } + *clone_offset_x = src_x; + *clone_offset_y = src_y; *clone_out = &clone->base; return CAIRO_STATUS_SUCCESS; @@ -1233,9 +1295,10 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac status = surface->base.status; if (status) goto BAIL; - surface->owns_pixmap = TRUE; - status = _cairo_surface_paint (&image->base, CAIRO_OPERATOR_SOURCE, &solid_pattern->base); + status = _cairo_surface_paint (&image->base, + CAIRO_OPERATOR_SOURCE, + &solid_pattern->base); if (status) goto BAIL; @@ -1246,17 +1309,19 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac if (status) goto BAIL; - BAIL: cairo_surface_destroy (&image->base); - if (status && surface) { - XFreePixmap (other->dpy, pixmap); + if (status) { + if (pixmap != None) + XFreePixmap (other->dpy, pixmap); cairo_surface_destroy (&surface->base); - surface = NULL; + + return _cairo_surface_create_in_error (status); } - return (cairo_surface_t *) surface; + surface->owns_pixmap = TRUE; + return &surface->base; } static cairo_status_t @@ -1267,25 +1332,18 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; - - xtransform.matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx); - xtransform.matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy); - xtransform.matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0); - - xtransform.matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx); - xtransform.matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy); - xtransform.matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0); - - xtransform.matrix[2][0] = 0; - xtransform.matrix[2][1] = 0; - xtransform.matrix[2][2] = 1 << 16; + + /* Casting between pixman_transform_t and XTransform is safe because + * they happen to be the exact same type. + */ + _cairo_matrix_to_pixman_matrix (matrix, (pixman_transform_t *)&xtransform); if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0) return CAIRO_STATUS_SUCCESS; if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) return CAIRO_INT_STATUS_UNSUPPORTED; - + XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform); surface->xtransform = xtransform; @@ -1379,10 +1437,10 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, switch (attributes->extend) { case CAIRO_EXTEND_NONE: - _cairo_xlib_surface_set_repeat (surface, 0); + _cairo_xlib_surface_set_repeat (surface, RepeatNone); break; case CAIRO_EXTEND_REPEAT: - _cairo_xlib_surface_set_repeat (surface, 1); + _cairo_xlib_surface_set_repeat (surface, RepeatNormal); break; case CAIRO_EXTEND_REFLECT: case CAIRO_EXTEND_PAD: @@ -1414,7 +1472,9 @@ _surfaces_compatible (cairo_xlib_surface_t *dst, return FALSE; /* if Render is supported, match picture formats */ - if (src->xrender_format != NULL && src->xrender_format == dst->xrender_format) + if (src->xrender_format != dst->xrender_format) + return FALSE; + else if (src->xrender_format != NULL) return TRUE; /* Without Render, match visuals instead */ @@ -1557,17 +1617,17 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst, _cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL); cairo_bool_t needs_alpha_composite; - if (!_cairo_surface_is_xlib (&src->base)) + if (! _cairo_surface_is_xlib (&src->base)) return DO_UNSUPPORTED; needs_alpha_composite = _operator_needs_alpha_composite (op, _surface_has_alpha (src)); - if (!have_mask && + if (! have_mask && is_integer_translation && src_attr->extend == CAIRO_EXTEND_NONE && - !needs_alpha_composite && - _surfaces_compatible(src, dst)) + ! needs_alpha_composite && + _surfaces_compatible (src, dst)) { return DO_XCOPYAREA; } @@ -1577,8 +1637,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst, src_attr->extend == CAIRO_EXTEND_REPEAT && (src->width != 1 || src->height != 1)) { - if (!have_mask && - !needs_alpha_composite && + if (! have_mask && + ! needs_alpha_composite && _surfaces_compatible (dst, src)) { return DO_XTILE; @@ -1587,10 +1647,10 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst, return DO_UNSUPPORTED; } - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) + if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) return DO_UNSUPPORTED; - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) + if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return DO_UNSUPPORTED; return DO_RENDER; @@ -1659,7 +1719,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, int itx, ity; cairo_bool_t is_integer_translation; - _cairo_xlib_display_notify (dst->screen_info->display); + _cairo_xlib_display_notify (dst->display); operation = _categorize_composite_operation (dst, op, src_pattern, mask_pattern != NULL); @@ -1682,7 +1742,10 @@ _cairo_xlib_surface_composite (cairo_operator_t op, status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } - if (mask != NULL && !_cairo_surface_is_xlib (&mask->base)) { + if (mask != NULL && + (! _cairo_surface_is_xlib (&mask->base) || + ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))) + { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } @@ -1737,12 +1800,18 @@ _cairo_xlib_surface_composite (cairo_operator_t op, status = _cairo_xlib_surface_ensure_gc (dst); if (status) goto BAIL; + + is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix, + &itx, &ity); + /* This is a pre-condition for DO_XCOPYAREA. */ + assert (is_integer_translation); + XCopyArea (dst->dpy, src->drawable, dst->drawable, dst->gc, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, + src_x + src_attr.x_offset + itx, + src_y + src_attr.y_offset + ity, width, height, dst_x, dst_y); break; @@ -1803,7 +1872,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, cairo_rectangle_int_t *rects, int num_rects) { - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status; cairo_solid_pattern_t solid; cairo_surface_t *solid_surface = NULL; cairo_surface_attributes_t attrs; @@ -1815,7 +1884,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, if (status) return status; - status = _cairo_pattern_acquire_surface (&solid.base, (cairo_surface_t *) surface, + status = _cairo_pattern_acquire_surface (&solid.base, &surface->base, 0, 0, ARRAY_LENGTH (dither_pattern[0]), ARRAY_LENGTH (dither_pattern), @@ -1824,7 +1893,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, if (status) return status; - if (!_cairo_surface_is_xlib (solid_surface)) { + if (! _cairo_surface_is_xlib (solid_surface)) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } @@ -1832,7 +1901,8 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, XSetTSOrigin (surface->dpy, surface->gc, - (surface->base.device_transform.x0 + attrs.x_offset), - (surface->base.device_transform.y0 + attrs.y_offset)); - XSetTile (surface->dpy, surface->gc, ((cairo_xlib_surface_t *) solid_surface)->drawable); + XSetTile (surface->dpy, surface->gc, + ((cairo_xlib_surface_t *) solid_surface)->drawable); XSetFillStyle (surface->dpy, surface->gc, FillTiled); for (i = 0; i < num_rects; i++) { @@ -1860,9 +1930,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, XRectangle *xrects = static_xrects; int i; - _cairo_xlib_display_notify (surface->screen_info->display); + _cairo_xlib_display_notify (surface->display); - if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) { + if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) { if (op == CAIRO_OPERATOR_CLEAR || ((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) && CAIRO_COLOR_IS_OPAQUE (color))) @@ -1918,10 +1988,17 @@ _create_a8_picture (cairo_xlib_surface_t *surface, Pixmap pixmap; Picture picture; + XRenderPictFormat *xrender_format; if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return None; + xrender_format = + _cairo_xlib_display_get_xrender_format (surface->display, + CAIRO_FORMAT_A8); + if (xrender_format == NULL) + return None; + pixmap = XCreatePixmap (surface->dpy, surface->drawable, width <= 0 ? 1 : width, height <= 0 ? 1 : height, @@ -1933,8 +2010,7 @@ _create_a8_picture (cairo_xlib_surface_t *surface, } picture = XRenderCreatePicture (surface->dpy, pixmap, - XRenderFindStandardFormat (surface->dpy, PictStandardA8), - mask, &pa); + xrender_format, mask, &pa); XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color, 0, 0, width, height); XFreePixmap (surface->dpy, pixmap); @@ -1993,6 +2069,11 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst, } solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE); + if (solid_picture == None) { + XRenderFreePicture (dst->dpy, mask_picture); + free (offset_traps); + return None; + } XRenderCompositeTrapezoids (dst->dpy, PictOpAdd, solid_picture, mask_picture, @@ -2029,7 +2110,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, int render_src_x, render_src_y; XRenderPictFormat *pict_format; - _cairo_xlib_display_notify (dst->screen_info->display); + _cairo_xlib_display_notify (dst->display); if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2045,7 +2126,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, if (status) return status; - operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); + operation = _recategorize_composite_operation (dst, op, src, + &attributes, TRUE); if (operation == DO_UNSUPPORTED) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; @@ -2053,13 +2135,17 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, switch (antialias) { case CAIRO_ANTIALIAS_NONE: - pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1); + pict_format = + _cairo_xlib_display_get_xrender_format (dst->display, + CAIRO_FORMAT_A1); break; case CAIRO_ANTIALIAS_GRAY: case CAIRO_ANTIALIAS_SUBPIXEL: case CAIRO_ANTIALIAS_DEFAULT: default: - pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8); + pict_format = + _cairo_xlib_display_get_xrender_format (dst->display, + CAIRO_FORMAT_A8); break; } @@ -2310,7 +2396,7 @@ _cairo_xlib_surface_is_similar (void *surface_a, _xrender_format_to_content (xrender_format) != content) { xrender_format = _cairo_xlib_display_get_xrender_format ( - b->screen_info->display, + b->display, _cairo_format_from_content (content)); } @@ -2486,15 +2572,24 @@ _cairo_xlib_surface_create_internal (Display *dpy, if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { if (!xrender_format) { - if (visual) + if (visual) { xrender_format = XRenderFindVisualFormat (dpy, visual); - else if (depth == 1) - xrender_format = XRenderFindStandardFormat (dpy, PictStandardA1); + } else if (depth == 1) { + xrender_format = + _cairo_xlib_display_get_xrender_format (display, + CAIRO_FORMAT_A1); + } } } else { xrender_format = NULL; } + /* we cannot use XRender for this surface, so ensure we don't try */ + if (xrender_format == NULL) { + surface->render_major = -1; + surface->render_minor = -1; + } + _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, _xrender_format_to_content (xrender_format)); @@ -2787,7 +2882,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, if (surface->drawable != drawable) { if (surface->dst_picture != None) { status = _cairo_xlib_display_queue_resource ( - surface->screen_info->display, + surface->display, XRenderFreePicture, surface->dst_picture); if (status) { @@ -2800,7 +2895,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, if (surface->src_picture != None) { status = _cairo_xlib_display_queue_resource ( - surface->screen_info->display, + surface->display, XRenderFreePicture, surface->src_picture); if (status) { @@ -3019,7 +3114,7 @@ _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display, scaled_font = font_private->scaled_font; CAIRO_MUTEX_LOCK (scaled_font->mutex); - font_private = scaled_font->surface_private; + font_private = scaled_font->surface_private; scaled_font->surface_private = NULL; _cairo_scaled_font_reset_cache (scaled_font); @@ -3331,7 +3426,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE, pscaled_glyph); - if (status != CAIRO_STATUS_SUCCESS) + if (status) return status; scaled_glyph = *pscaled_glyph; @@ -3369,7 +3464,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy, cairo_surface_t *tmp_surface; tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1); - if (tmp_surface->status) + status = tmp_surface->status; + if (status) goto BAIL; cr = cairo_create (tmp_surface); @@ -3398,7 +3494,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy, tmp_surface = cairo_image_surface_create (glyphset_info->format, glyph_surface->width, glyph_surface->height); - if (tmp_surface->status) + status = tmp_surface->status; + if (status) goto BAIL; tmp_surface->device_transform = glyph_surface->base.device_transform; @@ -3544,18 +3641,29 @@ typedef union { /* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */ COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t)); +/* Start a new element for the first glyph, + * or for any glyph that has unexpected position, + * or if current element has too many glyphs + * (Xrender limits each element to 252 glyphs, we limit them to 128) + * + * These same conditions need to be mirrored between + * _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks + */ +#define _start_new_glyph_elt(count, glyph) \ + (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y) + static cairo_status_t -_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, - cairo_xlib_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_xlib_surface_t *src, - cairo_surface_attributes_t *attributes, - /* info for this chunk */ - int num_elts, - int width, - cairo_xlib_font_glyphset_info_t *glyphset_info) +_emit_glyphs_chunk (cairo_xlib_surface_t *dst, + cairo_xlib_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_operator_t op, + cairo_xlib_surface_t *src, + cairo_surface_attributes_t *attributes, + /* info for this chunk */ + int num_elts, + int width, + cairo_xlib_font_glyphset_info_t *glyphset_info) { /* Which XRenderCompositeText function to use */ cairo_xrender_composite_text_func_t composite_text_func; @@ -3606,9 +3714,13 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, j = 0; for (i = 0; i < num_glyphs; i++) { - /* Start a new element for first output glyph, and for glyphs with - * unexpected position */ - if (!j || glyphs[i].i.x || glyphs[i].i.y) { + /* Start a new element for first output glyph, + * or for any glyph that has unexpected position, + * or if current element has too many glyphs. + * + * These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs() + */ + if (_start_new_glyph_elt (j, &glyphs[i])) { if (j) { elts[nelt].nchars = n; nelt++; @@ -3637,6 +3749,10 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, n = 0; } + /* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the + * expected number of xGlyphElts. */ + assert (nelt == num_elts); + composite_text_func (dst->dpy, _render_operator (op), src->src_picture, @@ -3653,6 +3769,11 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, return CAIRO_STATUS_SUCCESS; } + +/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have + * enough room for padding */ +#define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4) + static cairo_status_t _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, cairo_xlib_glyph_t *glyphs, @@ -3681,7 +3802,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, int request_size = 0; _cairo_xlib_surface_ensure_dst_picture (dst); - _cairo_xlib_display_notify (dst->screen_info->display); + _cairo_xlib_display_notify (dst->display); for (i = 0; i < num_glyphs; i++) { int this_x, this_y; @@ -3738,6 +3859,10 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, if (!glyphset_info) glyphset_info = this_glyphset_info; + /* The invariant here is that we can always flush the glyphs + * accumulated before this one, using old_width, and they + * would fit in the request. + */ old_width = width; /* Update max glyph index */ @@ -3762,11 +3887,11 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, * to the mask first, and then composes that to final surface, * though it's not a big deal. */ - if (request_size + width > max_request_size - sz_xGlyphElt || + if (request_size + width > max_request_size - _cairo_sz_xGlyphElt || (this_glyphset_info != glyphset_info)) { - status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i, - scaled_font, op, src, attributes, - num_elts, old_width, glyphset_info); + status = _emit_glyphs_chunk (dst, glyphs, i, + scaled_font, op, src, attributes, + num_elts, old_width, glyphset_info); if (status != CAIRO_STATUS_SUCCESS) return status; @@ -3787,11 +3912,15 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, glyphs[i].i.x = this_x - x; glyphs[i].i.y = this_y - y; - /* Start a new element for the first glyph, or for any glyph that - * has unexpected position */ - if (!num_out_glyphs || glyphs[i].i.x || glyphs[i].i.y) { + /* Start a new element for the first glyph, + * or for any glyph that has unexpected position, + * or if current element has too many glyphs. + * + * These same conditions are mirrored in _emit_glyphs_chunk(). + */ + if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) { num_elts++; - request_size += sz_xGlyphElt; + request_size += _cairo_sz_xGlyphElt; } /* adjust current-position */ @@ -3803,9 +3932,9 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, } if (num_elts) - status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i, - scaled_font, op, src, attributes, - num_elts, width, glyphset_info); + status = _emit_glyphs_chunk (dst, glyphs, i, + scaled_font, op, src, attributes, + num_elts, width, glyphset_info); *remaining_glyphs = num_glyphs - i; if (*remaining_glyphs && status == CAIRO_STATUS_SUCCESS) @@ -3814,6 +3943,23 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, return status; } +static cairo_bool_t +_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst, + cairo_scaled_font_t *scaled_font) +{ + cairo_xlib_surface_font_private_t *font_private; + + font_private = scaled_font->surface_private; + if ((scaled_font->surface_backend != NULL && + scaled_font->surface_backend != &cairo_xlib_surface_backend) || + (font_private != NULL && font_private->display != dst->display)) + { + return FALSE; + } + + return TRUE; +} + static cairo_int_status_t _cairo_xlib_surface_show_glyphs (void *abstract_dst, cairo_operator_t op, @@ -3830,11 +3976,9 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, cairo_surface_attributes_t attributes; cairo_xlib_surface_t *src = NULL; - cairo_xlib_surface_font_private_t *font_private; - cairo_solid_pattern_t solid_pattern; - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format) + if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; /* Just let unbounded operators go through the fallback code @@ -3865,22 +4009,14 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (operation == DO_UNSUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; - font_private = scaled_font->surface_private; - if ((scaled_font->surface_backend != NULL && - scaled_font->surface_backend != &cairo_xlib_surface_backend) || - (font_private != NULL && font_private->display != dst->screen_info->display)) + if (! _cairo_xlib_surface_owns_font (dst, scaled_font)) return CAIRO_INT_STATUS_UNSUPPORTED; /* After passing all those tests, we're now committed to rendering * these glyphs or to fail trying. We first upload any glyphs to * the X server that it doesn't have already, then we draw - * them. We tie into the scaled_font's glyph cache and remove - * glyphs from the X server when they are ejected from the - * scaled_font cache. Because of this we first freeze the - * scaled_font's cache so that we don't cause any of our glyphs to - * be ejected and removed from the X server before we have a - * chance to render them. */ - _cairo_scaled_font_freeze_cache (scaled_font); + * them. + */ /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore * the mask (the glyphs). This code below was executed as a side effect @@ -3920,7 +4056,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, goto BAIL0; } - operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); + operation = _recategorize_composite_operation (dst, op, src, + &attributes, TRUE); if (operation == DO_UNSUPPORTED) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL1; @@ -3930,14 +4067,19 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (status) goto BAIL1; - status = _cairo_xlib_surface_emit_glyphs (dst, - (cairo_xlib_glyph_t *) glyphs, - num_glyphs, - scaled_font, - op, - src, - &attributes, - remaining_glyphs); + _cairo_scaled_font_freeze_cache (scaled_font); + if (_cairo_xlib_surface_owns_font (dst, scaled_font)) { + status = _cairo_xlib_surface_emit_glyphs (dst, + (cairo_xlib_glyph_t *) glyphs, + num_glyphs, + scaled_font, + op, + src, + &attributes, + remaining_glyphs); + } else + status = CAIRO_INT_STATUS_UNSUPPORTED; + _cairo_scaled_font_thaw_cache (scaled_font); BAIL1: if (src) @@ -3945,8 +4087,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (src_pattern == &solid_pattern.base) _cairo_pattern_fini (&solid_pattern.base); BAIL0: - _cairo_scaled_font_thaw_cache (scaled_font); - _cairo_xlib_display_notify (dst->screen_info->display); + _cairo_xlib_display_notify (dst->display); return status; } diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index 6b919a327e8b..cefc92538fbb 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -42,7 +42,7 @@ #include "cairo-arc-private.h" #include "cairo-path-private.h" -#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */ +#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1) static const cairo_t _cairo_nil = { CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ @@ -84,8 +84,7 @@ static const cairo_t _cairo_nil = { cairo_status_t _cairo_error (cairo_status_t status) { - assert (status > CAIRO_STATUS_SUCCESS && - status <= CAIRO_STATUS_LAST_STATUS); + assert (_cairo_status_is_error (status)); return status; } @@ -288,7 +287,7 @@ cairo_set_user_data (cairo_t *cr, cairo_destroy_func_t destroy) { if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return cr->status; return _cairo_user_data_array_set_data (&cr->user_data, key, user_data, destroy); @@ -926,6 +925,7 @@ cairo_set_line_width (cairo_t *cr, double width) if (status) _cairo_set_error (cr, status); } +slim_hidden_def (cairo_set_line_width); /** * cairo_set_line_cap: @@ -955,6 +955,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) if (status) _cairo_set_error (cr, status); } +slim_hidden_def (cairo_set_line_cap); /** * cairo_set_line_join: @@ -984,6 +985,7 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) if (status) _cairo_set_error (cr, status); } +slim_hidden_def (cairo_set_line_join); /** * cairo_set_dash: @@ -2087,6 +2089,7 @@ cairo_stroke (cairo_t *cr) cairo_new_path (cr); } +slim_hidden_def(cairo_stroke); /** * cairo_stroke_preserve: @@ -3077,8 +3080,9 @@ cairo_show_text (cairo_t *cr, const char *utf8) cairo_glyph_t *glyphs = NULL, *last_glyph; cairo_text_cluster_t *clusters = NULL; int utf8_len, num_glyphs, num_clusters; - cairo_bool_t backward; + cairo_text_cluster_flags_t cluster_flags; double x, y; + cairo_bool_t has_show_text_glyphs; if (cr->status) return; @@ -3090,12 +3094,15 @@ cairo_show_text (cairo_t *cr, const char *utf8) utf8_len = strlen (utf8); + has_show_text_glyphs = + cairo_surface_has_show_text_glyphs (cairo_get_target (cr)); + status = _cairo_gstate_text_to_glyphs (cr->gstate, x, y, utf8, utf8_len, &glyphs, &num_glyphs, - cairo_has_show_text_glyphs (cr) ? &clusters : NULL, &num_clusters, - &backward); + has_show_text_glyphs ? &clusters : NULL, &num_clusters, + &cluster_flags); if (status) goto BAIL; @@ -3106,7 +3113,7 @@ cairo_show_text (cairo_t *cr, const char *utf8) utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward); + cluster_flags); if (status) goto BAIL; @@ -3169,36 +3176,6 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) _cairo_set_error (cr, status); } -/** - * cairo_has_show_text_glyphs: - * @cr: a cairo context - * - * Returns whether the target surface of a cairo context supports - * sophisticated cairo_show_text_glyphs() operations. That is, - * whether it actually uses the provided text and cluster data - * to a cairo_show_text_glyphs() call. - * - * Note: Even if this function returns %FALSE, a - * cairo_show_text_glyphs() operation will still succeed. It just will - * act like a cairo_show_glyphs() operation. Users can use this - * function to avoid computing UTF-8 text and cluster mapping if the - * target surface does not use it. - * - * This is a convenience function that simply calls - * cairo_surface_has_show_text_glyphs() on @cr's target. - * - * Return value: %TRUE if the target surface of @cr supports - * cairo_show_text_glyphs(), %FALSE otherwise - * - * Since: 1.8 - **/ -cairo_bool_t -cairo_has_show_text_glyphs (cairo_t *cr) -{ - return _cairo_gstate_has_show_text_glyphs (cr->gstate); -} -slim_hidden_def (cairo_has_show_text_glyphs); - /** * cairo_show_text_glyphs: * @cr: a cairo context @@ -3208,14 +3185,14 @@ slim_hidden_def (cairo_has_show_text_glyphs); * @num_glyphs: number of glyphs to show * @clusters: array of cluster mapping information * @num_clusters: number of clusters in the mapping - * @backward: whether the text to glyphs mapping goes backward + * @cluster_flags: cluster mapping flags * * This operation has rendering effects similar to cairo_show_glyphs() * but, if the target surface supports it, uses the provided text and * cluster mapping to embed the text for the glyphs shown in the output. - * The cairo_has_show_text_glyphs() function can be used to query that. - * If the target does not support it, this function acts like - * cairo_show_glyphs(). + * If the target does not support the extended attributes, this function + * acts like the basic cairo_show_glyphs() as if it had been passed + * @glyphs and @num_glyphs. * * The mapping between @utf8 and @glyphs is provided by an array of * clusters. Each cluster covers a number of @@ -3224,7 +3201,8 @@ slim_hidden_def (cairo_has_show_text_glyphs); * and @glyphs in entirety. * * The first cluster always covers bytes from the beginning of @utf8. - * If @backward is %FALSE, the first cluster also covers the beginning + * If @cluster_flags do not have the %CAIRO_TEXT_CLUSTER_FLAG_BACKWARD + * set, the first cluster also covers the beginning * of @glyphs, otherwise it covers the end of the @glyphs array and * following clusters move backward. * @@ -3240,7 +3218,7 @@ cairo_show_text_glyphs (cairo_t *cr, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward) + cairo_text_cluster_flags_t cluster_flags) { cairo_status_t status; @@ -3275,8 +3253,7 @@ cairo_show_text_glyphs (cairo_t *cr, * and that cluster boundaries are UTF-8 boundaries. */ status = _cairo_validate_text_clusters (utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - backward); + clusters, num_clusters, cluster_flags); if (status == CAIRO_STATUS_INVALID_CLUSTERS) { /* Either got invalid UTF-8 text, or cluster mapping is bad. * Differentiate those. */ @@ -3297,8 +3274,7 @@ cairo_show_text_glyphs (cairo_t *cr, status = _cairo_gstate_show_text_glyphs (cr->gstate, utf8, utf8_len, glyphs, num_glyphs, - clusters, num_clusters, - !!backward); + clusters, num_clusters, cluster_flags); if (status) _cairo_set_error (cr, status); } @@ -3585,6 +3561,7 @@ cairo_get_line_width (cairo_t *cr) return _cairo_gstate_get_line_width (cr->gstate); } +slim_hidden_def (cairo_get_line_width); /** * cairo_get_line_cap: diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index 1da882eaf60f..cf4bc05b389c 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -51,7 +51,11 @@ #endif #ifndef cairo_public -# define cairo_public +# if defined (_MSC_VER) && ! defined (CAIRO_WIN32_STATIC_BUILD) +# define cairo_public __declspec(dllimport) +# else +# define cairo_public +# endif #endif CAIRO_BEGIN_DECLS @@ -892,6 +896,19 @@ cairo_text_cluster_allocate (int num_clusters); cairo_public void cairo_text_cluster_free (cairo_text_cluster_t *clusters); +/** + * cairo_text_cluster_flags_t: + * @CAIRO_TEXT_CLUSTER_FLAG_BACKWARD: The clusters in the cluster array + * map to glyphs in the glyph array from end to start. + * + * Specifies properties of a text cluster mapping. + * + * Since: 1.8 + **/ +typedef enum _cairo_text_cluster_flags { + CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001 +} cairo_text_cluster_flags_t; + /** * cairo_text_extents_t: * @x_bearing: the horizontal distance from the origin to the @@ -1028,28 +1045,6 @@ typedef enum _cairo_subpixel_order { CAIRO_SUBPIXEL_ORDER_VBGR } cairo_subpixel_order_t; -/** - * cairo_lcd_filter_t: - * @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for - * font backend and target device - * @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering - * @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter - * @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel - * @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel - * - * The LCD filter specifies the low-pass filter applied to LCD-optimized - * bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL. - * - * Since: 1.8 - **/ -typedef enum _cairo_lcd_filter { - CAIRO_LCD_FILTER_DEFAULT, - CAIRO_LCD_FILTER_NONE, - CAIRO_LCD_FILTER_INTRA_PIXEL, - CAIRO_LCD_FILTER_FIR3, - CAIRO_LCD_FILTER_FIR5 -} cairo_lcd_filter_t; - /** * cairo_hint_style_t: * @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for @@ -1155,12 +1150,6 @@ cairo_font_options_set_subpixel_order (cairo_font_options_t *options, cairo_public cairo_subpixel_order_t cairo_font_options_get_subpixel_order (const cairo_font_options_t *options); -cairo_public void -cairo_font_options_set_lcd_filter (cairo_font_options_t *options, - cairo_lcd_filter_t lcd_filter); -cairo_public cairo_lcd_filter_t -cairo_font_options_get_lcd_filter (const cairo_font_options_t *options); - cairo_public void cairo_font_options_set_hint_style (cairo_font_options_t *options, cairo_hint_style_t hint_style); @@ -1220,9 +1209,6 @@ cairo_show_text (cairo_t *cr, const char *utf8); cairo_public void cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); -cairo_public cairo_bool_t -cairo_has_show_text_glyphs (cairo_t *cr); - cairo_public void cairo_show_text_glyphs (cairo_t *cr, const char *utf8, @@ -1231,7 +1217,7 @@ cairo_show_text_glyphs (cairo_t *cr, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward); + cairo_text_cluster_flags_t cluster_flags); cairo_public void cairo_text_path (cairo_t *cr, const char *utf8); @@ -1376,16 +1362,16 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, cairo_text_extents_t *extents); cairo_public cairo_status_t -cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward); +cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, + double x, + double y, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags); cairo_public cairo_font_face_t * cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font); @@ -1525,7 +1511,8 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal * @num_glyphs: pointer to number of glyphs * @clusters: pointer to array of cluster mapping information to fill, or %NULL * @num_clusters: pointer to number of clusters - * @backward: pointer to whether the text to glyphs mapping goes backward + * @cluster_flags: pointer to location to store cluster flags corresponding to the + * output @clusters * * #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which * is called to convert input text to an array of glyphs. This is used by the @@ -1536,35 +1523,30 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal * as well as complex shaping required for scripts like * Arabic and Indic. * - * The @num_glyphs argument is preset to -1. The callback should allocate an - * array for the resulting glyphs (using malloc()), and populate the glyph indices and - * positions (in font space) assuming that the text is to be shown at the - * origin. Cairo will free the glyph array when done with it, no matter what - * the return value of the callback is. - * - * If @glyphs initially points to a non-%NULL value, that array can be used - * as a glyph buffer, and @num_glyphs points to the number of glyph - * entries available there. If the provided glyph array is too short for + * The @num_glyphs argument is preset to the number of glyph entries available + * in the @glyphs buffer. If the @glyphs buffer is %NULL, the value of + * @num_glyphs will be zero. If the provided glyph array is too short for * the conversion (or for convenience), a new glyph array may be allocated * using cairo_glyph_allocate() and placed in @glyphs. Upon return, - * @num_glyphs should contain the number of generated glyphs. - * If the value @glyphs points at has changed after the call, cairo will - * free the allocated glyph array using cairo_glyph_free(). + * @num_glyphs should contain the number of generated glyphs. If the value + * @glyphs points at has changed after the call, the caller will free the + * allocated glyph array using cairo_glyph_free(). + * The callback should populate the glyph indices and positions (in font space) + * assuming that the text is to be shown at the origin. * - * If @clusters is not %NULL, @num_clusters and @backward are also non-%NULL, - * and cluster mapping should be computed. - * The semantics of how cluster array allocation works is similar to the glyph - * array. That is, + * If @clusters is not %NULL, @num_clusters and @cluster_flags are also + * non-%NULL, and cluster mapping should be computed. The semantics of how + * cluster array allocation works is similar to the glyph array. That is, * if @clusters initially points to a non-%NULL value, that array may be used * as a cluster buffer, and @num_clusters points to the number of cluster * entries available there. If the provided cluster array is too short for * the conversion (or for convenience), a new cluster array may be allocated * using cairo_text_cluster_allocate() and placed in @clusters. Upon return, * @num_clusters should contain the number of generated clusters. - * If the value @clusters points at has changed after the call, cairo will - * free the allocated cluster array using cairo_text_cluster_free(). + * If the value @clusters points at has changed after the call, the caller + * will free the allocated cluster array using cairo_text_cluster_free(). * - * The callback is optional. If not set, or if @num_glyphs is negative upon + * The callback is optional. If @num_glyphs is negative upon * the callback returning, the unicode_to_glyph callback * is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t. * @@ -1581,14 +1563,14 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal * * Since: 1.8 **/ -typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward); +typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags); /** * cairo_user_scaled_font_unicode_to_glyph_func_t: @@ -1931,8 +1913,7 @@ typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2, CAIRO_SURFACE_TYPE_WIN32_PRINTING, - CAIRO_SURFACE_TYPE_QUARTZ_IMAGE, - CAIRO_SURFACE_TYPE_QPAINTER + CAIRO_SURFACE_TYPE_QUARTZ_IMAGE } cairo_surface_type_t; cairo_public cairo_surface_type_t diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index 61c128f2c09f..77c0c9470d2f 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -50,12 +50,9 @@ #include "config.h" #endif -/* We use our own macros */ -#undef PACKAGE -#undef PACKAGE_NAME -#undef PACKAGE_STRING -#undef PACKAGE_TARNAME -#undef PACKAGE_VERSION +#ifdef _MSC_VER +#define cairo_public __declspec(dllexport) +#endif #include #include @@ -75,11 +72,14 @@ #include "cairo-compiler-private.h" -#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_SVG_SURFACE) +#if CAIRO_HAS_PS_SURFACE || \ + CAIRO_HAS_PDF_SURFACE || \ + CAIRO_HAS_SVG_SURFACE || \ + CAIRO_HAS_WIN32_SURFACE #define CAIRO_HAS_FONT_SUBSET 1 #endif -#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE) +#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE #define CAIRO_HAS_PDF_OPERATORS 1 #endif @@ -132,7 +132,7 @@ _cairo_win32_tmpfile (void); * a bit of a pain, but it should be easy to always catch as long as * one adds a new test case to test a trigger of the new status value. */ -#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_SLANT +#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_WEIGHT #ifdef __GNUC__ #define cairo_container_of(ptr, type, member) ({ \ @@ -418,6 +418,10 @@ typedef struct _cairo_scaled_font_subset { struct _cairo_scaled_font_backend { cairo_font_type_t type; + cairo_warn cairo_status_t + (*get_implementation) (cairo_toy_font_face_t *toy_face, + cairo_font_face_t **font_face); + cairo_warn cairo_status_t (*create_toy) (cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, @@ -438,16 +442,16 @@ struct _cairo_scaled_font_backend { * then just converting characters one by one. */ cairo_warn cairo_int_status_t - (*text_to_glyphs) (void *scaled_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward); + (*text_to_glyphs) (void *scaled_font, + double x, + double y, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags); unsigned long (*ucs4_to_index) (void *scaled_font, @@ -490,6 +494,10 @@ struct _cairo_font_face_backend { void (*destroy) (void *font_face); + cairo_warn cairo_status_t + (*get_implementation) (void *font_face, + cairo_font_face_t **font_face_out); + cairo_warn cairo_status_t (*scaled_font_create) (void *font_face, const cairo_matrix_t *font_matrix, @@ -498,6 +506,8 @@ struct _cairo_font_face_backend { cairo_scaled_font_t **scaled_font); }; +extern const cairo_private struct _cairo_scaled_font_backend _cairo_user_scaled_font_backend; + /* concrete font backends */ #if CAIRO_HAS_FT_FONT @@ -559,9 +569,12 @@ struct _cairo_surface_backend { * 1. It is as compatible as possible with @surface (in terms of * efficiency) * - * 2. It has the same size as @src + * 2. It has the same contents as @src within the given rectangle. * - * 3. It has the same contents as @src within the given rectangle. + * 3. The offset of the similar surface with respect to the original + * surface is returned in the clone_offset vector. + * - if you clone the entire surface, this vector is zero. + * - if you clone (src_x, src_y)x(w, h) the vector is (src_x, src_y); */ cairo_warn cairo_status_t (*clone_similar) (void *surface, @@ -570,6 +583,8 @@ struct _cairo_surface_backend { int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out); /* XXX: dst should be the first argument for consistency */ @@ -799,7 +814,7 @@ struct _cairo_surface_backend { int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font); }; @@ -825,24 +840,6 @@ struct _cairo_image_surface { extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend; -/* XXX: Right now, the _cairo_color structure puts unpremultiplied - color in the doubles and premultiplied color in the shorts. Yes, - this is crazy insane, (but at least we don't export this - madness). I'm still working on a cleaner API, but in the meantime, - at least this does prevent precision loss in color when changing - alpha. */ -struct _cairo_color { - double red; - double green; - double blue; - double alpha; - - unsigned short red_short; - unsigned short green_short; - unsigned short blue_short; - unsigned short alpha_short; -}; - #define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD @@ -966,8 +963,8 @@ typedef struct _cairo_traps { #else -/* Paranoia: this should have been caught by configure. */ -#error No font backends are available. +#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT +#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_user_scaled_font_backend #endif @@ -1249,16 +1246,16 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate, cairo_font_face_t *font_face); cairo_private cairo_status_t -_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_bool_t *backward); +_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, + double x, + double y, + const char *utf8, + int utf8_len, + cairo_glyph_t **glyphs, + int *num_glyphs, + cairo_text_cluster_t **clusters, + int *num_clusters, + cairo_text_cluster_flags_t *cluster_flags); cairo_private cairo_status_t _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, @@ -1266,9 +1263,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, int num_glyphs, cairo_text_extents_t *extents); -cairo_private cairo_bool_t -_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate); - cairo_private cairo_status_t _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, const char *utf8, @@ -1277,7 +1271,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward); + cairo_text_cluster_flags_t cluster_flags); cairo_private cairo_status_t _cairo_gstate_glyph_path (cairo_gstate_t *gstate, @@ -1358,6 +1352,17 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *font); cairo_private void _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font); +/* cairo-font-face-twin.c */ + +cairo_private cairo_font_face_t * +_cairo_font_face_twin_create (cairo_font_slant_t slant, + cairo_font_weight_t weight); + +/* cairo-font-face-twin-data.c */ + +extern const cairo_private int8_t _cairo_twin_outlines[]; +extern const cairo_private uint16_t _cairo_twin_charmap[128]; + /* cairo-font-options.c */ cairo_private void @@ -1383,7 +1388,7 @@ _cairo_validate_text_clusters (const char *utf8, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward); + cairo_text_cluster_flags_t cluster_flags); /* cairo-path-fixed.c */ cairo_private void @@ -1547,7 +1552,7 @@ _cairo_scaled_font_create_in_error (cairo_status_t status); cairo_private void _cairo_scaled_font_reset_static_data (void); -cairo_private void +cairo_private cairo_status_t _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font); cairo_private void @@ -1565,6 +1570,7 @@ cairo_private cairo_status_t _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *fs_metrics); +/* This should only be called on an error path by a scaled_font constructor */ cairo_private void _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font); @@ -1788,7 +1794,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font); cairo_private cairo_status_t @@ -1836,6 +1842,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out); cairo_private cairo_surface_t * @@ -1997,7 +2005,7 @@ cairo_private cairo_surface_t * _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, pixman_format_code_t pixman_format); -cairo_private cairo_int_status_t +cairo_private cairo_bool_t _pixman_format_from_masks (cairo_format_masks_t *masks, pixman_format_code_t *format_ret); @@ -2109,21 +2117,19 @@ _cairo_polygon_init (cairo_polygon_t *polygon); cairo_private void _cairo_polygon_fini (cairo_polygon_t *polygon); -cairo_private cairo_status_t -_cairo_polygon_status (cairo_polygon_t *polygon); +cairo_private void +_cairo_polygon_move_to (cairo_polygon_t *polygon, + const cairo_point_t *point); cairo_private void -_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2); - -cairo_private void -_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point); - -cairo_private void -_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point); +_cairo_polygon_line_to (cairo_polygon_t *polygon, + const cairo_point_t *point); cairo_private void _cairo_polygon_close (cairo_polygon_t *polygon); +#define _cairo_polygon_status(P) (P)->status + /* cairo-spline.c */ cairo_private cairo_int_status_t _cairo_spline_init (cairo_spline_t *spline, @@ -2176,6 +2182,9 @@ cairo_private cairo_bool_t _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix, int *itx, int *ity); +cairo_private cairo_bool_t +_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix); + cairo_private double _cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius); @@ -2195,29 +2204,38 @@ cairo_private cairo_bool_t _cairo_traps_get_limit (cairo_traps_t *traps, cairo_box_t *limits); -cairo_private cairo_status_t +cairo_private void _cairo_traps_init_box (cairo_traps_t *traps, - cairo_box_t *box); + const cairo_box_t *box); + +cairo_private void +_cairo_traps_clear (cairo_traps_t *traps); cairo_private void _cairo_traps_fini (cairo_traps_t *traps); -cairo_private cairo_status_t -_cairo_traps_status (cairo_traps_t *traps); +#define _cairo_traps_status(T) (T)->status cairo_private void _cairo_traps_translate (cairo_traps_t *traps, int x, int y); cairo_private cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]); +_cairo_traps_tessellate_triangle (cairo_traps_t *traps, + const cairo_point_t t[3]); cairo_private cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]); +_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, + const cairo_point_t q[4]); + +cairo_private cairo_status_t +_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, + const cairo_point_t *top_left, + const cairo_point_t *bottom_right); cairo_private void -_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_point_t left_p1, cairo_point_t left_p2, - cairo_point_t right_p1, cairo_point_t right_p2); +_cairo_traps_add_trap (cairo_traps_t *traps, + cairo_fixed_t top, cairo_fixed_t bottom, + cairo_line_t *left, cairo_line_t *right); cairo_private cairo_status_t _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, @@ -2249,10 +2267,12 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, /* cairo-slope.c */ cairo_private void -_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b); +_cairo_slope_init (cairo_slope_t *slope, + const cairo_point_t *a, + const cairo_point_t *b); cairo_private int -_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b); +_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b); /* cairo-pattern.c */ @@ -2264,6 +2284,10 @@ cairo_private cairo_status_t _cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other); +cairo_private cairo_status_t +_cairo_pattern_init_snapshot (cairo_pattern_t *pattern, + const cairo_pattern_t *other); + cairo_private void _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, const cairo_color_t *color, @@ -2363,7 +2387,7 @@ cairo_private int _cairo_ucs4_to_utf8 (uint32_t unicode, char *utf8); -#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0 || CAIRO_HAS_PDF_SURFACE+0 +#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS # define CAIRO_HAS_UTF8_TO_UTF16 1 #endif #if CAIRO_HAS_UTF8_TO_UTF16 @@ -2374,6 +2398,9 @@ _cairo_utf8_to_utf16 (const char *str, int *items_written); #endif +#define _cairo_status_is_error(status) \ + (status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS) + cairo_private cairo_status_t _cairo_error (cairo_status_t status); @@ -2391,21 +2418,22 @@ slim_hidden_proto (cairo_curve_to); slim_hidden_proto (cairo_destroy); slim_hidden_proto (cairo_fill_preserve); slim_hidden_proto (cairo_font_face_destroy); +slim_hidden_proto (cairo_font_face_get_user_data); slim_hidden_proto_no_warn (cairo_font_face_reference); +slim_hidden_proto (cairo_font_face_set_user_data); slim_hidden_proto (cairo_font_options_equal); slim_hidden_proto (cairo_font_options_hash); slim_hidden_proto (cairo_font_options_merge); slim_hidden_proto (cairo_font_options_set_antialias); slim_hidden_proto (cairo_font_options_set_hint_metrics); slim_hidden_proto (cairo_font_options_set_hint_style); -slim_hidden_proto (cairo_font_options_set_lcd_filter); slim_hidden_proto (cairo_font_options_set_subpixel_order); slim_hidden_proto (cairo_font_options_status); slim_hidden_proto (cairo_get_current_point); +slim_hidden_proto (cairo_get_line_width); slim_hidden_proto (cairo_get_matrix); slim_hidden_proto (cairo_get_target); slim_hidden_proto (cairo_get_tolerance); -slim_hidden_proto (cairo_has_show_text_glyphs); slim_hidden_proto (cairo_glyph_allocate); slim_hidden_proto (cairo_glyph_free); slim_hidden_proto (cairo_image_surface_create); @@ -2462,12 +2490,16 @@ slim_hidden_proto_no_warn (cairo_scaled_font_reference); slim_hidden_proto (cairo_scaled_font_status); slim_hidden_proto (cairo_set_font_size); slim_hidden_proto (cairo_set_font_options); +slim_hidden_proto (cairo_set_line_cap); +slim_hidden_proto (cairo_set_line_join); +slim_hidden_proto (cairo_set_line_width); slim_hidden_proto (cairo_set_matrix); slim_hidden_proto (cairo_set_operator); slim_hidden_proto (cairo_set_source); slim_hidden_proto (cairo_set_source); slim_hidden_proto (cairo_set_source_surface); slim_hidden_proto (cairo_status); +slim_hidden_proto (cairo_stroke); slim_hidden_proto (cairo_stroke_preserve); slim_hidden_proto (cairo_surface_create_similar); slim_hidden_proto (cairo_surface_destroy); @@ -2488,6 +2520,12 @@ slim_hidden_proto (cairo_surface_status); slim_hidden_proto (cairo_text_cluster_allocate); slim_hidden_proto (cairo_text_cluster_free); slim_hidden_proto (cairo_toy_font_face_create); +slim_hidden_proto (cairo_toy_font_face_get_slant); +slim_hidden_proto (cairo_toy_font_face_get_weight); +slim_hidden_proto (cairo_user_font_face_create); +slim_hidden_proto (cairo_user_font_face_set_init_func); +slim_hidden_proto (cairo_user_font_face_set_render_glyph_func); +slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func); slim_hidden_proto (cairo_version_string); #if CAIRO_HAS_PNG_FUNCTIONS diff --git a/gfx/cairo/cairo/src/test-fallback-surface.c b/gfx/cairo/cairo/src/test-fallback-surface.c index e720e88ec228..883941df014a 100644 --- a/gfx/cairo/cairo/src/test-fallback-surface.c +++ b/gfx/cairo/cairo/src/test-fallback-surface.c @@ -176,11 +176,15 @@ _test_fallback_surface_clone_similar (void *abstract_surface, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { test_fallback_surface_t *surface = abstract_surface; if (src->backend == surface->base.backend) { + *clone_offset_x = 0; + *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; diff --git a/gfx/cairo/cairo/src/test-meta-surface.c b/gfx/cairo/cairo/src/test-meta-surface.c index 4d56e1b76556..6038430cf6fa 100644 --- a/gfx/cairo/cairo/src/test-meta-surface.c +++ b/gfx/cairo/cairo/src/test-meta-surface.c @@ -273,34 +273,18 @@ _test_meta_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { test_meta_surface_t *surface = abstract_surface; - cairo_int_status_t status; surface->image_reflects_meta = FALSE; - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_text_glyphs from within a call to the same. - * Since _cairo_surface_show_text_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - status = _cairo_surface_show_text_glyphs (surface->meta, op, source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - backward, - scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); - - return status; + return _cairo_surface_show_text_glyphs (surface->meta, op, source, + utf8, utf8_len, + glyphs, num_glyphs, + clusters, num_clusters, cluster_flags, + scaled_font); } @@ -308,43 +292,8 @@ static cairo_surface_t * _test_meta_surface_snapshot (void *abstract_other) { test_meta_surface_t *other = abstract_other; - cairo_status_t status; - /* XXX: Just making a snapshot of other->meta is what we really - * want. But this currently triggers a bug somewhere (the "mask" - * test from the test suite segfaults). - * - * For now, we'll create a new image surface and replay onto - * that. It would be tempting to replay into other->image and then - * return a snapshot of that, but that will cause the self-copy - * test to fail, (since our replay will be affected by a clip that - * should not have any effect on the use of the resulting snapshot - * as a source). - */ - -#if 0 return _cairo_surface_snapshot (other->meta); -#else - cairo_rectangle_int_t extents; - cairo_surface_t *surface; - - status = _cairo_surface_get_extents (other->image, &extents); - if (status) - return _cairo_surface_create_in_error (status); - - surface = cairo_surface_create_similar (other->image, - CAIRO_CONTENT_COLOR_ALPHA, - extents.width, - extents.height); - - status = _cairo_meta_surface_replay (other->meta, surface); - if (status) { - cairo_surface_destroy (surface); - surface = _cairo_surface_create_in_error (status); - } - - return surface; -#endif } static const cairo_surface_backend_t test_meta_surface_backend = { diff --git a/gfx/cairo/cairo/src/test-paginated-surface.c b/gfx/cairo/cairo/src/test-paginated-surface.c index 5d86986c1ac0..354f95d1adf1 100644 --- a/gfx/cairo/cairo/src/test-paginated-surface.c +++ b/gfx/cairo/cairo/src/test-paginated-surface.c @@ -93,14 +93,16 @@ _cairo_test_paginated_surface_create_for_data (unsigned char *data, paginated = _cairo_paginated_surface_create (&surface->base, content, width, height, &test_paginated_surface_paginated_backend); - - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - - if (paginated->status) { - cairo_surface_destroy (target); + status = paginated->status; + if (status == CAIRO_STATUS_SUCCESS) { + /* paginated keeps the only reference to surface now, drop ours */ + cairo_surface_destroy (&surface->base); + return paginated; } - return paginated; + + cairo_surface_destroy (target); + free (surface); + return _cairo_surface_create_in_error (status); } static cairo_status_t @@ -250,35 +252,19 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, - cairo_bool_t backward, + cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font) { test_paginated_surface_t *surface = abstract_surface; - cairo_int_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_text_glyphs from within a call to the same. - * Since _cairo_surface_show_text_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - status = _cairo_surface_show_text_glyphs (surface->target, op, source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - backward, - scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); - - return status; + return _cairo_surface_show_text_glyphs (surface->target, op, source, + utf8, utf8_len, + glyphs, num_glyphs, + clusters, num_clusters, cluster_flags, + scaled_font); } diff --git a/gfx/cairo/nonfatal-assertions.patch b/gfx/cairo/nonfatal-assertions.patch index 1e7363b7c25f..dcbb904abd26 100644 --- a/gfx/cairo/nonfatal-assertions.patch +++ b/gfx/cairo/nonfatal-assertions.patch @@ -1,6 +1,6 @@ diff -r b79d47dad1ea gfx/cairo/cairo/src/cairoint.h ---- a/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700 -+++ b/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200 +--- a/gfx/cairo/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700 ++++ b/gfx/cairo/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200 @@ -159,6 +159,13 @@ CAIRO_BEGIN_DECLS #ifndef M_PI