[cairo-commit] 2 commits - src/cairo-clip.c src/cairo-clip-private.h src/cairo-image-source.c src/cairo-surface-wrapper.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Sep 20 06:29:54 PDT 2011


 src/cairo-clip-private.h    |    3 +
 src/cairo-clip.c            |  107 ++++++++++++++++++++++++++++++++++++++++++++
 src/cairo-image-source.c    |   29 +++++++++--
 src/cairo-surface-wrapper.c |    8 ---
 4 files changed, 134 insertions(+), 13 deletions(-)

New commits:
commit 5f0dcf610f8714dcffe49c3ea6edea479590c34b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 20 14:05:31 2011 +0100

    image: clip the replay to the sample extents in device space
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index 4c2c1d2..da6dc08 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -623,7 +623,7 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
     if (_cairo_surface_get_extents (source, &limit)) {
 	if (sample->x >= limit.x &&
 	    sample->y >= limit.y &&
-	    sample->x + sample->width <= limit.x + limit.width &&
+	    sample->x + sample->width  <= limit.x + limit.width &&
 	    sample->y + sample->height <= limit.y + limit.height)
 	{
 	    extend = CAIRO_EXTEND_NONE;
@@ -640,9 +640,29 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
 	extend = CAIRO_EXTEND_NONE;
 
     if (extend == CAIRO_EXTEND_NONE) {
-	limit = *extents;
 	if (! _cairo_rectangle_intersect (&limit, sample))
 	    return _pixman_transparent_image ();
+
+	if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
+	    double x1, y1, x2, y2;
+
+	    matrix = pattern->base.matrix;
+	    status = cairo_matrix_invert (&matrix);
+	    assert (status == CAIRO_STATUS_SUCCESS);
+
+	    x1 = limit.x;
+	    y1 = limit.y;
+	    x2 = limit.x + limit.width;
+	    y2 = limit.y + limit.height;
+
+	    _cairo_matrix_transform_bounding_box (&matrix,
+						  &x1, &y1, &x2, &y2, NULL);
+
+	    limit.x = floor (x1);
+	    limit.y = floor (y1);
+	    limit.width  = ceil (x2) - limit.x;
+	    limit.height = ceil (y2) - limit.y;
+	}
     }
 
     if (dst->base.content == source->content)
@@ -652,7 +672,7 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
 	clone = _cairo_image_surface_create_with_content (source->content,
 							  limit.width,
 							  limit.height);
-    cairo_surface_set_device_offset (clone, limit.x, limit.y);
+    cairo_surface_set_device_offset (clone, -limit.x, -limit.y);
 
     m = NULL;
     if (extend == CAIRO_EXTEND_NONE) {
@@ -662,9 +682,6 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
 			       &pattern->base.matrix);
 	if (tx | ty)
 	    cairo_matrix_translate (m, tx, ty);
-
-	status = cairo_matrix_invert (m);
-	assert (status == CAIRO_STATUS_SUCCESS);
     } else {
 	/* XXX extract scale factor for repeating patterns */
     }
commit da95bdfcd77c56a52e08544946786cff8a33ca1e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 20 14:04:29 2011 +0100

    wrapper: transform the clip into device space
    
    We need more than just mere translation!
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index a682ce4..aaf16f3 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -103,6 +103,9 @@ cairo_private cairo_clip_t *
 _cairo_clip_translate (cairo_clip_t *clip, int tx, int ty);
 
 cairo_private cairo_clip_t *
+_cairo_clip_transform (cairo_clip_t *clip, const cairo_matrix_t *m);
+
+cairo_private cairo_clip_t *
 _cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty);
 
 cairo_private cairo_bool_t
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 44f4e7b..11ba54d 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -452,6 +452,113 @@ _cairo_clip_translate (cairo_clip_t *clip, int tx, int ty)
     return clip;
 }
 
+static cairo_status_t
+_cairo_path_fixed_add_box (cairo_path_fixed_t *path,
+			   const cairo_box_t *box)
+{
+    cairo_status_t status;
+
+    status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y);
+    if (unlikely (status))
+	return status;
+
+    return _cairo_path_fixed_close_path (path);
+}
+
+static cairo_status_t
+_cairo_path_fixed_init_from_boxes (cairo_path_fixed_t *path,
+				   const cairo_boxes_t *boxes)
+{
+    cairo_status_t status;
+    const struct _cairo_boxes_chunk *chunk;
+    int i;
+
+    _cairo_path_fixed_init (path);
+    if (boxes->num_boxes == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
+	for (i = 0; i < chunk->count; i++) {
+	    status = _cairo_path_fixed_add_box (path, &chunk->base[i]);
+	    if (unlikely (status)) {
+		_cairo_path_fixed_fini (path);
+		return status;
+	    }
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_clip_t *
+_cairo_clip_intersect_clip_path_transformed (cairo_clip_t *clip,
+					     const cairo_clip_path_t *clip_path,
+					     const cairo_matrix_t *m)
+{
+    cairo_path_fixed_t path;
+
+    if (clip_path->prev)
+	clip = _cairo_clip_intersect_clip_path_transformed (clip,
+							    clip_path->prev,
+							    m);
+
+    if (_cairo_path_fixed_init_copy (&path, &clip_path->path))
+	return _cairo_clip_set_all_clipped (clip);
+
+    clip =  _cairo_clip_intersect_path (clip,
+				       &path,
+				       clip_path->fill_rule,
+				       clip_path->tolerance,
+				       clip_path->antialias);
+    _cairo_path_fixed_fini (&path);
+
+    return clip;
+}
+
+cairo_clip_t *
+_cairo_clip_transform (cairo_clip_t *clip, const cairo_matrix_t *m)
+{
+    cairo_clip_t *copy;
+
+    if (_cairo_matrix_is_translation (m))
+	return _cairo_clip_translate (clip, m->x0, m->y0);
+
+    copy = _cairo_clip_create ();
+
+    if (clip->num_boxes) {
+	cairo_path_fixed_t path;
+	cairo_boxes_t boxes;
+
+	_cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
+	_cairo_path_fixed_init_from_boxes (&path, &boxes);
+	_cairo_path_fixed_transform (&path, m);
+
+	copy = _cairo_clip_intersect_path (copy, &path,
+					   CAIRO_FILL_RULE_WINDING,
+					   0.1,
+					   CAIRO_ANTIALIAS_DEFAULT);
+
+	_cairo_path_fixed_fini (&path);
+    }
+
+    if (clip->path)
+	copy = _cairo_clip_intersect_clip_path_transformed (copy, clip->path,m);
+
+    return copy;
+}
+
 cairo_clip_t *
 _cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty)
 {
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 48bd30a..00d9aa3 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -127,12 +127,7 @@ _cairo_surface_wrapper_get_clip (cairo_surface_wrapper_t *wrapper,
 					  -wrapper->extents.x,
 					  -wrapper->extents.y);
     }
-    if (! _cairo_matrix_is_identity (&wrapper->transform)) {
-	/* XXX */
-	copy = _cairo_clip_translate (copy,
-				      wrapper->transform.x0,
-				      wrapper->transform.y0);
-    }
+    copy = _cairo_clip_transform (copy, &wrapper->transform);
     if (! _cairo_matrix_is_identity (&wrapper->target->device_transform)) {
 	/* XXX */
 	copy = _cairo_clip_translate (copy,
@@ -562,7 +557,6 @@ _cairo_surface_wrapper_set_inverse_transform (cairo_surface_wrapper_t *wrapper,
 
 	wrapper->needs_transform = TRUE;
     }
-
 }
 
 void


More information about the cairo-commit mailing list