diff options
Diffstat (limited to 'src/cairo-analysis-surface.c')
-rw-r--r-- | src/cairo-analysis-surface.c | 160 |
1 files changed, 142 insertions, 18 deletions
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index a118e338c..0e7ba8a38 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* * Copyright © 2006 Keith Packard * Copyright © 2007 Adrian Johnson @@ -59,6 +60,10 @@ typedef struct { cairo_region_t fallback_region; cairo_box_t page_bbox; + cairo_bool_t create_region_ids; + unsigned source_region_id; + unsigned mask_region_id; + cairo_bool_t has_ctm; cairo_matrix_t ctm; @@ -257,7 +262,8 @@ _add_operation (cairo_analysis_surface_t *surface, static cairo_int_status_t _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, const cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents) + cairo_rectangle_int_t *extents, + unsigned int *regions_id) { const cairo_surface_pattern_t *surface_pattern; cairo_analysis_surface_t *tmp; @@ -280,7 +286,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, } tmp = (cairo_analysis_surface_t *) - _cairo_analysis_surface_create (surface->target); + _cairo_analysis_surface_create (surface->target, surface->create_region_ids); if (unlikely (tmp->base.status)) { status =tmp->base.status; goto cleanup1; @@ -295,13 +301,29 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, source = _cairo_surface_get_source (source, NULL); surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT - || pattern->extend == CAIRO_EXTEND_REFLECT); - status = _cairo_recording_surface_replay_and_create_regions (source, - &pattern->matrix, - &tmp->base, - surface_is_unbounded); - if (unlikely (status)) - goto cleanup2; + || pattern->extend == CAIRO_EXTEND_REFLECT); + + if (surface->create_region_ids) { + status = _cairo_recording_surface_region_array_attach (source, regions_id); + if (unlikely (status)) + goto cleanup2; + + status = _cairo_recording_surface_replay_and_create_regions (source, + *regions_id, + &pattern->matrix, + &tmp->base, + surface_is_unbounded); + if (unlikely (status)) + goto cleanup2; + } else { + status = _cairo_recording_surface_replay_with_clip (source, + &pattern->matrix, + &tmp->base, + NULL, /* target clip */ + surface_is_unbounded); + if (unlikely (status)) + goto cleanup2; + } /* black background or mime data fills entire extents */ if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) { @@ -412,6 +434,8 @@ _cairo_analysis_surface_paint (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->paint == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -427,7 +451,10 @@ _cairo_analysis_surface_paint (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -445,6 +472,8 @@ _cairo_analysis_surface_mask (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->mask == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -468,7 +497,10 @@ _cairo_analysis_surface_mask (void *abstract_surface, src_surface = _cairo_surface_get_source (src_surface, NULL); if (_cairo_surface_is_recording (src_surface)) { backend_source_status = - _analyze_recording_surface_pattern (surface, source, &rec_extents); + _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); if (_cairo_int_status_is_error (backend_source_status)) return backend_source_status; @@ -481,7 +513,10 @@ _cairo_analysis_surface_mask (void *abstract_surface, mask_surface = _cairo_surface_get_source (mask_surface, NULL); if (_cairo_surface_is_recording (mask_surface)) { backend_mask_status = - _analyze_recording_surface_pattern (surface, mask, &rec_extents); + _analyze_recording_surface_pattern (surface, + mask, + &rec_extents, + &surface->mask_region_id); if (_cairo_int_status_is_error (backend_mask_status)) return backend_mask_status; @@ -520,6 +555,8 @@ _cairo_analysis_surface_stroke (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->stroke == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -538,7 +575,10 @@ _cairo_analysis_surface_stroke (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -590,7 +630,10 @@ _cairo_analysis_surface_fill (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -619,6 +662,9 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; + /* Adapted from _cairo_surface_show_glyphs */ if (surface->target->backend->show_glyphs != NULL) { backend_status = @@ -654,7 +700,10 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -699,6 +748,9 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; + /* Adapted from _cairo_surface_show_glyphs */ backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (surface->target->backend->show_text_glyphs != NULL) { @@ -732,7 +784,10 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -760,6 +815,8 @@ _cairo_analysis_surface_tag (void *abstract_surface, cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; + surface->source_region_id = 0; + surface->mask_region_id = 0; backend_status = CAIRO_INT_STATUS_SUCCESS; if (surface->target->backend->tag != NULL) { backend_status = @@ -774,6 +831,14 @@ _cairo_analysis_surface_tag (void *abstract_surface, return backend_status; } +static cairo_bool_t +_cairo_analysis_surface_supports_color_glyph (void *abstract_surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + return TRUE; +} + static const cairo_surface_backend_t cairo_analysis_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, @@ -808,11 +873,13 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = { _cairo_analysis_surface_has_show_text_glyphs, _cairo_analysis_surface_show_text_glyphs, NULL, /* get_supported_mime_types */ - _cairo_analysis_surface_tag + _cairo_analysis_surface_tag, + _cairo_analysis_surface_supports_color_glyph }; cairo_surface_t * -_cairo_analysis_surface_create (cairo_surface_t *target) +_cairo_analysis_surface_create (cairo_surface_t *target, + cairo_bool_t create_region_ids) { cairo_analysis_surface_t *surface; cairo_status_t status; @@ -841,6 +908,10 @@ _cairo_analysis_surface_create (cairo_surface_t *target) surface->has_supported = FALSE; surface->has_unsupported = FALSE; + surface->create_region_ids = create_region_ids; + surface->source_region_id = 0; + surface->mask_region_id = 0; + _cairo_region_init (&surface->supported_region); _cairo_region_init (&surface->fallback_region); @@ -918,6 +989,23 @@ _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface, *bbox = surface->page_bbox; } +unsigned int +_cairo_analysis_surface_get_source_region_id (cairo_surface_t *abstract_surface) +{ + cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; + + return surface->source_region_id; +} + +unsigned int +_cairo_analysis_surface_get_mask_region_id (cairo_surface_t *abstract_surface) +{ + cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; + + return surface->mask_region_id; +} + + /* null surface type: a surface that does nothing (has no side effects, yay!) */ static cairo_int_status_t @@ -926,6 +1014,12 @@ _paint_return_success (void *surface, const cairo_pattern_t *source, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -936,6 +1030,18 @@ _mask_return_success (void *surface, const cairo_pattern_t *mask, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + + if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -951,6 +1057,12 @@ _stroke_return_success (void *surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -964,6 +1076,12 @@ _fill_return_success (void *surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -976,6 +1094,12 @@ _show_glyphs_return_success (void *surface, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } |