Pass mask to composite operation as pattern

This commit is contained in:
David Reveman 2005-03-03 18:39:06 +00:00
parent a97f4cce5e
commit 50b5344d7d
21 changed files with 566 additions and 269 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;
/* XXX: this stuff can go when we change the mask to be a pattern. */
if (generic_mask && (generic_mask->backend != dst->base.backend))
{
status = _cairo_surface_clone_similar (abstract_dst, generic_mask,
&mask_clone);
if (status)
return status;
mask = (cairo_glitz_surface_t *) mask_clone;
}
status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
src_x, src_y, width, height,
&src, &attributes);
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)
{
if (mask_clone)
cairo_surface_destroy (mask_clone);
return status;
_cairo_glitz_surface_set_attributes (src, &src_attr);
if (mask)
{
_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);
if (mask_attr.n_params)
free (mask_attr.params);
_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 (src_attr.n_params)
free (src_attr.params);
if (attributes.n_params)
free (attributes.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;

View file

@ -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);

View file

@ -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)
return status;
status = _cairo_image_surface_set_attributes (src, &src_attr);
if (CAIRO_OK (status))
{
if (mask)
_cairo_surface_release_source_image (&dst->base, mask, extra);
return status;
{
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);
}
}
status = _cairo_image_surface_set_attributes (src, &attributes);
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);
_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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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,

View file

@ -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,

View file

@ -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)
{
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_clone)
cairo_surface_destroy (mask_clone);
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;
}

View file

@ -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;

View file

@ -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;
/* XXX: this stuff can go when we change the mask to be a pattern. */
if (generic_mask && (generic_mask->backend != dst->base.backend))
{
status = _cairo_surface_clone_similar (abstract_dst, generic_mask,
&mask_clone);
if (status)
return status;
mask = (cairo_glitz_surface_t *) mask_clone;
}
status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
src_x, src_y, width, height,
&src, &attributes);
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)
{
if (mask_clone)
cairo_surface_destroy (mask_clone);
return status;
_cairo_glitz_surface_set_attributes (src, &src_attr);
if (mask)
{
_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);
if (mask_attr.n_params)
free (mask_attr.params);
_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 (src_attr.n_params)
free (src_attr.params);
if (attributes.n_params)
free (attributes.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;

View file

@ -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);

View file

@ -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)
return status;
status = _cairo_image_surface_set_attributes (src, &src_attr);
if (CAIRO_OK (status))
{
if (mask)
_cairo_surface_release_source_image (&dst->base, mask, extra);
return status;
{
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);
}
}
status = _cairo_image_surface_set_attributes (src, &attributes);
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);
_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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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)
{
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_clone)
cairo_surface_destroy (mask_clone);
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;
}

View file

@ -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 */