author | Vladimir Vukicevic <vladimir@pobox.com> |
Wed, 05 Nov 2008 23:48:23 -0800 | |
changeset 21379 | ce976e0708ab4a7fc43cf78fcad0c6b21c8a06ff |
parent 21378 | 69224da04e45b6af348854c3fe0e52ae4bb54815 |
child 21380 | 85f7383ab46f51ba7f8e37083b16ce65dba7ed83 |
push id | unknown |
push user | unknown |
push date | unknown |
bugs | 462938 |
milestone | 1.9.1b2pre |
--- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -2,18 +2,18 @@ Snapshots of cairo and glitz for mozilla We only include the relevant parts of each release (generally, src/*.[ch]), as we have Makefile.in's that integrate into the Mozilla build system. For documentation and similar, please see the official tarballs at 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 ***** VC6 is not supported. Please upgrade to VC8. ==== Patches ==== Some specific things: @@ -23,15 +23,17 @@ max-font-size.patch: Clamp freetype font win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1 nonfatal-assertions.patch: Make assertions non-fatal buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583. 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 ==== disable printing patch ==== disable-printing.patch: allows us to use NS_PRINTING to disable printing.
--- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -80,16 +80,18 @@ CSRCS = \ cairo-bentley-ottmann.c \ cairo-cache.c \ cairo-clip.c \ cairo-color.c \ cairo-debug.c \ 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 \ cairo-hash.c \ cairo-hull.c \ cairo-image-surface.c \ cairo-lzw.c \ cairo-matrix.c \
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h @@ -61,13 +61,16 @@ cairo_private cairo_bool_t cairo_private cairo_bool_t _cairo_analysis_surface_has_unsupported (cairo_surface_t *surface); 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); #endif /* CAIRO_ANALYSIS_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c +++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c @@ -57,19 +57,51 @@ typedef struct { cairo_rectangle_int_t current_clip; cairo_box_t page_bbox; cairo_bool_t has_ctm; cairo_matrix_t ctm; } 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; cairo_status_t status; cairo_bool_t old_has_ctm; cairo_matrix_t old_ctm, p2d; cairo_rectangle_int_t old_clip; cairo_rectangle_int_t meta_extents; @@ -113,19 +145,19 @@ static cairo_int_status_t surface->current_clip = old_clip; surface->width = old_width; surface->height = old_height; return status; } 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; if (rect->width == 0 || rect->height == 0) { /* Even though the operation is not visible we must be careful * to not allow unsupported operations to be replayed to the * backend during CAIRO_PAGINATED_MODE_RENDER */ @@ -297,75 +329,81 @@ static cairo_int_status_t if (!surface->target->backend->paint) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->paint) (surface->target, op, 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) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &source_extents); } _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; } static cairo_int_status_t _cairo_analysis_surface_mask (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, 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) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->mask) (surface->target, op, 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); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; @@ -379,17 +417,17 @@ static cairo_int_status_t if (status) return status; _cairo_rectangle_intersect (&extents, &source_extents); } _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; } static cairo_int_status_t _cairo_analysis_surface_stroke (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, @@ -398,30 +436,28 @@ static cairo_int_status_t cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias) { 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) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->stroke) (surface->target, op, source, path, style, ctm, ctm_inverse, 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) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); @@ -429,78 +465,66 @@ static cairo_int_status_t return status; _cairo_rectangle_intersect (&extents, &source_extents); } _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); status = _cairo_path_fixed_stroke_to_traps (path, style, ctm, ctm_inverse, tolerance, &traps); if (status) { _cairo_traps_fini (&traps); 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; } static cairo_int_status_t _cairo_analysis_surface_fill (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { cairo_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) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->fill) (surface->target, op, source, path, fill_rule, 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) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); @@ -508,49 +532,38 @@ static cairo_int_status_t return status; _cairo_rectangle_intersect (&extents, &source_extents); } _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); status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); if (status) { _cairo_traps_fini (&traps); 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_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; } static cairo_int_status_t _cairo_analysis_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, @@ -577,18 +590,17 @@ static cairo_int_status_t glyphs, num_glyphs, NULL, 0, FALSE, scaled_font); else 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) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); @@ -606,17 +618,17 @@ static cairo_int_status_t num_glyphs, &glyph_extents); if (status) return status; _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; } static cairo_bool_t _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface) { cairo_analysis_surface_t *surface = abstract_surface; @@ -629,49 +641,47 @@ static cairo_int_status_t cairo_operator_t op, cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, 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; cairo_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; /* Adapted from _cairo_surface_show_glyphs */ backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (surface->target->backend->show_text_glyphs) backend_status = surface->target->backend->show_text_glyphs (surface->target, op, 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; backend_status = surface->target->backend->show_glyphs (surface->target, op, source, glyphs, num_glyphs, scaled_font, &remaining_glyphs); glyphs += num_glyphs - remaining_glyphs; num_glyphs = remaining_glyphs; if (remaining_glyphs == 0) backend_status = CAIRO_STATUS_SUCCESS; } 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) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); @@ -689,17 +699,17 @@ static cairo_int_status_t num_glyphs, &glyph_extents); if (status) return status; _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; } static const cairo_surface_backend_t cairo_analysis_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, NULL, /* create_similar */ _cairo_analysis_surface_finish, @@ -737,16 +747,21 @@ static const cairo_surface_backend_t cai }; cairo_surface_t * _cairo_analysis_surface_create (cairo_surface_t *target, int width, 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) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); /* I believe the content type here is truly arbitrary. I'm quite * sure nothing will ever use this value. */ _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend, @@ -780,27 +795,32 @@ cairo_surface_t * surface->current_clip.y = 0; surface->current_clip.width = width; surface->current_clip.height = height; } 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) { cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; *ctm = surface->ctm; }
--- a/gfx/cairo/cairo/src/cairo-array.c +++ b/gfx/cairo/cairo/src/cairo-array.c @@ -80,16 +80,17 @@ void array->element_size = other->element_size; array->elements = other->elements; array->is_snapshot = TRUE; } /** * _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 * _cairo_array_init() again first. **/ void _cairo_array_fini (cairo_array_t *array) { @@ -99,16 +100,17 @@ void if (array->elements) { free (* array->elements); free (array->elements); } } /** * _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 * is always increased by doubling as many times as necessary. **/ cairo_status_t _cairo_array_grow_by (cairo_array_t *array, unsigned int additional) { @@ -153,48 +155,52 @@ cairo_status_t *array->elements = new_elements; return CAIRO_STATUS_SUCCESS; } /** * _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 * beyond @num_elements are simply "forgotten". **/ void _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) { assert (! array->is_snapshot); if (num_elements < array->num_elements) array->num_elements = 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; + * <informalexample><programlisting> + * cairo_array_t array; * double *values; * * _cairo_array_init (&array, sizeof(double)); * ... calls to _cairo_array_append() here ... * * values = _cairo_array_index (&array, 0); * for (i = 0; i < _cairo_array_num_elements (&array); i++) * ... use values[i] here ... + * </programlisting></informalexample> **/ void * _cairo_array_index (cairo_array_t *array, unsigned int index) { /* We allow an index of 0 for the no-elements case. * This makes for cleaner calling code which will often look like: * * elements = _cairo_array_index (array, num_elements); @@ -210,28 +216,30 @@ void * assert (index < array->num_elements); return (void *) &(*array->elements)[index * array->element_size]; } /** * _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. **/ void _cairo_array_copy_element (cairo_array_t *array, int index, void *dst) { memcpy (dst, _cairo_array_index (array, index), array->element_size); } /** * _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 * into the array. The address of the resulting object within the * array can be determined with: * * _cairo_array_index (array, _cairo_array_num_elements (array) - 1); * @@ -245,16 +253,17 @@ cairo_status_t { assert (! array->is_snapshot); return _cairo_array_append_multiple (array, element, 1); } /** * _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 * @elements into the array. * * Return value: %CAIRO_STATUS_SUCCESS if successful or * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the * operation. @@ -275,16 +284,17 @@ cairo_status_t memcpy (dest, elements, num_elements * array->element_size); return CAIRO_STATUS_SUCCESS; } /** * _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 * @elements. This memory will be unitialized, but will be accounted * for in the return value of _cairo_array_num_elements(). * * Return value: %CAIRO_STATUS_SUCCESS if successful or * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the @@ -309,30 +319,34 @@ cairo_status_t array->num_elements += num_elements; return CAIRO_STATUS_SUCCESS; } /** * _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) { return array->num_elements; } /** * _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) { return array->size; } /* #cairo_user_data_array_t */
--- a/gfx/cairo/cairo/src/cairo-atomic-private.h +++ b/gfx/cairo/cairo/src/cairo-atomic-private.h @@ -32,53 +32,54 @@ * * Contributor(s): * Chris Wilson <chris@chris-wilson.co.uk> */ #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; # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1)) # 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; cairo_private void _cairo_atomic_int_inc (int *x); cairo_private cairo_bool_t _cairo_atomic_int_dec_and_test (int *x); cairo_private int _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" cairo_private int _cairo_atomic_int_get (int *x); cairo_private void _cairo_atomic_int_set (int *x, int value);
--- a/gfx/cairo/cairo/src/cairo-atomic.c +++ b/gfx/cairo/cairo/src/cairo-atomic.c @@ -31,17 +31,17 @@ * Chris Wilson <chris@chris-wilson.co.uk> */ #include "cairoint.h" #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) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x += 1; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); } @@ -68,17 +68,17 @@ int *x = newv; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; } #endif -#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER +#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER int _cairo_atomic_int_get (int *x) { int ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c +++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c @@ -34,16 +34,19 @@ */ /* Provide definitions for standalone compilation */ #include "cairoint.h" #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 { cairo_int128_t x; cairo_int128_t y; } cairo_bo_point128_t; typedef struct _cairo_bo_intersect_ordinate { @@ -193,79 +196,180 @@ static int int32_t adx = a->bottom.x - a->top.x; int32_t bdx = b->bottom.x - b->top.x; /* Since the dy's are all positive by construction we can fast * path the case where the two edges point in different directions * 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; + + adx = a->bottom.x - a->top.x; + ady = a->bottom.y - a->top.y; + + bdx = b->bottom.x - b->top.x; + bdy = b->bottom.y - b->top.y; + + 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; +} - if (edge->middle.y == y) { - quorem.quo = edge->middle.x; - quorem.rem = 0; - return quorem; +/* + * 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; } - 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; - } - - /* 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; - - return quorem; } static int _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) return 0; /* don't bother solving for abscissa if the edges' bounding boxes * can be used to order them. */ { @@ -284,28 +388,19 @@ static int } else { bmin = b->bottom.x; bmax = b->middle.x; } if (amax < bmin) return -1; 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 * called only when starting a new edge, (not when stopping an * edge), so we don't have to worry about conditionally inverting * the sense of _slope_compare. */ cmp = _slope_compare (a, b); if (cmp) @@ -484,27 +579,27 @@ det32_64 (int32_t a, /* det = a * d - b * c */ ad = _cairo_int32x32_64_mul (a, d); bc = _cairo_int32x32_64_mul (b, c); return _cairo_int64_sub (ad, bc); } 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); } /* Compute the intersection of two lines as defined by two edges. The * result is provided as a coordinate pair of 128-bit integers. * * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or @@ -527,41 +622,41 @@ intersect_lines (cairo_bo_edge_t *a, int32_t dy1 = a->top.y - a->bottom.y; int32_t dx2 = b->top.x - b->bottom.x; int32_t dy2 = b->top.y - b->bottom.y; 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, a->bottom.x, a->bottom.y); b_det = det32_64 (b->top.x, b->top.y, 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; } static int _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a, int32_t b) { @@ -936,17 +1031,16 @@ static void left->next = right->next; right->next = left; right->prev = left->prev; left->prev = right; } -#define DEBUG_PRINT_STATE 0 #if DEBUG_PRINT_STATE static void _cairo_bo_edge_print (cairo_bo_edge_t *edge) { printf ("(0x%x, 0x%x)-(0x%x, 0x%x)", edge->top.x, edge->top.y, edge->bottom.x, edge->bottom.y); } @@ -1073,45 +1167,45 @@ static cairo_status_t if (right->bottom.y < bot) bot = right->bottom.y; fixed_top = trap->top; fixed_bot = bot; /* 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) " "right=(%08x,%08x)-(%08x,%08x) top=%08x, bot=%08x\n", left->top.x, left->top.y, left->bottom.x, left->bottom.y, right->top.x, right->top.y, right->bottom.x, right->bottom.y, trap->top, bot); #endif @@ -1172,41 +1266,43 @@ static void } static void _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) { cairo_bo_edge_t *edge; skip_elt_t *elt; /* March through both the skip list's singly-linked list and the * sweep line's own list through pointers in the edges themselves * and make sure they agree at every point. */ for (edge = sweep_line->head, elt = sweep_line->active_edges.chains[0]; edge && elt; edge = edge->next, elt = elt->next[0]) { 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 _active_edges_to_traps (cairo_bo_edge_t *head, int32_t top, cairo_fill_rule_t fill_rule, cairo_bo_traps_t *bo_traps) { @@ -1319,19 +1415,18 @@ static cairo_status_t status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right); if (status) goto unwind; #if DEBUG_PRINT_STATE print_state ("After processing start", &event_queue, &sweep_line); #endif - _cairo_bo_sweep_line_validate (&sweep_line); + break; - break; case CAIRO_BO_EVENT_TYPE_STOP: edge = event->e1; left = edge->prev; right = edge->next; _cairo_bo_sweep_line_delete (&sweep_line, edge); @@ -1341,19 +1436,18 @@ static cairo_status_t status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right); if (status) goto unwind; #if DEBUG_PRINT_STATE print_state ("After processing stop", &event_queue, &sweep_line); #endif - _cairo_bo_sweep_line_validate (&sweep_line); + break; - break; case CAIRO_BO_EVENT_TYPE_INTERSECTION: edge1 = event->e1; edge2 = event->e2; /* skip this intersection if its edges are not adjacent */ if (edge2 != edge1->next) break; @@ -1377,20 +1471,21 @@ static cairo_status_t status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge1, right); if (status) goto unwind; #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; unwind: for (edge = sweep_line.head; edge; edge = edge->next) { cairo_status_t status2 = _cairo_bo_edge_end_trap (edge, sweep_line.current_y, &bo_traps); @@ -1422,22 +1517,26 @@ cairo_status_t int intersections; cairo_status_t status; cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)]; cairo_bo_edge_t *edges; cairo_fixed_t xmin = 0x7FFFFFFF; 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 { edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t)); if (edges == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -1466,16 +1565,23 @@ cairo_status_t if (ymax - ymin < 0) ymax = ymin + 0x7FFFFFFF; for (i = 0, num_bo_edges = 0; i < polygon->num_edges; i++) { cairo_bo_edge_t *edge = &edges[num_bo_edges]; 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; bot.x -= xmin; bot.y -= ymin; /* If the coordinates are still negative, then their extent is * overflowing 2^31-1. We're going to kludge it and clamp the
--- a/gfx/cairo/cairo/src/cairo-cache.c +++ b/gfx/cairo/cairo/src/cairo-cache.c @@ -87,16 +87,17 @@ static void cache->size = 0; } /** * _cairo_cache_create: * @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. * * Data is provided to the cache in the form of user-derived version * of #cairo_cache_entry_t. A cache entry must be able to hold hash * code, a size, and the key/value pair being stored in the * cache. Sometimes only the key will be necessary, (as in @@ -114,18 +115,16 @@ static void * undesired. If the cache entries have reference counts, then it is a * simple matter to use the reference counts to ensure that entries * continue to live even after being ejected from the cache. However, * in some cases the memory overhead of adding a reference count to * the entry would be objectionable. In such cases, the * _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, cairo_destroy_func_t entry_destroy, unsigned long max_size) { cairo_status_t status; cairo_cache_t *cache;
--- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -143,33 +143,36 @@ static cairo_status_t cairo_rectangle_int_t *rectangle) { while (clip_path) { cairo_status_t status; cairo_traps_t traps; 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, clip_path->tolerance, &traps); if (status) { _cairo_traps_fini (&traps); return status; } _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; } return CAIRO_STATUS_SUCCESS; } cairo_status_t _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, @@ -431,19 +434,18 @@ static cairo_status_t _cairo_traps_extents (traps, &extents); _cairo_box_round_to_rectangle (&extents, &surface_rect); if (clip->surface != NULL) _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect); /* 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) { surface = NULL; status = CAIRO_STATUS_SUCCESS; if (clip->surface != NULL) cairo_surface_destroy (clip->surface); goto DONE; @@ -556,16 +558,17 @@ cairo_status_t _cairo_clip_clip (cairo_clip_t *clip, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, cairo_surface_t *target) { cairo_status_t status; + cairo_rectangle_int_t rectangle; cairo_traps_t traps; if (clip->all_clipped) return CAIRO_STATUS_SUCCESS; /* catch the empty clip path */ if (! path->has_current_point) { _cairo_clip_set_all_clipped (clip, target); @@ -577,16 +580,27 @@ cairo_status_t antialias); if (status == CAIRO_STATUS_SUCCESS) clip->serial = _cairo_surface_allocate_clip_serial (target); if (status != CAIRO_INT_STATUS_UNSUPPORTED) 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, &traps); if (status) goto bail; status = _cairo_clip_intersect_region (clip, &traps, target); @@ -671,26 +685,32 @@ cairo_status_t status = _cairo_region_copy (&clip->region, &other->region); if (status) goto BAIL; clip->has_region = TRUE; } 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) { status = _cairo_clip_path_reapply_clip_path (clip, other->path); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) goto BAIL; } }
--- a/gfx/cairo/cairo/src/cairo-color.c +++ b/gfx/cairo/cairo/src/cairo-color.c @@ -160,13 +160,16 @@ void *blue = color->blue * color->alpha; *alpha = color->alpha; } 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 && color_a->alpha_short == color_b->alpha_short; }
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h +++ b/gfx/cairo/cairo/src/cairo-compiler-private.h @@ -33,16 +33,18 @@ * * Contributor(s): * Carl D. Worth <cworth@cworth.org> */ #ifndef CAIRO_COMPILER_PRIVATE_H #define CAIRO_COMPILER_PRIVATE_H +#include "cairo.h" + #if HAVE_CONFIG_H #include "config.h" #endif #if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) # define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private # define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn # define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name)) @@ -104,23 +106,52 @@ # define CAIRO_FUNCTION_ALIAS(old, new) \ extern __typeof (new) old \ __asm__ ("" #old) \ __attribute__((__alias__("" #new))) #else # 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) #endif #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) #define snprintf _snprintf +#define popen _popen #endif #ifdef _MSC_VER #undef inline #define inline __inline #endif #ifdef __STRICT_ANSI__
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c @@ -29,109 +29,103 @@ * * The Initial Developer of the Original Code is University of Southern * California. * * Contributor(s): * Michael Emmel <mike.emmel@gmail.com> * Claudio Ciccani <klan@users.sf.net> */ - #include "cairoint.h" #include "cairo-directfb.h" -#include <stdlib.h> - #include <directfb.h> #include <direct/types.h> #include <direct/debug.h> #include <direct/memcpy.h> #include <direct/util.h> +#include "cairo-clip-private.h" /* * Rectangle works fine. * Bugs 361377, 359553, 359243 in Gnome BTS are caused * by GDK/DirectFB, not by Cairo/DirectFB. */ #define DFB_RECTANGLES 1 /* * Composite works fine. */ -#define DFB_COMPOSITE 1 +#define DFB_COMPOSITE 1 /* * CompositeTrapezoids works (without antialiasing). */ #define DFB_COMPOSITE_TRAPEZOIDS 1 /* * ShowGlyphs works fine. */ #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; /*****************************************************************************/ 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) {\ DFBRegion reg = (surface)->clips[k];\ DFBRegion *cli = (clip);\ if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\ reg.x1 > cli->x2 || reg.y1 > cli->y2)\ continue;\ @@ -139,909 +133,957 @@ static int _directfb_argb_font = 0; reg.x1 = cli->x1;\ if (reg.y1 < cli->y1)\ reg.y1 = cli->y1;\ if (reg.x2 > cli->x2)\ reg.x2 = cli->x2;\ 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);\ (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\ } /* XXX: A1 has a different bits ordering in cairo. * 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; } 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; 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) { int w, h; surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h); if (w < source_rect.w || h < source_rect.h) { surface->tmpsurface->Release (surface->tmpsurface); 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) { image_rect_out->x = source_rect.x; image_rect_out->y = source_rect.y; image_rect_out->width = source_rect.w; 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, int width, int height) { 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; } 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; } if (surface->dfbsurface) { surface->dfbsurface->Release (surface->dfbsurface); surface->dfbsurface = NULL; } - + if (surface->dfb) surface->dfb = NULL; - + return CAIRO_STATUS_SUCCESS; } static cairo_status_t _cairo_directfb_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, 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 _cairo_directfb_surface_release_source_image (void *abstract_surface, 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); } static cairo_status_t _cairo_directfb_surface_acquire_dest_image (void *abstract_surface, cairo_rectangle_int_t *interest_rect, cairo_image_surface_t **image_out, cairo_rectangle_int_t *image_rect_out, 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 _cairo_directfb_surface_release_dest_image (void *abstract_surface, cairo_rectangle_int_t *interest_rect, cairo_image_surface_t *image, cairo_rectangle_int_t *image_rect, 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); } static cairo_status_t _cairo_directfb_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, int src_x, int src_y, int width, int height, + 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); + + 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); + } - 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; + 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; } #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS static cairo_int_status_t _directfb_prepare_composite (cairo_directfb_surface_t *dst, cairo_pattern_t *src_pattern, cairo_pattern_t *mask_pattern, cairo_operator_t op, 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; - + /* 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 (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); + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } - - if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) - dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); - + + 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; } static void _directfb_finish_composite (cairo_directfb_surface_t *dst, cairo_pattern_t *src_pattern, 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; } - - if (src_attr->extend != CAIRO_EXTEND_NONE && - src_attr->extend != CAIRO_EXTEND_REPEAT) - return DFXL_NONE; - - return DFXL_BLIT; + + 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; + } } static cairo_int_status_t _cairo_directfb_surface_composite (cairo_operator_t op, cairo_pattern_t *src_pattern, cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height) { cairo_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"); + 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; - - 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; + 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 */ #if DFB_RECTANGLES static cairo_int_status_t _cairo_directfb_surface_fill_rectangles (void *abstract_surface, cairo_operator_t op, const cairo_color_t *color, @@ -1049,316 +1091,320 @@ static cairo_int_status_t int n_rects) { cairo_directfb_surface_t *dst = abstract_surface; DFBSurfaceDrawingFlags flags; DFBSurfaceBlendFunction sblend; 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 ); - + 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; + 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 #if DFB_COMPOSITE_TRAPEZOIDS static cairo_int_status_t _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, void *abstract_dst, cairo_antialias_t antialias, int src_x, int src_y, int dst_x, int dst_y, 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," " width=%u, height=%u, traps=%p, num_traps=%d ).\n", __FUNCTION__, op, pattern, dst, antialias, src_x, src_y, dst_x, dst_y, width, height, traps, num_traps); 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 */ static cairo_int_status_t _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; + + surface->has_clip = TRUE; + + 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); - 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->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; + } - _cairo_region_boxes_fini (region, boxes); - } - else { - if (surface->clips) { - free (surface->clips); - surface->clips = NULL; - surface->n_clips = 0; - } + 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; } static cairo_int_status_t _cairo_directfb_abstract_surface_get_extents (void *abstract_surface, 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 _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache) { cache->dfbsurface->Release (cache->dfbsurface); free (cache); } @@ -1366,374 +1412,400 @@ static void static cairo_status_t _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, 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 ); + _cairo_cache_freeze (scaled_font->glyphs); + if (scaled_font->surface_private) { - cache = scaled_font->surface_private; - x = cache->x; - y = cache->y; + cache = scaled_font->surface_private; + x = cache->x; + y = cache->y; } - _cairo_cache_freeze( scaled_font->glyphs ); - 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; + + D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index ); + + 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; + } - 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 ); + 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 (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++; + 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); - - 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; - } + + /* XXX query maximum surface size */ + if (w > 2048 || h > 2048) { + _cairo_cache_thaw (scaled_font->glyphs); + return CAIRO_INT_STATUS_UNSUPPORTED; } - 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); + + 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); - 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]); + status = _directfb_allocate_font_cache (surface->dfb, + w, h, + &new_cache); + if (status) { + _cairo_cache_thaw (scaled_font->glyphs); + return status; + } - 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); + new_cache->dfbsurface->Blit (new_cache->dfbsurface, + cache->dfbsurface, NULL, 0, 0); - 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); + _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; } - _cairo_cache_thaw( scaled_font->glyphs ); + 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); + + 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]); + + 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); cache->x = x; cache->y = y; - + D_DEBUG_AT (CairoDFB_Font, " => cache %d,%d, %p [%d]\n", x, y, cache, n); *ret_cache = cache; *ret_num = n; return CAIRO_STATUS_SUCCESS; } 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; } } static void _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font) { D_DEBUG_AT (CairoDFB_Font, "%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; } } static cairo_int_status_t _cairo_directfb_surface_show_glyphs (void *abstract_dst, cairo_operator_t op, cairo_pattern_t *pattern, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, int *remaining_glyphs) { 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 */ static cairo_bool_t _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content) { cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a; cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b; 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*/ #else NULL,/*composite*/ #endif #if DFB_RECTANGLES _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/ @@ -1775,83 +1847,86 @@ static cairo_surface_backend_t cairo_dir NULL /* reset */ }; 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; } -
--- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-directfb.h @@ -44,17 +44,17 @@ * if found, enables using ARGB fonts instead of A8 */ #ifndef CAIRO_DIRECTFB_H #define CAIRO_DIRECTFB_H #include "cairo.h" -#ifdef CAIRO_HAS_DIRECTFB_SURFACE +#if CAIRO_HAS_DIRECTFB_SURFACE #include <directfb.h> CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface);
deleted file mode 100644 --- 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 -
new file mode 100644 --- /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, +}; +
new file mode 100644 --- /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 <keithp@keithp.com> + * Behdad Esfahbod <behdad@behdad.org> + */ + +#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; +}
--- a/gfx/cairo/cairo/src/cairo-font-face.c +++ b/gfx/cairo/cairo/src/cairo-font-face.c @@ -277,16 +277,17 @@ cairo_font_face_status (cairo_font_face_ **/ void * cairo_font_face_get_user_data (cairo_font_face_t *font_face, const cairo_user_data_key_t *key) { 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: * @font_face: a #cairo_font_face_t * @key: the address of a #cairo_user_data_key_t to attach the user data to * @user_data: the user data to attach to the font face * @destroy: a #cairo_destroy_func_t which will be called when the * font face is destroyed or when new user data is attached using the @@ -301,21 +302,22 @@ cairo_font_face_get_user_data (cairo_fon **/ cairo_status_t cairo_font_face_set_user_data (cairo_font_face_t *font_face, const cairo_user_data_key_t *key, void *user_data, 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; static int _cairo_toy_font_face_keys_equal (const void *key_a, const void *key_b); /* We maintain a hash table from family/weight/slant => @@ -562,39 +564,89 @@ static void _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry); _cairo_toy_font_face_hash_table_unlock (); _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, const cairo_matrix_t *ctm, const cairo_font_options_t *options, 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) return font_face->base.status; status = cairo_font_options_status ((cairo_font_options_t *) options); 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 _cairo_font_face_is_toy (cairo_font_face_t *font_face) { return font_face->backend == &_cairo_toy_font_face_backend; } @@ -636,16 +688,17 @@ cairo_toy_font_face_get_slant (cairo_fon { cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face; if (! _cairo_font_face_is_toy (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return CAIRO_FONT_SLANT_DEFAULT; } return toy_font_face->slant; } +slim_hidden_def (cairo_toy_font_face_get_slant); /** * cairo_toy_font_face_get_weight: * @font_face: A toy font face * * Gets the weight a toy font. * * Return value: The weight value @@ -657,20 +710,22 @@ cairo_toy_font_face_get_weight (cairo_fo { cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face; if (! _cairo_font_face_is_toy (font_face)) { if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) return CAIRO_FONT_WEIGHT_DEFAULT; } 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 }; void _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font, const cairo_unscaled_font_backend_t *backend) { CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
--- a/gfx/cairo/cairo/src/cairo-font-options.c +++ b/gfx/cairo/cairo/src/cairo-font-options.c @@ -34,44 +34,41 @@ * Owen Taylor <otaylor@redhat.com> */ #include "cairoint.h" 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 }; /** * _cairo_font_options_init_default: * @options: a #cairo_font_options_t * * Initializes all fields of the font options object to default values. **/ void _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; } void _cairo_font_options_init_copy (cairo_font_options_t *options, const cairo_font_options_t *other) { 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; } /** * cairo_font_options_create: * * Allocates a new font options object with all options initialized @@ -187,18 +184,16 @@ cairo_font_options_merge (cairo_font_opt if (cairo_font_options_status ((cairo_font_options_t *) other)) return; if (other->antialias != CAIRO_ANTIALIAS_DEFAULT) 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) options->hint_metrics = other->hint_metrics; } slim_hidden_def (cairo_font_options_merge); /** @@ -221,17 +216,16 @@ cairo_font_options_equal (const cairo_fo if (cairo_font_options_status ((cairo_font_options_t *) other)) return FALSE; if (options == other) return TRUE; 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); } slim_hidden_def (cairo_font_options_equal); /** * cairo_font_options_hash: * @options: a #cairo_font_options_t @@ -247,18 +241,17 @@ slim_hidden_def (cairo_font_options_equa unsigned long cairo_font_options_hash (const cairo_font_options_t *options) { if (cairo_font_options_status ((cairo_font_options_t *) options)) options = &_cairo_font_options_nil; /* force default values */ 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); /** * cairo_font_options_set_antialias: * @options: a #cairo_font_options_t * @antialias: the new antialiasing mode @@ -330,59 +323,16 @@ cairo_font_options_get_subpixel_order (c { if (cairo_font_options_status ((cairo_font_options_t *) options)) return CAIRO_SUBPIXEL_ORDER_DEFAULT; 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 * @hint_style: the new hint style * * Sets the hint style for font outlines for the font options object. * This controls whether to fit font outlines to the pixel grid, * and if so, whether to optimize for fidelity or contrast. * See the documentation for #cairo_hint_style_t for full details.
--- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -52,40 +52,16 @@ #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_IMAGE_H #include FT_TRUETYPE_TABLES_H #if HAVE_FT_GLYPHSLOT_EMBOLDEN #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)) #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) /* This is the max number of FT_face objects we keep open at once */ #define MAX_OPEN_FACES 10 @@ -762,309 +738,46 @@ static cairo_status_t unscaled->face->available_sizes[best_i].height); if (error) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } 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 */ static cairo_status_t _get_bitmap_surface (FT_Bitmap *bitmap, cairo_bool_t own_buffer, cairo_font_options_t *font_options, cairo_image_surface_t **surface) { 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; if (width == 0 || height == 0) { *surface = (cairo_image_surface_t *) cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); return (*surface)->base.status; @@ -1111,63 +824,154 @@ static cairo_status_t } #endif format = CAIRO_FORMAT_A1; break; 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; } else { data = _cairo_malloc_ab (height, stride); if (!data) return _cairo_error (CAIRO_STATUS_NO_MEMORY); 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); - - data = bitmap->buffer; + 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; + + 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: case FT_PIXEL_MODE_GRAY4: /* These could be triggered by very rare types of TrueType fonts */ default: if (own_buffer) free (bitmap->buffer); 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); - - _cairo_image_surface_assume_ownership_of_data (image); + if (subpixel) + pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); + + _cairo_image_surface_assume_ownership_of_data ((*surface)); return CAIRO_STATUS_SUCCESS; } /* Converts an outline FT_GlyphSlot into an image * * This could go through _render_glyph_bitmap as well, letting * FreeType convert the outline to a bitmap, but doing it ourselves @@ -1182,173 +986,129 @@ static cairo_status_t * when we add subpixel support. If so, we may want to eliminate * this version of the code path entirely. */ static cairo_status_t _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); cbox.xMin &= -64; cbox.yMin &= -64; cbox.xMax = (cbox.xMax + 63) & -64; cbox.yMax = (cbox.yMax + 63) & -64; 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; } (*surface) = (cairo_image_surface_t *) cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); if ((*surface)->base.status) return (*surface)->base.status; } else { - int bitmap_size; - - 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; - } + matrix.xx = matrix.yy = 0x10000L; + matrix.xy = matrix.yx = 0; + + 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 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: + 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; + } + 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)); - - /* Note: - * _get_bitmap_surface will free bitmap.buffer if there is an error - */ + 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); + } + 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; } /* Converts a bitmap (or other) FT_GlyphSlot into an image */ static cairo_status_t _render_glyph_bitmap (FT_Face face, cairo_font_options_t *font_options, cairo_image_surface_t **surface) @@ -1557,17 +1317,16 @@ static void /* disable antialiasing if requested */ if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch) antialias = FcTrue; if (antialias) { cairo_subpixel_order_t subpixel_order; - int lcd_filter; /* disable hinting if requested */ if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch) hinting = FcTrue; if (FcPatternGetInteger (pattern, FC_RGBA, 0, &rgba) != FcResultMatch) @@ -1593,35 +1352,16 @@ static void break; } if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) { ft_options.base.subpixel_order = subpixel_order; 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) hintstyle = FC_HINT_FULL; if (!hinting) hintstyle = FC_HINT_NONE; @@ -1712,22 +1452,16 @@ static void } if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT) options->base.hint_style = other->base.hint_style; 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; else load_target = FT_LOAD_TARGET_MONO; load_flags |= FT_LOAD_MONOCHROME; } else { switch (options->base.hint_style) { @@ -1741,21 +1475,21 @@ static void break; case CAIRO_HINT_STYLE_FULL: case CAIRO_HINT_STYLE_DEFAULT: if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) { switch (options->base.subpixel_order) { 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; } } break; } } options->load_flags = load_flags | load_target; @@ -2478,16 +2212,17 @@ static cairo_int_status_t _cairo_ft_unscaled_font_unlock_face (unscaled); return CAIRO_STATUS_SUCCESS; } 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, NULL, /* text_to_glyphs */ _cairo_ft_ucs4_to_index, NULL, /* show_glyphs */ _cairo_ft_load_truetype_table, _cairo_ft_index_to_ucs4 @@ -2584,16 +2319,17 @@ static cairo_status_t font_matrix, ctm, options, ft_options, scaled_font); } 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 }; static cairo_font_face_t * _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, cairo_ft_options_t *ft_options) { cairo_ft_font_face_t *font_face, **prev_font_face; @@ -2688,44 +2424,16 @@ static cairo_status_t rgba = FC_RGBA_NONE; } if (! FcPatternAddInteger (pattern, FC_RGBA, rgba)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } } - 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) { if (! FcPatternAddBool (pattern, FC_HINTING, options->hint_style != CAIRO_HINT_STYLE_NONE)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2856,20 +2564,24 @@ cairo_ft_font_face_create_for_pattern (F * are useful. You should not pass any of the flags affecting * the load target, such as %FT_LOAD_TARGET_LIGHT. * * Creates a new font face for the FreeType font backend from a * pre-opened FreeType face. This font can then be used with * 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. * * <informalexample><programlisting> * static const cairo_user_data_key_t key; * * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); * status = cairo_font_face_set_user_data (font_face, &key, * ft_face, (cairo_destroy_func_t) FT_Done_Face); * if (status) {
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c +++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c @@ -506,27 +506,31 @@ static void static cairo_status_t _cairo_glitz_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, int src_x, int src_y, int width, int height, + int *clone_offset_x, + int *clone_offset_y, cairo_surface_t **clone_out) { cairo_glitz_surface_t *surface = abstract_surface; cairo_glitz_surface_t *clone; cairo_status_t status; if (surface->base.status) return surface->base.status; if (src->backend == surface->base.backend) { + *clone_offset_x = 0; + *clone_offset_y = 0; *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; cairo_content_t content; @@ -534,16 +538,18 @@ static cairo_status_t cairo_rectangle_int_t extent; content = _cairo_content_from_format (image_src->format); clone = (cairo_glitz_surface_t *) _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; image_extent.x = 0; image_extent.y = 0; image_extent.width = image_src->width; image_extent.height = image_src->height; extent.x = src_x; @@ -797,18 +803,17 @@ static cairo_int_status_t free (data); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } src = (cairo_glitz_surface_t *) _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; } for (i = 0; i < gradient->n_stops; i++) { pixels[i] = @@ -1271,18 +1276,23 @@ static cairo_int_status_t format.vertex.mask.type = GLITZ_DATA_TYPE_FLOAT; format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X; format.vertex.mask.offset = 2 * sizeof (glitz_float_t); mask = (cairo_glitz_surface_t *) _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); return mask->base.status; } color.red = color.green = color.blue = color.alpha = 0xffff; @@ -1380,18 +1390,17 @@ static cairo_int_status_t pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y, n_traps, (pixman_trapezoid_t *) traps); mask = (cairo_glitz_surface_t *) _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); return mask->base.status; } status = _cairo_glitz_surface_set_image (mask, image, 0, 0, width, height, 0, 0); @@ -2006,17 +2015,17 @@ static cairo_status_t glyph_private->area = NULL; glyph_private->locked = FALSE; scaled_glyph->surface_private = (void *) glyph_private; } 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) { status = _cairo_glitz_surface_font_init (surface, scaled_font, glyph_surface->format); if (status) return status; } @@ -2239,32 +2248,38 @@ static cairo_int_status_t cairo_glitz_surface_t *clone; for (i = 0; i < num_glyphs; i++) { glyph_private = scaled_glyphs[i]->surface_private; 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; glyph_height = scaled_glyphs[i]->surface->height; status = _cairo_glitz_surface_clone_similar (abstract_surface, image, 0, 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); y1 = _cairo_lround (glyphs[i].y - y_offset); glitz_composite (_glitz_operator (op), src->surface, clone->surface, @@ -2366,16 +2381,23 @@ static cairo_bool_t cairo_content_t content) { cairo_glitz_surface_t *a = (cairo_glitz_surface_t *) surface_a; cairo_glitz_surface_t *b = (cairo_glitz_surface_t *) surface_b; 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; } static cairo_status_t _cairo_glitz_surface_reset (void *abstract_surface) { cairo_glitz_surface_t *surface = abstract_surface; cairo_status_t status;
--- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -55,17 +55,17 @@ static cairo_status_t _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate); static cairo_status_t _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, cairo_glyph_t *transformed_glyphs, int *num_transformed_glyphs); cairo_status_t _cairo_gstate_init (cairo_gstate_t *gstate, @@ -309,16 +309,18 @@ cairo_status_t return CAIRO_STATUS_SUCCESS; } /** * _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. **/ cairo_bool_t _cairo_gstate_is_redirected (cairo_gstate_t *gstate) { return (gstate->target != gstate->original_target); } @@ -367,16 +369,18 @@ cairo_surface_t * { return gstate->original_target; } /** * _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 * _cairo_gstate_get_clip (cairo_gstate_t *gstate) { return &gstate->clip; } @@ -940,26 +944,33 @@ cairo_status_t cairo_status_t _cairo_gstate_in_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double x, double y, 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) { *inside_ret = FALSE; return CAIRO_STATUS_SUCCESS; } _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, &gstate->ctm, &gstate->ctm_inverse, gstate->tolerance, &traps); if (status) @@ -1006,21 +1017,28 @@ cairo_status_t cairo_status_t _cairo_gstate_in_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double x, double y, 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, gstate->tolerance, &traps); if (status) goto BAIL; @@ -1456,38 +1474,38 @@ cairo_status_t return status; cairo_scaled_font_extents (gstate->scaled_font, extents); return cairo_scaled_font_status (gstate->scaled_font); } 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; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, - backward); + cluster_flags); } cairo_status_t _cairo_gstate_set_font_face (cairo_gstate_t *gstate, cairo_font_face_t *font_face) { if (font_face && font_face->status) return font_face->status; @@ -1517,31 +1535,25 @@ cairo_status_t cairo_scaled_font_glyph_extents (gstate->scaled_font, glyphs, num_glyphs, extents); 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, int utf8_len, const cairo_glyph_t *glyphs, 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; cairo_glyph_t *transformed_glyphs; cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; if (gstate->source->status) return gstate->source->status; @@ -1557,20 +1569,22 @@ cairo_status_t if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) { transformed_glyphs = stack_transformed_glyphs; } else { transformed_glyphs = cairo_glyph_allocate (num_glyphs); if (transformed_glyphs == NULL) 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); if (status) goto CLEANUP_GLYPHS; /* Just in case */ if (!clusters) @@ -1581,36 +1595,34 @@ cairo_status_t * and moreover, not all components below us correctly handle huge font * sizes. I wanted to set the limit at 256. But alas, seems like cairo's * rasterizer is something like ten times slower than freetype's for huge * sizes. So, no win just yet. For now, do it for insanely-huge sizes, * just to make sure we don't make anyone unhappy. When we get a really * 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, &source_pattern.base, 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, gstate->op, &source_pattern.base, &path, CAIRO_FILL_RULE_WINDING, gstate->tolerance, @@ -1644,25 +1656,28 @@ cairo_status_t if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs)) transformed_glyphs = stack_transformed_glyphs; else transformed_glyphs = cairo_glyph_allocate (num_glyphs); 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); return status; } cairo_status_t _cairo_gstate_set_antialias (cairo_gstate_t *gstate, @@ -1692,43 +1707,47 @@ cairo_antialias_t * * Transform an array of glyphs to backend space by first adding the offset * of the font matrix, then transforming from user space to backend space. * The result of the transformation is placed in @transformed_glyphs. * * 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, cairo_glyph_t *transformed_glyphs, int *num_transformed_glyphs) { int i, j; cairo_matrix_t *ctm = &gstate->ctm; cairo_matrix_t *font_matrix = &gstate->font_matrix; 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 * font scale. This however can fail in extreme cases where the * font has really long swashes for example... We can correctly * handle that by looking the glyph up and using its device bbox * to device if it's going to be visible, but I'm not inclined to * do that now. @@ -1798,9 +1817,11 @@ static void cairo_matrix_transform_point (&aggregate_transform, &transformed_glyphs[j].x, &transformed_glyphs[j].y); if (!drop || KEEP_GLYPH (transformed_glyphs[j])) j++; } *num_transformed_glyphs = j; } + + return CAIRO_STATUS_SUCCESS; }
--- a/gfx/cairo/cairo/src/cairo-hull.c +++ b/gfx/cairo/cairo/src/cairo-hull.c @@ -73,40 +73,47 @@ static void hull[i].discard = 0; /* Discard all points coincident with the extremal point */ if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0) hull[i].discard = 1; } } +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) { cairo_hull_t *a = (cairo_hull_t *) av; cairo_hull_t *b = (cairo_hull_t *) bv; int ret; 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 { b->discard = 1; ret = 1; } }
--- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -55,16 +55,20 @@ static cairo_format_t case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4: case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2: case PIXMAN_b2g3r3: case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2: case PIXMAN_c8: case PIXMAN_g8: case PIXMAN_x4a4: case PIXMAN_a4: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1: 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; } return CAIRO_FORMAT_INVALID; } static cairo_content_t @@ -76,16 +80,19 @@ static cairo_content_t case PIXMAN_a1r5g5b5: case PIXMAN_a1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_a4b4g4r4: case PIXMAN_a2r2g2b2: 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: case PIXMAN_r8g8b8: case PIXMAN_b8g8r8: case PIXMAN_r5g6b5: case PIXMAN_b5g6r5: case PIXMAN_x1r5g5b5: @@ -98,16 +105,19 @@ static cairo_content_t case PIXMAN_g8: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1: 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: +#endif return CAIRO_CONTENT_COLOR; case PIXMAN_a8: case PIXMAN_a1: case PIXMAN_x4a4: case PIXMAN_a4: return CAIRO_CONTENT_ALPHA; } @@ -139,17 +149,17 @@ cairo_surface_t * surface->width = pixman_image_get_width (pixman_image); surface->height = pixman_image_get_height (pixman_image); surface->stride = pixman_image_get_stride (pixman_image); surface->depth = pixman_image_get_depth (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) { pixman_format_code_t format; int format_type; int a, r, g, b; cairo_format_masks_t format_masks; @@ -161,40 +171,40 @@ cairo_int_status_t if (masks->red_mask) { if (masks->red_mask > masks->blue_mask) format_type = PIXMAN_TYPE_ARGB; else format_type = PIXMAN_TYPE_ABGR; } 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 * alpha in the least-significant bits, or insane channel order, * or whatever. */ _pixman_format_to_masks (format, &format_masks); if (masks->bpp != format_masks.bpp || masks->red_mask != format_masks.red_mask || 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. */ #define MASK(N) ((1 << (N))-1) void _pixman_format_to_masks (pixman_format_code_t format, cairo_format_masks_t *masks) @@ -248,30 +258,31 @@ void * that accepts a #cairo_internal_format_t rather than mask values. */ cairo_surface_t * _cairo_image_surface_create_with_masks (unsigned char *data, cairo_format_masks_t *masks, int width, 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" "\tAlpha mask: 0x%08lx\n" "\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); ASSERT_NOT_REACHED; } return _cairo_image_surface_create_with_pixman_format (data, @@ -468,23 +479,35 @@ slim_hidden_def (cairo_format_stride_for cairo_surface_t * cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, int width, int height, 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)); 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, width, height, stride); } slim_hidden_def (cairo_image_surface_create_for_data); cairo_surface_t * @@ -505,17 +528,18 @@ cairo_surface_t * /** * cairo_image_surface_get_data: * @surface: a #cairo_image_surface_t * * Get a pointer to the data of the image surface, for direct * 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 **/ unsigned char * cairo_image_surface_get_data (cairo_surface_t *surface) { cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; @@ -543,18 +567,16 @@ cairo_image_surface_get_format (cairo_su { cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; if (! _cairo_surface_is_image (surface)) { _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return 0; } - assert (CAIRO_FORMAT_VALID (image_surface->format)); - return image_surface->format; } /** * cairo_image_surface_get_width: * @surface: a #cairo_image_surface_t * * Get the width of the image surface in pixels. @@ -761,21 +783,24 @@ static void static cairo_status_t _cairo_image_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, int src_x, int src_y, int width, int height, + 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; } return CAIRO_INT_STATUS_UNSUPPORTED; }
--- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -619,16 +619,45 @@ cairo_bool_t return TRUE; } } 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. The following is a derivation of a formula to calculate the length of the major axis for this ellipse; this is useful for error bounds calculations. Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this derivation:
--- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h @@ -109,17 +109,17 @@ typedef struct _cairo_command_show_text_ cairo_operator_t op; cairo_pattern_union_t source; char *utf8; int utf8_len; cairo_glyph_t *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; typedef struct _cairo_command_intersect_clip_path { cairo_command_header_t header; cairo_path_fixed_t *path_pointer; cairo_path_fixed_t path; cairo_fill_rule_t fill_rule;
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c +++ b/gfx/cairo/cairo/src/cairo-meta-surface.c @@ -211,42 +211,16 @@ static cairo_status_t static void _cairo_meta_surface_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *image_extra) { 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, cairo_pattern_t *source) { cairo_status_t status; cairo_meta_surface_t *meta = abstract_surface; cairo_command_paint_t *command; @@ -254,17 +228,17 @@ static cairo_int_status_t command = malloc (sizeof (cairo_command_paint_t)); if (command == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); command->header.type = CAIRO_COMMAND_PAINT; 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 = _cairo_array_append (&meta->commands, &command); if (status) goto CLEANUP_SOURCE; /* An optimisation that takes care to not replay what was done @@ -295,21 +269,21 @@ static cairo_int_status_t command = malloc (sizeof (cairo_command_mask_t)); if (command == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); command->header.type = CAIRO_COMMAND_MASK; 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; status = _cairo_array_append (&meta->commands, &command); if (status) goto CLEANUP_MASK; return CAIRO_STATUS_SUCCESS; @@ -341,17 +315,17 @@ static cairo_int_status_t command = malloc (sizeof (cairo_command_stroke_t)); if (command == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); command->header.type = CAIRO_COMMAND_STROKE; 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 = _cairo_path_fixed_init_copy (&command->path, path); if (status) goto CLEANUP_SOURCE; status = _cairo_stroke_style_init_copy (&command->style, style); @@ -396,17 +370,17 @@ static cairo_int_status_t command = malloc (sizeof (cairo_command_fill_t)); if (command == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); command->header.type = CAIRO_COMMAND_FILL; 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 = _cairo_path_fixed_init_copy (&command->path, path); if (status) goto CLEANUP_SOURCE; command->fill_rule = fill_rule; @@ -439,32 +413,32 @@ static cairo_int_status_t cairo_operator_t op, cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, 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_meta_surface_t *meta = abstract_surface; cairo_command_show_text_glyphs_t *command; command = malloc (sizeof (cairo_command_show_text_glyphs_t)); if (command == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS; 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; command->utf8 = NULL; command->utf8_len = utf8_len; command->glyphs = NULL; command->num_glyphs = num_glyphs; command->clusters = NULL; @@ -490,17 +464,17 @@ static cairo_int_status_t command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0])); if (command->clusters == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_ARRAYS; } 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); status = _cairo_array_append (&meta->commands, &command); if (status) goto CLEANUP_SCALED_FONT; return CAIRO_STATUS_SUCCESS; @@ -843,17 +817,17 @@ static cairo_status_t case CAIRO_COMMAND_STROKE: { cairo_matrix_t dev_ctm = command->stroke.ctm; cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse; 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); } status = _cairo_surface_stroke (target, command->stroke.op, &command->stroke.source.base, dev_path, &command->stroke.style, @@ -947,17 +921,17 @@ static cairo_status_t } status = _cairo_surface_show_text_glyphs (target, command->show_text_glyphs.op, &command->show_text_glyphs.source.base, 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); break; } case CAIRO_COMMAND_INTERSECT_CLIP_PATH: /* XXX Meta surface clipping is broken and requires some * cairo-gstate.c rewriting. Work around it for now. */
--- a/gfx/cairo/cairo/src/cairo-misc.c +++ b/gfx/cairo/cairo/src/cairo-misc.c @@ -235,34 +235,34 @@ slim_hidden_def (cairo_text_cluster_free /** * _cairo_validate_text_clusters: * @utf8: UTF-8 text * @utf8_len: length of @utf8 in bytes * @glyphs: array of glyphs * @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. * * Return value: %CAIRO_STATUS_SUCCESS upon success, or * %CAIRO_STATUS_INVALID_CLUSTERS on error. * The error is either invalid UTF-8 input, * or bad cluster mapping. */ cairo_status_t _cairo_validate_text_clusters (const char *utf8, int utf8_len, const cairo_glyph_t *glyphs, 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; unsigned int n_glyphs = 0; int i; for (i = 0; i < num_clusters; i++) { int cluster_bytes = clusters[i].num_bytes;
--- a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h @@ -36,20 +36,25 @@ * Carl D. Worth <cworth@cworth.org> * Mathias Hasselmann <mathias.hasselmann@gmx.de> * Behdad Esfahbod <behdad@behdad.org> */ #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 <lockdep.h> +#endif /* A fully qualified no-operation statement */ #define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0) /* And one that evaluates it's argument once */ #define CAIRO_MUTEX_IMPL_NOOP1(expr) do { if (expr) ; } while (0) /* Cairo mutex implementation: @@ -67,16 +72,19 @@ * implementation supports. No trailing semicolon needed. * You should be able to compile the following snippet (don't try * running it): * * <programlisting> * cairo_mutex_impl_t _cairo_some_mutex; * </programlisting> * + * - #define %CAIRO_MUTEX_IMPL_<NAME> 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 * initialized, and is-not-already-locked/is-locked, * respectively. Use the "do { ... } while (0)" idiom if necessary. * No trailing semicolons are needed (in any macro you define here). * You should be able to compile the following snippet: * @@ -142,73 +150,84 @@ * </programlisting> * * - That is all. If for any reason you think the above API is * not enough to implement #cairo_mutex_impl_t on your system, please * stop and write to the cairo mailing list about it. DO NOT * 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) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 #elif HAVE_PTHREAD_H /*******************************************************/ # include <pthread.h> 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 <windows.h> 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)) # define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } #elif defined __OS2__ /******************************************************/ # define INCL_BASE # define INCL_PM # include <os2.h> 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) # define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 #elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ 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() # define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL #else /**********************************************************************/
--- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h @@ -26,30 +26,34 @@ * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * Contributor(s): * Mathias Hasselmann <mathias.hasselmann@gmx.de> */ - -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock); -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock); +#ifndef CAIRO_FEATURES_H +/* This block is to just make this header file standalone */ +#define CAIRO_MUTEX_DECLARE(mutex) +#endif -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_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) #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 */ #undef CAIRO_MUTEX_DECLARE
--- a/gfx/cairo/cairo/src/cairo-mutex-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-private.h @@ -36,20 +36,16 @@ * Carl D. Worth <cworth@cworth.org> * Mathias Hasselmann <mathias.hasselmann@gmx.de> * Behdad Esfahbod <behdad@behdad.org> */ #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 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER cairo_private void _cairo_mutex_initialize (void); #endif #if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER @@ -57,15 +53,15 @@ cairo_private void _cairo_mutex_finalize #endif /* only if using static initializer and/or finalizer define the boolean */ #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER cairo_private extern cairo_bool_t _cairo_mutex_initialized; #endif /* 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 CAIRO_END_DECLS #endif
--- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h @@ -85,17 +85,16 @@ /* and dynamic ones can be initialized using the static initializer. */ # define CAIRO_MUTEX_IMPL_INIT(mutex) do { \ cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; \ memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \ } while (0) #endif /* CAIRO_MUTEX_IMPL_INIT */ - #ifdef CAIRO_MUTEX_IMPL_FINI /* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all * static mutex'es. */ # ifndef CAIRO_MUTEX_IMPL_FINALIZE # define CAIRO_MUTEX_IMPL_FINALIZE() do { \ if (_cairo_mutex_initialized) \ _cairo_mutex_finalize (); \ @@ -164,16 +163,22 @@ typedef cairo_mutex_impl_t cairo_mutex_t #define CAIRO_MUTEX_INITIALIZE CAIRO_MUTEX_IMPL_INITIALIZE #define CAIRO_MUTEX_FINALIZE CAIRO_MUTEX_IMPL_FINALIZE #define CAIRO_MUTEX_LOCK CAIRO_MUTEX_IMPL_LOCK #define CAIRO_MUTEX_UNLOCK CAIRO_MUTEX_IMPL_UNLOCK #define CAIRO_MUTEX_INIT CAIRO_MUTEX_IMPL_INIT #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 */ #ifdef CAIRO_MUTEX_DEBUG /* TODO add mutex debugging facilities here (eg deadlock detection) */
--- a/gfx/cairo/cairo/src/cairo-mutex.c +++ b/gfx/cairo/cairo/src/cairo-mutex.c @@ -30,17 +30,17 @@ * Contributor(s): * Mathias Hasselmann <mathias.hasselmann@gmx.de> */ #include "cairoint.h" #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 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER # if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER # define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE # else @@ -56,27 +56,27 @@ cairo_bool_t _cairo_mutex_initialized = #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER void _cairo_mutex_initialize (void) { if (_cairo_mutex_initialized) return; _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 } #endif #if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER void _cairo_mutex_finalize (void) { if (!_cairo_mutex_initialized) return; _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 } #endif
deleted file mode 100644 --- 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 <cairo-features.h> - -/* This is a dummy header, to trick gtk-doc only */ - -#define CAIRO_HAS_WIN32_FONT 1 -#define CAIRO_HAS_WIN32_SURFACE 1 - -#endif
--- a/gfx/cairo/cairo/src/cairo-os2-private.h +++ b/gfx/cairo/cairo/src/cairo-os2-private.h @@ -33,30 +33,30 @@ * * Contributor(s): * Peter Weilbacher <mozilla@Weilbacher.org> */ #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 #define INCL_WIN #define INCL_GPI #ifdef __WATCOMC__ # include <os2.h> #else # include <os2emx.h> #endif -#include "cairo-os2.h" -#include "cairoint.h" - typedef struct _cairo_os2_surface { cairo_surface_t base; /* Mutex semaphore to protect private fields from concurrent access */ HMTX hmtx_use_private_fields; /* Private fields: */ HPS hps_client_window;
--- a/gfx/cairo/cairo/src/cairo-os2-surface.c +++ b/gfx/cairo/cairo/src/cairo-os2-surface.c @@ -227,16 +227,22 @@ void _buffer_free (void *buffer) { #ifdef OS2_USE_PLATFORM_ALLOC DosFreeMem (buffer); #else free (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. */ #ifdef __WATCOMC__ unsigned _System LibMain (unsigned hmod, unsigned termination) @@ -1197,16 +1203,18 @@ cairo_os2_surface_set_manual_window_refr local_os2_surface->blit_as_changes = !manual_refresh; } /** * 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 **/ cairo_bool_t cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface) { cairo_os2_surface_t *local_os2_surface;
--- a/gfx/cairo/cairo/src/cairo-output-stream-private.h +++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h @@ -156,17 +156,21 @@ cairo_private cairo_output_stream_t * cairo_private void _cairo_memory_stream_copy (cairo_output_stream_t *base, cairo_output_stream_t *dest); 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); /* cairo-deflate-stream.c */ cairo_private cairo_output_stream_t * _cairo_deflate_stream_create (cairo_output_stream_t *output); + #endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -111,16 +111,19 @@ typedef struct _cairo_output_stream_with static cairo_status_t closure_write (cairo_output_stream_t *stream, const unsigned char *data, unsigned int length) { 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); } static cairo_status_t closure_close (cairo_output_stream_t *stream) { cairo_output_stream_with_closure_t *stream_with_closure = @@ -578,16 +581,19 @@ cairo_output_stream_t * } cairo_output_stream_t * _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) { case ENOMEM: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; default: _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR); @@ -671,8 +677,31 @@ void int _cairo_memory_stream_length (cairo_output_stream_t *base) { memory_stream_t *stream = (memory_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; +}
--- a/gfx/cairo/cairo/src/cairo-paginated-private.h +++ b/gfx/cairo/cairo/src/cairo-paginated-private.h @@ -60,26 +60,29 @@ struct _cairo_paginated_surface_backend (*set_paginated_mode) (void *surface, cairo_paginated_mode_t mode); /* Optional. Specifies the smallest box that encloses all objects * on the page. Will be called at the end of the ANALYZE phase but * 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. * Will be called at the end of the ANALYZE phase but before the * 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 * is well-suited for doing the analysis common to most surfaces that * have paginated output, (that is, things directed at printers, or * for saving content in files such as PostScript or PDF files). * * To use the paginated surface, you'll first need to create your
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -103,16 +103,17 @@ cairo_surface_t * goto FAIL_CLEANUP_SURFACE; surface->page_num = 1; surface->page_is_blank = TRUE; return &surface->base; FAIL_CLEANUP_SURFACE: + cairo_surface_destroy (target); free (surface); FAIL: return _cairo_surface_create_in_error (status); } cairo_bool_t _cairo_surface_is_paginated (cairo_surface_t *surface) { @@ -294,18 +295,20 @@ static cairo_int_status_t if (surface->target->status) return surface->target->status; analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); 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; goto FAIL; } if (surface->backend->set_bounding_box) { cairo_box_t bbox; @@ -320,81 +323,71 @@ static cairo_int_status_t cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis); status = surface->backend->set_fallback_images_required (surface->target, has_fallbacks); if (status) 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); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (status) 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; box.p2.y = surface->height; status = _paint_fallback_image (surface, &box); if (status) 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, NULL, CAIRO_FILL_RULE_WINDING, CAIRO_GSTATE_TOLERANCE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT); if (status) @@ -617,17 +610,17 @@ static cairo_int_status_t cairo_operator_t op, cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, 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; cairo_int_status_t status; /* Optimize away erasing of nothing. */ if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) return CAIRO_STATUS_SUCCESS; @@ -639,24 +632,22 @@ static cairo_int_status_t * 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, + cluster_flags, scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); return status; } static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { cairo_paginated_surface_t *other = abstract_other;
--- a/gfx/cairo/cairo/src/cairo-path-fill.c +++ b/gfx/cairo/cairo/src/cairo-path-fill.c @@ -210,14 +210,30 @@ BAIL: * If the path described anything but a device-axis aligned rectangle, * this function will return %CAIRO_INT_STATUS_UNSUPPORTED. */ static cairo_int_status_t _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; }
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -824,126 +824,147 @@ static cairo_status_t } /* * Dashed lines. Cap each dash end, join around turns when on */ 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; double dx2, dy2; cairo_stroke_face_t sub_start, sub_end; 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; } _cairo_slope_init (&dev_slope, p1, p2); 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; while (remain) { step_length = MIN (stroker->dash_remain, remain); remain -= step_length; dx2 = slope_dx * (mag - remain); dy2 = slope_dy * (mag - remain); cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2); 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; - } + 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 { + /* 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; - } + 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 { - 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; - } + 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; } } _cairo_stroker_step_dash (stroker, step_length); 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 _cairo_stroker_curve_to (void *closure, cairo_point_t *b, cairo_point_t *c, cairo_point_t *d) { @@ -1252,22 +1273,22 @@ static cairo_status_t } static cairo_status_t _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; /* For each segment we generate a single rectangular * trapezoid. This rectangle is based on a perpendicular * extension (by half the line width) of the segment endpoints * after some adjustments of the endpoints to account for caps * and joins. @@ -1310,53 +1331,61 @@ static cairo_status_t } else { if (lengthen_initial) a->x += half_line_width; if (shorten_final) b->x += half_line_width; 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) a->y -= half_line_width; if (shorten_final) b->y -= half_line_width; else if (lengthen_final) b->y += half_line_width; } else { if (lengthen_initial) a->y += half_line_width; if (shorten_final) b->y += half_line_width; 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; } stroker->num_segments = 0; return CAIRO_STATUS_SUCCESS; } @@ -1434,17 +1463,17 @@ static cairo_int_status_t cairo_traps_t *traps) { cairo_rectilinear_stroker_t rectilinear_stroker; cairo_int_status_t status; /* 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 * UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any * non-rectilinear line_to is encountered. */ if (path->has_curve_to) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1479,16 +1508,15 @@ static cairo_int_status_t _cairo_rectilinear_stroker_close_path, &rectilinear_stroker); if (status) goto BAIL; 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; }
--- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -187,16 +187,46 @@ cairo_status_t /* The reference count and user_data array are unique to the copy. */ CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); _cairo_user_data_array_init (&pattern->user_data); 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) { _cairo_user_data_array_fini (&pattern->user_data); switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: break; @@ -779,17 +809,17 @@ cairo_pattern_get_user_data (cairo_patte **/ cairo_status_t cairo_pattern_set_user_data (cairo_pattern_t *pattern, const cairo_user_data_key_t *key, void *user_data, 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); } /* make room for at least one more color stop */ static cairo_status_t _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern) @@ -1212,16 +1242,18 @@ static cairo_int_status_t pixman_image_t *pixman_image; pixman_transform_t pixman_transform; cairo_status_t status; cairo_bool_t repeat = FALSE; 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)); if (pixman_stops == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } for (i = 0; i < pattern->n_stops; i++) { @@ -1231,21 +1263,56 @@ static cairo_int_status_t pixman_stops[i].color.blue = pattern->stops[i].color.blue_short; pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short; } if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { 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, pattern->n_stops); } else { cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; @@ -1279,17 +1346,17 @@ static cairo_int_status_t PIXMAN_a8r8g8b8); if (image->base.status) { pixman_image_unref (pixman_image); return image->base.status; } 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; *out = &image->base; return CAIRO_STATUS_SUCCESS; } @@ -1327,17 +1394,17 @@ static cairo_int_status_t image = (cairo_image_surface_t *) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); if (image->base.status) { pixman_image_unref (pixman_image); 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); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } switch (pattern->base.extend) { case CAIRO_EXTEND_NONE: @@ -1361,17 +1428,20 @@ static cairo_int_status_t x, y, 0, 0, 0, 0, width, height); 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); attr->x_offset = -x; attr->y_offset = -y; cairo_matrix_init_identity (&attr->matrix); attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE; attr->filter = CAIRO_FILTER_NEAREST; @@ -1623,40 +1693,131 @@ cairo_bool_t case CAIRO_PATTERN_TYPE_RADIAL: return _gradient_is_opaque (&pattern->gradient.base); } ASSERT_NOT_REACHED; 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, int x, int y, unsigned int width, unsigned int height, cairo_surface_t **out, cairo_surface_attributes_t *attr) { 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 { attr->matrix = pattern->base.matrix; attr->x_offset = attr->y_offset = 0; tx = 0; ty = 0; } @@ -1729,82 +1890,94 @@ static cairo_int_status_t if (status) { cairo_surface_destroy (*out); *out = NULL; } 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, &image, &attr->extra); if (status) return status; *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; } /** * _cairo_pattern_acquire_surface: * @pattern: a #cairo_pattern_t @@ -1815,16 +1988,19 @@ static cairo_int_status_t * @height: height of destination area * @surface_out: location to store a pointer to a surface * @attributes: surface attributes that destination backend should apply to * the returned surface * * 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 _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, cairo_surface_t *dst, int x, int y, unsigned int width, @@ -2044,25 +2220,30 @@ cairo_status_t { cairo_status_t status; cairo_rectangle_int_t surface_extents; cairo_surface_pattern_t *surface_pattern = (cairo_surface_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;