[clip] Apply surface offset when combining with clip mask

In order to correctly combine the clip mask with the compositing mask the
clip path must be offset so that it is relative to the destination
surface.
This commit is contained in:
Chris Wilson 2009-08-29 14:15:07 +01:00
parent 21225a7163
commit 8a323d7c89
7 changed files with 56 additions and 57 deletions

View file

@ -116,7 +116,7 @@ _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,
int dst_x, int dst_y);
const cairo_rectangle_int_t *extents);
cairo_private cairo_int_status_t
_cairo_clip_get_region (cairo_clip_t *clip,

View file

@ -973,6 +973,31 @@ _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_combine_region (cairo_surface_t *surface,
const cairo_region_t *region,
const cairo_rectangle_int_t *extents)
{
cairo_region_t clear_region;
cairo_status_t status;
_cairo_region_init_rectangle (&clear_region, extents);
status = cairo_region_subtract (&clear_region, region);
if (unlikely (status))
return status;
if (! cairo_region_is_empty (&clear_region)) {
cairo_region_translate (&clear_region, -extents->x, -extents->y);
status = _cairo_surface_fill_region (surface,
CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
}
_cairo_region_fini (&clear_region);
return status;
}
static cairo_surface_t *
_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
cairo_surface_t *target)
@ -1019,7 +1044,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
if (unlikely (_cairo_status_is_error (status)))
goto BAIL;
need_translate = clip_extents->x || clip_extents->y;
need_translate = clip_extents->x | clip_extents->y;
if (status == CAIRO_STATUS_SUCCESS) {
if (need_translate) {
cairo_region_translate (clip_path->region,
@ -1069,18 +1094,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
goto BAIL;
if (status == CAIRO_STATUS_SUCCESS) {
if (need_translate) {
cairo_region_translate (prev->region,
-clip_extents->x, -clip_extents->y);
}
status = _cairo_surface_fill_region (surface,
CAIRO_OPERATOR_IN,
CAIRO_COLOR_WHITE,
prev->region);
if (need_translate) {
cairo_region_translate (prev->region,
clip_extents->x, clip_extents->y);
}
status = _combine_region (surface, prev->region, clip_extents);
if (unlikely (status))
goto BAIL;
} else if (prev->path.is_rectilinear) {
@ -1166,6 +1180,7 @@ _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
clip_path->region == NULL ? "no" : "yes",
clip_path->surface == NULL ? "no" : "yes");
_cairo_debug_print_path (stream, &clip_path->path);
fprintf (stream, "\n");
} while ((clip_path = clip_path->prev) != NULL);
}
@ -1179,12 +1194,11 @@ _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
cairo_status_t
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x,
int dst_y)
const cairo_rectangle_int_t *extents)
{
cairo_pattern_union_t pattern;
cairo_clip_path_t *clip_path = clip->path;
cairo_bool_t translate;
cairo_bool_t need_translate;
cairo_status_t status;
assert (clip_path != NULL);
@ -1195,8 +1209,8 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
_cairo_pattern_init_for_surface (&pattern.surface,
clip_path->surface);
cairo_matrix_init_translate (&pattern.base.matrix,
dst_x - clip_path->extents.x,
dst_y - clip_path->extents.y);
extents->x - clip_path->extents.x,
extents->y - clip_path->extents.y);
status = _cairo_surface_paint (dst,
CAIRO_OPERATOR_IN,
&pattern.base,
@ -1211,26 +1225,14 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
translate = dst_x | dst_y;
need_translate = extents->x | 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 (translate)
cairo_region_translate (clip_path->region, -dst_x, -dst_y);
status = _cairo_surface_fill_region (dst,
CAIRO_OPERATOR_IN,
CAIRO_COLOR_WHITE,
clip_path->region);
if (translate)
cairo_region_translate (clip_path->region, dst_x, dst_y);
return status;
}
if (status == CAIRO_STATUS_SUCCESS)
return _combine_region (dst, clip_path->region, extents);
if (clip_path->surface != NULL &&
clip_path->surface->backend == dst->backend)
@ -1238,8 +1240,8 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
_cairo_pattern_init_for_surface (&pattern.surface,
clip_path->surface);
cairo_matrix_init_translate (&pattern.base.matrix,
dst_x - clip_path->extents.x,
dst_y - clip_path->extents.y);
extents->x - clip_path->extents.x,
extents->y - clip_path->extents.y);
status = _cairo_surface_paint (dst,
CAIRO_OPERATOR_IN,
&pattern.base,
@ -1250,10 +1252,10 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
return status;
}
if (translate) {
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (-dst_x),
_cairo_fixed_from_int (-dst_y));
_cairo_fixed_from_int (-extents->x),
_cairo_fixed_from_int (-extents->y));
}
status = _cairo_surface_fill (dst,
CAIRO_OPERATOR_IN,
@ -1263,11 +1265,12 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
clip_path->tolerance,
clip_path->antialias,
NULL);
if (translate) {
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (dst_x),
_cairo_fixed_from_int (dst_y));
_cairo_fixed_from_int (extents->x),
_cairo_fixed_from_int (extents->y));
}
if (unlikely (status))
return status;
} while ((clip_path = clip_path->prev) != NULL);

View file

@ -426,7 +426,7 @@ slim_hidden_def (cairo_region_status);
* Since: 1.10
**/
cairo_status_t
cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other)
cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other)
{
if (dst->status)
return dst->status;
@ -434,8 +434,12 @@ cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other)
if (other->status)
return _cairo_region_set_error (dst, other->status);
if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, &other->rgn))
if (! pixman_region32_subtract (&dst->rgn,
&dst->rgn,
CONST_CAST &other->rgn))
{
return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -163,12 +163,8 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
if (unlikely (status))
goto CLEANUP_SURFACE;
if (clip_surface) {
status = _cairo_clip_combine_with_surface (clip,
mask,
extents->x,
extents->y);
}
if (clip_surface)
status = _cairo_clip_combine_with_surface (clip, mask, extents);
_cairo_pattern_init_for_surface (mask_pattern, mask);

View file

@ -264,9 +264,7 @@ _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
continue;
_left = left;
if (_left.p1.x <= limits->p1.x &&
_left.p2.x <= limits->p1.x)
{
if (_left.p1.x < limits->p1.x) {
_left.p1.x = limits->p1.x;
_left.p1.y = limits->p1.y;
_left.p2.x = limits->p1.x;
@ -274,9 +272,7 @@ _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
}
_right = right;
if (_right.p1.x >= limits->p2.x &&
_right.p2.x >= limits->p2.x)
{
if (_right.p1.x > limits->p2.x) {
_right.p1.x = limits->p2.x;
_right.p1.y = limits->p1.y;
_right.p2.x = limits->p2.x;

View file

@ -2518,7 +2518,7 @@ cairo_public void
cairo_region_translate (cairo_region_t *region, int dx, int dy);
cairo_public cairo_status_t
cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other);
cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other);
cairo_public cairo_status_t
cairo_region_subtract_rectangle (cairo_region_t *dst,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB