summaryrefslogtreecommitdiff
path: root/src/cairo-clip-surface.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-05-11 22:38:27 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-05-11 23:14:21 +0100
commit6cd1f5040fed1385c2990a68d6017a7ca6c37103 (patch)
tree8da5bd7afbcc123d41ddf841d268d02697662781 /src/cairo-clip-surface.c
parent4ea3ace6c810ba090464e48795fac5456f6cdc24 (diff)
clip: Apply clip boxes to the clip surface
As we convert the unaligned clip boxes to a region, we need to process the intersection of the boxes with the clip surface as a separate step. Fixes tighten-box for the base compositor. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-clip-surface.c')
-rw-r--r--src/cairo-clip-surface.c86
1 files changed, 77 insertions, 9 deletions
diff --git a/src/cairo-clip-surface.c b/src/cairo-clip-surface.c
index 523cd424..fff97240 100644
--- a/src/cairo-clip-surface.c
+++ b/src/cairo-clip-surface.c
@@ -91,6 +91,33 @@ _cairo_clip_combine_with_surface (const cairo_clip_t *clip,
return status;
}
+static cairo_status_t
+_cairo_path_fixed_add_box (cairo_path_fixed_t *path,
+ const cairo_box_t *box,
+ cairo_fixed_t fx,
+ cairo_fixed_t fy)
+{
+ cairo_status_t status;
+
+ status = _cairo_path_fixed_move_to (path, box->p1.x + fx, box->p1.y + fy);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p1.y + fy);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p2.y + fy);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p1.x + fx, box->p2.y + fy);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_path_fixed_close_path (path);
+}
+
cairo_surface_t *
_cairo_clip_get_surface (const cairo_clip_t *clip,
cairo_surface_t *target,
@@ -98,16 +125,51 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
{
cairo_surface_t *surface;
cairo_status_t status;
- cairo_clip_t *copy;
+ cairo_clip_t *copy, *region;
cairo_clip_path_t *copy_path, *clip_path;
- surface = _cairo_surface_create_similar_solid (target,
- CAIRO_CONTENT_ALPHA,
- clip->extents.width,
- clip->extents.height,
- CAIRO_COLOR_WHITE);
- if (unlikely (surface->status))
- return surface;
+ if (clip->num_boxes) {
+ cairo_path_fixed_t path;
+ int i;
+
+ surface = _cairo_surface_create_similar_solid (target,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_TRANSPARENT);
+ if (unlikely (surface->status))
+ return surface;
+
+ _cairo_path_fixed_init (&path);
+ status = CAIRO_STATUS_SUCCESS;
+ for (i = 0; status == CAIRO_STATUS_SUCCESS && i < clip->num_boxes; i++) {
+ status = _cairo_path_fixed_add_box (&path, &clip->boxes[i],
+ -_cairo_fixed_from_int (clip->extents.x),
+ -_cairo_fixed_from_int (clip->extents.y));
+ }
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = _cairo_surface_fill (surface,
+ CAIRO_OPERATOR_ADD,
+ &_cairo_pattern_white.base,
+ &path,
+ CAIRO_FILL_RULE_WINDING,
+ 1.,
+ CAIRO_ANTIALIAS_DEFAULT,
+ NULL);
+ _cairo_path_fixed_fini (&path);
+ if (unlikely (status)) {
+ cairo_surface_destroy (surface);
+ return _cairo_surface_create_in_error (status);
+ }
+ } else {
+ surface = _cairo_surface_create_similar_solid (target,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_WHITE);
+ if (unlikely (surface->status))
+ return surface;
+ }
copy = _cairo_clip_copy_with_translation (clip,
-clip->extents.x,
@@ -115,6 +177,10 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
copy_path = copy->path;
copy->path = NULL;
+ region = copy;
+ if (! _cairo_clip_is_region (copy))
+ region = _cairo_clip_copy_region (copy);
+
status = CAIRO_STATUS_SUCCESS;
clip_path = copy_path;
while (status == CAIRO_STATUS_SUCCESS && clip_path) {
@@ -125,12 +191,14 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias,
- copy);
+ region);
clip_path = clip_path->prev;
}
copy->path = copy_path;
_cairo_clip_destroy (copy);
+ if (region != copy)
+ _cairo_clip_destroy (region);
if (unlikely (status)) {
cairo_surface_destroy (surface);