diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-11 13:34:29 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-29 08:08:33 +0100 |
commit | a1e0c4b30980d624bb3e015b7dcf39b4a2ef8c56 (patch) | |
tree | a4ac7e28003d805d0a51085c85cb231bb1d998de | |
parent | 3f12d9ec5db1ac372742c3c03408bdaeaffdc1e4 (diff) |
[clip] Combine directly onto target
Where it is unlikely that we will reuse the temporary clip surface,
combine the clip directly with the mask.
-rw-r--r-- | src/cairo-clip-private.h | 3 | ||||
-rw-r--r-- | src/cairo-clip.c | 118 | ||||
-rw-r--r-- | src/cairo-surface-fallback.c | 26 |
3 files changed, 115 insertions, 32 deletions
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index 6e404927..a7e06a9a 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -113,6 +113,9 @@ _cairo_clip_get_extents (const cairo_clip_t *clip); cairo_private cairo_surface_t * _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst); +cairo_private cairo_status_t +_cairo_clip_combine_with_surface (cairo_clip_t *clip, cairo_surface_t *dst); + cairo_private cairo_int_status_t _cairo_clip_get_region (cairo_clip_t *clip, cairo_region_t **region); diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 09b26ade..67079c4b 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -1127,6 +1127,106 @@ BAIL: return _cairo_surface_create_in_error (status); } +cairo_status_t +_cairo_clip_combine_with_surface (cairo_clip_t *clip, cairo_surface_t *dst) +{ + cairo_pattern_union_t pattern; + cairo_clip_path_t *clip_path = clip->path; + const cairo_rectangle_int_t *clip_extents = &clip_path->extents; + cairo_bool_t need_translate; + cairo_status_t status; + + assert (clip_path != NULL); + + if (clip_path->surface != NULL && + clip_path->surface->backend == dst->backend) + { + _cairo_pattern_init_for_surface (&pattern.surface, + clip_path->surface); + cairo_matrix_init_translate (&pattern.base.matrix, + -clip_path->extents.x + clip_extents->x, + -clip_path->extents.y + clip_extents->y); + status = _cairo_surface_paint (dst, + CAIRO_OPERATOR_IN, + &pattern.base, + NULL); + + _cairo_pattern_fini (&pattern.base); + + return status; + } + + _cairo_pattern_init_solid (&pattern.solid, + CAIRO_COLOR_WHITE, + CAIRO_CONTENT_COLOR); + + need_translate = clip_extents->x || clip_extents->y; + do { + status = _cairo_clip_path_to_region (clip_path); + if (unlikely (_cairo_status_is_error (status))) + return status; + + if (status == CAIRO_STATUS_SUCCESS) { + if (need_translate) { + cairo_region_translate (clip_path->region, + -clip_extents->x, -clip_extents->y); + } + status = _cairo_surface_fill_region (dst, + CAIRO_OPERATOR_IN, + CAIRO_COLOR_WHITE, + clip_path->region); + if (need_translate) { + cairo_region_translate (clip_path->region, + clip_extents->x, clip_extents->y); + } + + return status; + } + + if (clip_path->surface != NULL && + clip_path->surface->backend == dst->backend) + { + _cairo_pattern_init_for_surface (&pattern.surface, + clip_path->surface); + cairo_matrix_init_translate (&pattern.base.matrix, + -clip_path->extents.x + clip_extents->x, + -clip_path->extents.y + clip_extents->y); + status = _cairo_surface_paint (dst, + CAIRO_OPERATOR_IN, + &pattern.base, + NULL); + + _cairo_pattern_fini (&pattern.base); + + return status; + } + + if (need_translate) { + _cairo_path_fixed_translate (&clip_path->path, + _cairo_fixed_from_int (-clip_extents->x), + _cairo_fixed_from_int (-clip_extents->y)); + } + status = _cairo_surface_fill (dst, + CAIRO_OPERATOR_IN, + &pattern.base, + &clip_path->path, + clip_path->fill_rule, + clip_path->tolerance, + clip_path->antialias, + NULL); + if (need_translate) { + _cairo_path_fixed_translate (&clip_path->path, + _cairo_fixed_from_int (clip_extents->x), + _cairo_fixed_from_int (clip_extents->y)); + } + + if (unlikely (status)) + return status; + } while ((clip_path = clip_path->prev) != NULL); + + return CAIRO_STATUS_SUCCESS; +} + const cairo_rectangle_int_t * _cairo_clip_get_extents (const cairo_clip_t *clip) { @@ -1273,18 +1373,20 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) cairo_rectangle_list_t *list; cairo_rectangle_t *rectangles = NULL; + cairo_region_t *region = NULL; cairo_int_status_t status; - cairo_region_t *region; int n_rects = 0; int i; - status = _cairo_clip_get_region (clip, ®ion); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { - goto DONE; - } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) - } else if (unlikely (status)) { - return ERROR_LIST (status); + if (clip != NULL && clip->path != NULL) { + status = _cairo_clip_get_region (clip, ®ion); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + goto DONE; + } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) + } else if (unlikely (status)) { + return ERROR_LIST (status); + } } if (region != NULL) { diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 14d94fd7..32db7fbd 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -163,30 +163,8 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern, if (unlikely (status)) goto CLEANUP_SURFACE; - if (clip_surface) { - cairo_surface_pattern_t pattern; - cairo_surface_t *surface; - - surface = _cairo_clip_get_surface (clip, mask); - _cairo_pattern_init_for_surface (&pattern, surface); - cairo_surface_destroy (surface); - - status = _cairo_surface_composite (CAIRO_OPERATOR_IN, - &pattern.base, - NULL, - mask, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, - 0, 0, - 0, 0, - extents->width, extents->height, - NULL); - - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto CLEANUP_SURFACE; - } + if (clip_surface) + status = _cairo_clip_combine_with_surface (clip, mask); _cairo_pattern_init_for_surface (mask_pattern, mask); |