diff options
author | David Reveman <davidr@novell.com> | 2005-03-03 18:39:06 +0000 |
---|---|---|
committer | David Reveman <davidr@novell.com> | 2005-03-03 18:39:06 +0000 |
commit | 50b5344d7d8ff16c06b89deefe9de520848de706 (patch) | |
tree | 81638207773a93afe7616beb30e6492e0ca65022 | |
parent | a97f4cce5e13cfa2dc3b843b3b37cb14cb16cf65 (diff) |
Pass mask to composite operation as pattern
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | src/cairo-ft-font.c | 7 | ||||
-rw-r--r-- | src/cairo-glitz-surface.c | 126 | ||||
-rw-r--r-- | src/cairo-gstate.c | 21 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 82 | ||||
-rw-r--r-- | src/cairo-pattern.c | 44 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 11 | ||||
-rw-r--r-- | src/cairo-ps-surface.c | 2 | ||||
-rw-r--r-- | src/cairo-surface.c | 14 | ||||
-rw-r--r-- | src/cairo-xlib-surface.c | 88 | ||||
-rw-r--r-- | src/cairo_ft_font.c | 7 | ||||
-rw-r--r-- | src/cairo_glitz_surface.c | 126 | ||||
-rw-r--r-- | src/cairo_gstate.c | 21 | ||||
-rw-r--r-- | src/cairo_image_surface.c | 82 | ||||
-rw-r--r-- | src/cairo_pattern.c | 44 | ||||
-rw-r--r-- | src/cairo_pdf_surface.c | 11 | ||||
-rw-r--r-- | src/cairo_png_surface.c | 4 | ||||
-rw-r--r-- | src/cairo_ps_surface.c | 2 | ||||
-rw-r--r-- | src/cairo_surface.c | 14 | ||||
-rw-r--r-- | src/cairo_xlib_surface.c | 88 | ||||
-rw-r--r-- | src/cairoint.h | 21 |
21 files changed, 564 insertions, 267 deletions
@@ -1,5 +1,21 @@ 2005-03-04 David Reveman <davidr@novell.com> + * src/cairo_pattern.c: + * src/cairoint.h: + Add convenience function _cairo_pattern_acquire_surfaces. + + * src/cairo_xlib_surface.c: + * src/cairo_surface.c: + * src/cairo_ps_surface.c: + * src/cairo_png_surface.c: + * src/cairo_pdf_surface.c: + * src/cairo_pattern.c: + * src/cairo_image_surface.c: + * src/cairo_gstate.c: + * src/cairo_glitz_surface.c: + * src/cairo_ft_font.c (_cairo_ft_font_show_glyphs): Mask to composite + operation is now passed as a pattern. + * src/cairoint.h: * src/cairo_xlib_surface.c: (_cairo_xlib_surface_set_matrix): Setting identity transform should diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index d691bbe51..44e1b0e84 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -989,6 +989,7 @@ _cairo_ft_font_show_glyphs (void *abstract_font, cairo_cache_t *cache; cairo_glyph_cache_key_t key; cairo_ft_font_t *font = abstract_font; + cairo_surface_pattern_t glyph_pattern; cairo_status_t status; int x, y; int i; @@ -1023,8 +1024,10 @@ _cairo_ft_font_show_glyphs (void *abstract_font, x = (int) floor (glyphs[i].x + 0.5); y = (int) floor (glyphs[i].y + 0.5); + _cairo_pattern_init_for_surface (&glyph_pattern, &(img->image->base)); + status = _cairo_surface_composite (operator, pattern, - &(img->image->base), + &glyph_pattern.base, surface, x + img->size.x, y + img->size.y, @@ -1034,6 +1037,8 @@ _cairo_ft_font_show_glyphs (void *abstract_font, (double) img->size.width, (double) img->size.height); + _cairo_pattern_fini (&glyph_pattern.base); + if (status) { _cairo_unlock_global_image_glyph_cache (); return status; diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index bf7e96658..112932530 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -708,6 +708,50 @@ _cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst, _cairo_glitz_surface_destroy (surface); } +static cairo_int_status_t +_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, + cairo_pattern_t *mask, + cairo_glitz_surface_t *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + unsigned int width, + unsigned int height, + cairo_glitz_surface_t **src_out, + cairo_glitz_surface_t **mask_out, + cairo_glitz_surface_attributes_t *sattr, + cairo_glitz_surface_attributes_t *mattr) +{ + cairo_int_status_t status; + + status = _cairo_glitz_pattern_acquire_surface (src, dst, + src_x, src_y, + width, height, + src_out, sattr); + if (status) + return status; + + if (mask) + { + status = _cairo_glitz_pattern_acquire_surface (mask, dst, + mask_x, mask_y, + width, height, + mask_out, mattr); + if (status) + { + _cairo_glitz_pattern_release_surface (dst, *src_out, sattr); + return status; + } + } + else + { + *mask_out = NULL; + } + + return CAIRO_STATUS_SUCCESS; +} + static void _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, cairo_glitz_surface_attributes_t *a) @@ -720,8 +764,8 @@ _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, static cairo_int_status_t _cairo_glitz_surface_composite (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -732,11 +776,10 @@ _cairo_glitz_surface_composite (cairo_operator_t op, unsigned int width, unsigned int height) { - cairo_glitz_surface_attributes_t attributes; + cairo_glitz_surface_attributes_t src_attr, mask_attr; cairo_glitz_surface_t *dst = abstract_dst; cairo_glitz_surface_t *src; cairo_glitz_surface_t *mask; - cairo_surface_t *mask_clone = NULL; cairo_int_status_t status; if (op == CAIRO_OPERATOR_SATURATE) @@ -745,48 +788,53 @@ _cairo_glitz_surface_composite (cairo_operator_t op, if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; - mask = (cairo_glitz_surface_t *) generic_mask; + status = _cairo_glitz_pattern_acquire_surfaces (src_pattern, mask_pattern, + dst, + src_x, src_y, + mask_x, mask_y, + width, height, + &src, &mask, + &src_attr, &mask_attr); + if (status) + return status; - /* XXX: this stuff can go when we change the mask to be a pattern. */ - if (generic_mask && (generic_mask->backend != dst->base.backend)) + _cairo_glitz_surface_set_attributes (src, &src_attr); + if (mask) { - status = _cairo_surface_clone_similar (abstract_dst, generic_mask, - &mask_clone); - if (status) - return status; + _cairo_glitz_surface_set_attributes (mask, &mask_attr); + glitz_composite (_glitz_operator (op), + src->surface, + mask->surface, + dst->surface, + src_x + src_attr.base.x_offset, + src_y + src_attr.base.y_offset, + mask_x + mask_attr.base.x_offset, + mask_y + mask_attr.base.y_offset, + dst_x, dst_y, + width, height); - mask = (cairo_glitz_surface_t *) mask_clone; - } - - status = _cairo_glitz_pattern_acquire_surface (pattern, dst, - src_x, src_y, width, height, - &src, &attributes); - if (status) - { - if (mask_clone) - cairo_surface_destroy (mask_clone); + if (mask_attr.n_params) + free (mask_attr.params); - return status; + _cairo_glitz_pattern_release_surface (dst, mask, &mask_attr); + } + else + { + glitz_composite (_glitz_operator (op), + src->surface, + NULL, + dst->surface, + src_x + src_attr.base.x_offset, + src_y + src_attr.base.y_offset, + 0, 0, + dst_x, dst_y, + width, height); } - _cairo_glitz_surface_set_attributes (src, &attributes); - - glitz_composite (_glitz_operator (op), - src->surface, - (mask) ? mask->surface : NULL, - dst->surface, - src_x + attributes.base.x_offset, - src_y + attributes.base.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); - - if (attributes.n_params) - free (attributes.params); + if (src_attr.n_params) + free (src_attr.params); - _cairo_glitz_pattern_release_surface (dst, src, &attributes); - if (mask_clone) - cairo_surface_destroy (mask_clone); + _cairo_glitz_pattern_release_surface (dst, src, &src_attr); if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 313507ba3..d6db560a3 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1487,6 +1487,7 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, if (gstate->clip.surface) { cairo_surface_t *intermediate; + cairo_surface_pattern_t intermediate_pattern; cairo_color_t empty_color; _cairo_rectangle_intersect (&extents, &gstate->clip.rect); @@ -1544,16 +1545,20 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, if (status) goto BAIL2; + _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); _cairo_gstate_pattern_init_copy (gstate, &pattern, src); status = _cairo_surface_composite (operator, - &pattern.base, intermediate, dst, + &pattern.base, + &intermediate_pattern.base, + dst, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); _cairo_pattern_fini (&pattern.base); + _cairo_pattern_fini (&intermediate_pattern.base); BAIL2: cairo_surface_destroy (intermediate); @@ -2043,14 +2048,21 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate, /* We only need to composite if the rectangle is not empty. */ if (!_cairo_rectangle_empty (&extents)) { + cairo_surface_pattern_t clip_pattern; + + _cairo_pattern_init_for_surface (&clip_pattern, + gstate->clip.surface); + status = _cairo_surface_composite (gstate->operator, &pattern.base, - gstate->clip.surface, + &clip_pattern.base, gstate->surface, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); + + _cairo_pattern_fini (&clip_pattern.base); } } else @@ -2421,6 +2433,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (gstate->clip.surface) { cairo_surface_t *intermediate; + cairo_surface_pattern_t intermediate_pattern; cairo_color_t empty_color; _cairo_rectangle_intersect (&extents, &gstate->clip.rect); @@ -2483,17 +2496,19 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (status) goto BAIL2; + _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); _cairo_gstate_pattern_init_copy (gstate, &pattern, gstate->pattern); status = _cairo_surface_composite (gstate->operator, &pattern.base, - intermediate, + &intermediate_pattern.base, gstate->surface, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); _cairo_pattern_fini (&pattern.base); + _cairo_pattern_fini (&intermediate_pattern.base); BAIL2: cairo_surface_destroy (intermediate); diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 69e4f8d55..9745b3150 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -453,8 +453,8 @@ _pixman_operator (cairo_operator_t operator) static cairo_int_status_t _cairo_image_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -465,50 +465,60 @@ _cairo_image_surface_composite (cairo_operator_t operator, unsigned int width, unsigned int height) { - cairo_surface_attributes_t attributes; + cairo_surface_attributes_t src_attr, mask_attr; cairo_image_surface_t *dst = abstract_dst; cairo_image_surface_t *src; - cairo_image_surface_t *mask = NULL; - void *extra; + cairo_image_surface_t *mask; cairo_int_status_t status; - /* XXX This stuff can go when we change the mask to be a pattern also. */ - if (generic_mask) - { - status = _cairo_surface_acquire_source_image (generic_mask, - &mask, &extra); - if (status) - return status; - } - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); + status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, + &dst->base, + src_x, src_y, + mask_x, mask_y, + width, height, + (cairo_surface_t **) &src, + (cairo_surface_t **) &mask, + &src_attr, &mask_attr); if (status) - { - if (mask) - _cairo_surface_release_source_image (&dst->base, mask, extra); - return status; - } - status = _cairo_image_surface_set_attributes (src, &attributes); + status = _cairo_image_surface_set_attributes (src, &src_attr); if (CAIRO_OK (status)) - pixman_composite (_pixman_operator (operator), - src->pixman_image, - mask ? mask->pixman_image : NULL, - dst->pixman_image, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); + { + if (mask) + { + status = _cairo_image_surface_set_attributes (mask, &mask_attr); + if (CAIRO_OK (status)) + pixman_composite (_pixman_operator (operator), + src->pixman_image, + mask->pixman_image, + dst->pixman_image, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + mask_x + mask_attr.x_offset, + mask_y + mask_attr.y_offset, + dst_x, dst_y, + width, height); + } + else + { + pixman_composite (_pixman_operator (operator), + src->pixman_image, + NULL, + dst->pixman_image, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + 0, 0, + dst_x, dst_y, + width, height); + } + } - _cairo_pattern_release_surface (&dst->base, &src->base, &attributes); if (mask) - _cairo_surface_release_source_image (&dst->base, mask, extra); - + _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr); + + _cairo_pattern_release_surface (&dst->base, &src->base, &src_attr); + return status; } diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index bea46f5d4..9c1263b4e 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1113,3 +1113,47 @@ _cairo_pattern_release_surface (cairo_surface_t *dst, else cairo_surface_destroy (surface); } + +cairo_int_status_t +_cairo_pattern_acquire_surfaces (cairo_pattern_t *src, + cairo_pattern_t *mask, + cairo_surface_t *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + unsigned int width, + unsigned int height, + cairo_surface_t **src_out, + cairo_surface_t **mask_out, + cairo_surface_attributes_t *src_attributes, + cairo_surface_attributes_t *mask_attributes) +{ + cairo_int_status_t status; + + status = _cairo_pattern_acquire_surface (src, dst, + src_x, src_y, + width, height, + src_out, src_attributes); + if (status) + return status; + + if (mask) + { + status = _cairo_pattern_acquire_surface (mask, dst, + mask_x, mask_y, + width, height, + mask_out, mask_attributes); + if (status) + { + _cairo_pattern_release_surface (dst, *src_out, src_attributes); + return status; + } + } + else + { + *mask_out = NULL; + } + + return CAIRO_STATUS_SUCCESS; +} diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index ea957c85f..467d891b0 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1312,8 +1312,8 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst, static cairo_int_status_t _cairo_pdf_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -1325,9 +1325,12 @@ _cairo_pdf_surface_composite (cairo_operator_t operator, unsigned int height) { cairo_pdf_surface_t *dst = abstract_dst; - cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern; + cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) src_pattern; - if (pattern->type != CAIRO_PATTERN_SURFACE) + if (mask_pattern) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (src_pattern->type != CAIRO_PATTERN_SURFACE) return CAIRO_STATUS_SUCCESS; if (src->surface->backend == &cairo_pdf_surface_backend) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 022ab0f26..4a45fc679 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -266,7 +266,7 @@ _cairo_ps_surface_clone_similar (void *abstract_surface, static cairo_int_status_t _cairo_ps_surface_composite (cairo_operator_t operator, cairo_pattern_t *src, - cairo_surface_t *generic_mask, + cairo_pattern_t *mask, void *abstract_dst, int src_x, int src_y, diff --git a/src/cairo-surface.c b/src/cairo-surface.c index e0e6d948f..330d58b1e 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -397,8 +397,8 @@ _fallback_cleanup (fallback_state_t *state) static cairo_status_t _fallback_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, cairo_surface_t *dst, int src_x, int src_y, @@ -416,7 +416,7 @@ _fallback_composite (cairo_operator_t operator, if (!CAIRO_OK (status) || !state.image) return status; - state.image->base.backend->composite (operator, pattern, mask, + state.image->base.backend->composite (operator, src, mask, &state.image->base, src_x, src_y, mask_x, mask_y, dst_x - state.image_rect.x, @@ -430,8 +430,8 @@ _fallback_composite (cairo_operator_t operator, cairo_status_t _cairo_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, cairo_surface_t *dst, int src_x, int src_y, @@ -445,7 +445,7 @@ _cairo_surface_composite (cairo_operator_t operator, cairo_int_status_t status; status = dst->backend->composite (operator, - pattern, mask, dst, + src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, @@ -454,7 +454,7 @@ _cairo_surface_composite (cairo_operator_t operator, return status; return _fallback_composite (operator, - pattern, mask, dst, + src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index f7acf2763..3eaef57e5 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -618,8 +618,8 @@ _render_operator (cairo_operator_t operator) static cairo_int_status_t _cairo_xlib_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -630,56 +630,64 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, unsigned int width, unsigned int height) { - cairo_surface_attributes_t attributes; + cairo_surface_attributes_t src_attr, mask_attr; cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; - cairo_xlib_surface_t *mask = (cairo_xlib_surface_t *) generic_mask; - cairo_surface_t *mask_clone = NULL; + cairo_xlib_surface_t *mask; cairo_int_status_t status; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; - /* XXX This stuff can go when we change the mask to be a pattern also. */ - if (generic_mask && (generic_mask->backend != dst->base.backend || - mask->dpy != dst->dpy)) { - status = _cairo_surface_clone_similar (abstract_dst, generic_mask, - &mask_clone); - if (status) - return status; - - mask = (cairo_xlib_surface_t *) mask_clone; - } - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); + status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, + &dst->base, + src_x, src_y, + mask_x, mask_y, + width, height, + (cairo_surface_t **) &src, + (cairo_surface_t **) &mask, + &src_attr, &mask_attr); if (status) - { - if (mask_clone) - cairo_surface_destroy (mask_clone); - return status; - } - status = _cairo_xlib_surface_set_attributes (src, &attributes); + status = _cairo_xlib_surface_set_attributes (src, &src_attr); if (CAIRO_OK (status)) - XRenderComposite (dst->dpy, - _render_operator (operator), - src->picture, - mask ? mask->picture : 0, - dst->picture, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); - - if (mask_clone) - cairo_surface_destroy (mask_clone); + { + if (mask) + { + status = _cairo_xlib_surface_set_attributes (mask, &mask_attr); + if (CAIRO_OK (status)) + XRenderComposite (dst->dpy, + _render_operator (operator), + src->picture, + mask->picture, + dst->picture, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + mask_x + mask_attr.x_offset, + mask_y + mask_attr.y_offset, + dst_x, dst_y, + width, height); + } + else + { + XRenderComposite (dst->dpy, + _render_operator (operator), + src->picture, + 0, + dst->picture, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + 0, 0, + dst_x, dst_y, + width, height); + } + } + + if (mask) + _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr); - _cairo_pattern_release_surface (&dst->base, &src->base, &attributes); + _cairo_pattern_release_surface (&dst->base, &src->base, &src_attr); return status; } diff --git a/src/cairo_ft_font.c b/src/cairo_ft_font.c index d691bbe51..44e1b0e84 100644 --- a/src/cairo_ft_font.c +++ b/src/cairo_ft_font.c @@ -989,6 +989,7 @@ _cairo_ft_font_show_glyphs (void *abstract_font, cairo_cache_t *cache; cairo_glyph_cache_key_t key; cairo_ft_font_t *font = abstract_font; + cairo_surface_pattern_t glyph_pattern; cairo_status_t status; int x, y; int i; @@ -1023,8 +1024,10 @@ _cairo_ft_font_show_glyphs (void *abstract_font, x = (int) floor (glyphs[i].x + 0.5); y = (int) floor (glyphs[i].y + 0.5); + _cairo_pattern_init_for_surface (&glyph_pattern, &(img->image->base)); + status = _cairo_surface_composite (operator, pattern, - &(img->image->base), + &glyph_pattern.base, surface, x + img->size.x, y + img->size.y, @@ -1034,6 +1037,8 @@ _cairo_ft_font_show_glyphs (void *abstract_font, (double) img->size.width, (double) img->size.height); + _cairo_pattern_fini (&glyph_pattern.base); + if (status) { _cairo_unlock_global_image_glyph_cache (); return status; diff --git a/src/cairo_glitz_surface.c b/src/cairo_glitz_surface.c index bf7e96658..112932530 100644 --- a/src/cairo_glitz_surface.c +++ b/src/cairo_glitz_surface.c @@ -708,6 +708,50 @@ _cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst, _cairo_glitz_surface_destroy (surface); } +static cairo_int_status_t +_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, + cairo_pattern_t *mask, + cairo_glitz_surface_t *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + unsigned int width, + unsigned int height, + cairo_glitz_surface_t **src_out, + cairo_glitz_surface_t **mask_out, + cairo_glitz_surface_attributes_t *sattr, + cairo_glitz_surface_attributes_t *mattr) +{ + cairo_int_status_t status; + + status = _cairo_glitz_pattern_acquire_surface (src, dst, + src_x, src_y, + width, height, + src_out, sattr); + if (status) + return status; + + if (mask) + { + status = _cairo_glitz_pattern_acquire_surface (mask, dst, + mask_x, mask_y, + width, height, + mask_out, mattr); + if (status) + { + _cairo_glitz_pattern_release_surface (dst, *src_out, sattr); + return status; + } + } + else + { + *mask_out = NULL; + } + + return CAIRO_STATUS_SUCCESS; +} + static void _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, cairo_glitz_surface_attributes_t *a) @@ -720,8 +764,8 @@ _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, static cairo_int_status_t _cairo_glitz_surface_composite (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -732,11 +776,10 @@ _cairo_glitz_surface_composite (cairo_operator_t op, unsigned int width, unsigned int height) { - cairo_glitz_surface_attributes_t attributes; + cairo_glitz_surface_attributes_t src_attr, mask_attr; cairo_glitz_surface_t *dst = abstract_dst; cairo_glitz_surface_t *src; cairo_glitz_surface_t *mask; - cairo_surface_t *mask_clone = NULL; cairo_int_status_t status; if (op == CAIRO_OPERATOR_SATURATE) @@ -745,48 +788,53 @@ _cairo_glitz_surface_composite (cairo_operator_t op, if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; - mask = (cairo_glitz_surface_t *) generic_mask; + status = _cairo_glitz_pattern_acquire_surfaces (src_pattern, mask_pattern, + dst, + src_x, src_y, + mask_x, mask_y, + width, height, + &src, &mask, + &src_attr, &mask_attr); + if (status) + return status; - /* XXX: this stuff can go when we change the mask to be a pattern. */ - if (generic_mask && (generic_mask->backend != dst->base.backend)) + _cairo_glitz_surface_set_attributes (src, &src_attr); + if (mask) { - status = _cairo_surface_clone_similar (abstract_dst, generic_mask, - &mask_clone); - if (status) - return status; + _cairo_glitz_surface_set_attributes (mask, &mask_attr); + glitz_composite (_glitz_operator (op), + src->surface, + mask->surface, + dst->surface, + src_x + src_attr.base.x_offset, + src_y + src_attr.base.y_offset, + mask_x + mask_attr.base.x_offset, + mask_y + mask_attr.base.y_offset, + dst_x, dst_y, + width, height); - mask = (cairo_glitz_surface_t *) mask_clone; - } - - status = _cairo_glitz_pattern_acquire_surface (pattern, dst, - src_x, src_y, width, height, - &src, &attributes); - if (status) - { - if (mask_clone) - cairo_surface_destroy (mask_clone); + if (mask_attr.n_params) + free (mask_attr.params); - return status; + _cairo_glitz_pattern_release_surface (dst, mask, &mask_attr); + } + else + { + glitz_composite (_glitz_operator (op), + src->surface, + NULL, + dst->surface, + src_x + src_attr.base.x_offset, + src_y + src_attr.base.y_offset, + 0, 0, + dst_x, dst_y, + width, height); } - _cairo_glitz_surface_set_attributes (src, &attributes); - - glitz_composite (_glitz_operator (op), - src->surface, - (mask) ? mask->surface : NULL, - dst->surface, - src_x + attributes.base.x_offset, - src_y + attributes.base.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); - - if (attributes.n_params) - free (attributes.params); + if (src_attr.n_params) + free (src_attr.params); - _cairo_glitz_pattern_release_surface (dst, src, &attributes); - if (mask_clone) - cairo_surface_destroy (mask_clone); + _cairo_glitz_pattern_release_surface (dst, src, &src_attr); if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c index 313507ba3..d6db560a3 100644 --- a/src/cairo_gstate.c +++ b/src/cairo_gstate.c @@ -1487,6 +1487,7 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, if (gstate->clip.surface) { cairo_surface_t *intermediate; + cairo_surface_pattern_t intermediate_pattern; cairo_color_t empty_color; _cairo_rectangle_intersect (&extents, &gstate->clip.rect); @@ -1544,16 +1545,20 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, if (status) goto BAIL2; + _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); _cairo_gstate_pattern_init_copy (gstate, &pattern, src); status = _cairo_surface_composite (operator, - &pattern.base, intermediate, dst, + &pattern.base, + &intermediate_pattern.base, + dst, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); _cairo_pattern_fini (&pattern.base); + _cairo_pattern_fini (&intermediate_pattern.base); BAIL2: cairo_surface_destroy (intermediate); @@ -2043,14 +2048,21 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate, /* We only need to composite if the rectangle is not empty. */ if (!_cairo_rectangle_empty (&extents)) { + cairo_surface_pattern_t clip_pattern; + + _cairo_pattern_init_for_surface (&clip_pattern, + gstate->clip.surface); + status = _cairo_surface_composite (gstate->operator, &pattern.base, - gstate->clip.surface, + &clip_pattern.base, gstate->surface, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); + + _cairo_pattern_fini (&clip_pattern.base); } } else @@ -2421,6 +2433,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (gstate->clip.surface) { cairo_surface_t *intermediate; + cairo_surface_pattern_t intermediate_pattern; cairo_color_t empty_color; _cairo_rectangle_intersect (&extents, &gstate->clip.rect); @@ -2483,17 +2496,19 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (status) goto BAIL2; + _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); _cairo_gstate_pattern_init_copy (gstate, &pattern, gstate->pattern); status = _cairo_surface_composite (gstate->operator, &pattern.base, - intermediate, + &intermediate_pattern.base, gstate->surface, extents.x, extents.y, 0, 0, extents.x, extents.y, extents.width, extents.height); _cairo_pattern_fini (&pattern.base); + _cairo_pattern_fini (&intermediate_pattern.base); BAIL2: cairo_surface_destroy (intermediate); diff --git a/src/cairo_image_surface.c b/src/cairo_image_surface.c index 69e4f8d55..9745b3150 100644 --- a/src/cairo_image_surface.c +++ b/src/cairo_image_surface.c @@ -453,8 +453,8 @@ _pixman_operator (cairo_operator_t operator) static cairo_int_status_t _cairo_image_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -465,50 +465,60 @@ _cairo_image_surface_composite (cairo_operator_t operator, unsigned int width, unsigned int height) { - cairo_surface_attributes_t attributes; + cairo_surface_attributes_t src_attr, mask_attr; cairo_image_surface_t *dst = abstract_dst; cairo_image_surface_t *src; - cairo_image_surface_t *mask = NULL; - void *extra; + cairo_image_surface_t *mask; cairo_int_status_t status; - /* XXX This stuff can go when we change the mask to be a pattern also. */ - if (generic_mask) - { - status = _cairo_surface_acquire_source_image (generic_mask, - &mask, &extra); - if (status) - return status; - } - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); + status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, + &dst->base, + src_x, src_y, + mask_x, mask_y, + width, height, + (cairo_surface_t **) &src, + (cairo_surface_t **) &mask, + &src_attr, &mask_attr); if (status) - { - if (mask) - _cairo_surface_release_source_image (&dst->base, mask, extra); - return status; - } - status = _cairo_image_surface_set_attributes (src, &attributes); + status = _cairo_image_surface_set_attributes (src, &src_attr); if (CAIRO_OK (status)) - pixman_composite (_pixman_operator (operator), - src->pixman_image, - mask ? mask->pixman_image : NULL, - dst->pixman_image, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); + { + if (mask) + { + status = _cairo_image_surface_set_attributes (mask, &mask_attr); + if (CAIRO_OK (status)) + pixman_composite (_pixman_operator (operator), + src->pixman_image, + mask->pixman_image, + dst->pixman_image, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + mask_x + mask_attr.x_offset, + mask_y + mask_attr.y_offset, + dst_x, dst_y, + width, height); + } + else + { + pixman_composite (_pixman_operator (operator), + src->pixman_image, + NULL, + dst->pixman_image, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + 0, 0, + dst_x, dst_y, + width, height); + } + } - _cairo_pattern_release_surface (&dst->base, &src->base, &attributes); if (mask) - _cairo_surface_release_source_image (&dst->base, mask, extra); - + _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr); + + _cairo_pattern_release_surface (&dst->base, &src->base, &src_attr); + return status; } diff --git a/src/cairo_pattern.c b/src/cairo_pattern.c index bea46f5d4..9c1263b4e 100644 --- a/src/cairo_pattern.c +++ b/src/cairo_pattern.c @@ -1113,3 +1113,47 @@ _cairo_pattern_release_surface (cairo_surface_t *dst, else cairo_surface_destroy (surface); } + +cairo_int_status_t +_cairo_pattern_acquire_surfaces (cairo_pattern_t *src, + cairo_pattern_t *mask, + cairo_surface_t *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + unsigned int width, + unsigned int height, + cairo_surface_t **src_out, + cairo_surface_t **mask_out, + cairo_surface_attributes_t *src_attributes, + cairo_surface_attributes_t *mask_attributes) +{ + cairo_int_status_t status; + + status = _cairo_pattern_acquire_surface (src, dst, + src_x, src_y, + width, height, + src_out, src_attributes); + if (status) + return status; + + if (mask) + { + status = _cairo_pattern_acquire_surface (mask, dst, + mask_x, mask_y, + width, height, + mask_out, mask_attributes); + if (status) + { + _cairo_pattern_release_surface (dst, *src_out, src_attributes); + return status; + } + } + else + { + *mask_out = NULL; + } + + return CAIRO_STATUS_SUCCESS; +} diff --git a/src/cairo_pdf_surface.c b/src/cairo_pdf_surface.c index ea957c85f..467d891b0 100644 --- a/src/cairo_pdf_surface.c +++ b/src/cairo_pdf_surface.c @@ -1312,8 +1312,8 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst, static cairo_int_status_t _cairo_pdf_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -1325,9 +1325,12 @@ _cairo_pdf_surface_composite (cairo_operator_t operator, unsigned int height) { cairo_pdf_surface_t *dst = abstract_dst; - cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern; + cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) src_pattern; - if (pattern->type != CAIRO_PATTERN_SURFACE) + if (mask_pattern) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (src_pattern->type != CAIRO_PATTERN_SURFACE) return CAIRO_STATUS_SUCCESS; if (src->surface->backend == &cairo_pdf_surface_backend) diff --git a/src/cairo_png_surface.c b/src/cairo_png_surface.c index 5606019cc..1ae745cb5 100644 --- a/src/cairo_png_surface.c +++ b/src/cairo_png_surface.c @@ -242,8 +242,8 @@ _cairo_png_surface_clone_similar (void *abstract_surface, static cairo_int_status_t _cairo_png_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, void *abstract_dst, int src_x, int src_y, diff --git a/src/cairo_ps_surface.c b/src/cairo_ps_surface.c index 022ab0f26..4a45fc679 100644 --- a/src/cairo_ps_surface.c +++ b/src/cairo_ps_surface.c @@ -266,7 +266,7 @@ _cairo_ps_surface_clone_similar (void *abstract_surface, static cairo_int_status_t _cairo_ps_surface_composite (cairo_operator_t operator, cairo_pattern_t *src, - cairo_surface_t *generic_mask, + cairo_pattern_t *mask, void *abstract_dst, int src_x, int src_y, diff --git a/src/cairo_surface.c b/src/cairo_surface.c index e0e6d948f..330d58b1e 100644 --- a/src/cairo_surface.c +++ b/src/cairo_surface.c @@ -397,8 +397,8 @@ _fallback_cleanup (fallback_state_t *state) static cairo_status_t _fallback_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, cairo_surface_t *dst, int src_x, int src_y, @@ -416,7 +416,7 @@ _fallback_composite (cairo_operator_t operator, if (!CAIRO_OK (status) || !state.image) return status; - state.image->base.backend->composite (operator, pattern, mask, + state.image->base.backend->composite (operator, src, mask, &state.image->base, src_x, src_y, mask_x, mask_y, dst_x - state.image_rect.x, @@ -430,8 +430,8 @@ _fallback_composite (cairo_operator_t operator, cairo_status_t _cairo_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, cairo_surface_t *dst, int src_x, int src_y, @@ -445,7 +445,7 @@ _cairo_surface_composite (cairo_operator_t operator, cairo_int_status_t status; status = dst->backend->composite (operator, - pattern, mask, dst, + src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, @@ -454,7 +454,7 @@ _cairo_surface_composite (cairo_operator_t operator, return status; return _fallback_composite (operator, - pattern, mask, dst, + src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, diff --git a/src/cairo_xlib_surface.c b/src/cairo_xlib_surface.c index f7acf2763..3eaef57e5 100644 --- a/src/cairo_xlib_surface.c +++ b/src/cairo_xlib_surface.c @@ -618,8 +618,8 @@ _render_operator (cairo_operator_t operator) static cairo_int_status_t _cairo_xlib_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_mask, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, @@ -630,56 +630,64 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, unsigned int width, unsigned int height) { - cairo_surface_attributes_t attributes; + cairo_surface_attributes_t src_attr, mask_attr; cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; - cairo_xlib_surface_t *mask = (cairo_xlib_surface_t *) generic_mask; - cairo_surface_t *mask_clone = NULL; + cairo_xlib_surface_t *mask; cairo_int_status_t status; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; - /* XXX This stuff can go when we change the mask to be a pattern also. */ - if (generic_mask && (generic_mask->backend != dst->base.backend || - mask->dpy != dst->dpy)) { - status = _cairo_surface_clone_similar (abstract_dst, generic_mask, - &mask_clone); - if (status) - return status; - - mask = (cairo_xlib_surface_t *) mask_clone; - } - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); + status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, + &dst->base, + src_x, src_y, + mask_x, mask_y, + width, height, + (cairo_surface_t **) &src, + (cairo_surface_t **) &mask, + &src_attr, &mask_attr); if (status) - { - if (mask_clone) - cairo_surface_destroy (mask_clone); - return status; - } - status = _cairo_xlib_surface_set_attributes (src, &attributes); + status = _cairo_xlib_surface_set_attributes (src, &src_attr); if (CAIRO_OK (status)) - XRenderComposite (dst->dpy, - _render_operator (operator), - src->picture, - mask ? mask->picture : 0, - dst->picture, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - mask_x, mask_y, - dst_x, dst_y, - width, height); - - if (mask_clone) - cairo_surface_destroy (mask_clone); + { + if (mask) + { + status = _cairo_xlib_surface_set_attributes (mask, &mask_attr); + if (CAIRO_OK (status)) + XRenderComposite (dst->dpy, + _render_operator (operator), + src->picture, + mask->picture, + dst->picture, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + mask_x + mask_attr.x_offset, + mask_y + mask_attr.y_offset, + dst_x, dst_y, + width, height); + } + else + { + XRenderComposite (dst->dpy, + _render_operator (operator), + src->picture, + 0, + dst->picture, + src_x + src_attr.x_offset, + src_y + src_attr.y_offset, + 0, 0, + dst_x, dst_y, + width, height); + } + } + + if (mask) + _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr); - _cairo_pattern_release_surface (&dst->base, &src->base, &attributes); + _cairo_pattern_release_surface (&dst->base, &src->base, &src_attr); return status; } diff --git a/src/cairoint.h b/src/cairoint.h index f46588ec6..c840737a1 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -589,7 +589,7 @@ typedef struct _cairo_surface_backend { cairo_int_status_t (*composite) (cairo_operator_t operator, cairo_pattern_t *src, - cairo_surface_t *mask, + cairo_pattern_t *mask, void *dst, int src_x, int src_y, @@ -1427,8 +1427,8 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface, cairo_private cairo_status_t _cairo_surface_composite (cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *mask, + cairo_pattern_t *src, + cairo_pattern_t *mask, cairo_surface_t *dst, int src_x, int src_y, @@ -1730,6 +1730,21 @@ _cairo_pattern_release_surface (cairo_surface_t *dst, cairo_surface_t *surface, cairo_surface_attributes_t *attributes); +cairo_private cairo_int_status_t +_cairo_pattern_acquire_surfaces (cairo_pattern_t *src, + cairo_pattern_t *mask, + cairo_surface_t *dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + unsigned int width, + unsigned int height, + cairo_surface_t **src_out, + cairo_surface_t **mask_out, + cairo_surface_attributes_t *src_attributes, + cairo_surface_attributes_t *mask_attributes); + /* cairo_unicode.c */ |