[cairo-commit] 2 commits - src/cairo-xcb-surface-render.c

Uli Schlachter psychon at kemper.freedesktop.org
Mon Jun 25 12:19:09 PDT 2012


 src/cairo-xcb-surface-render.c |   56 ++++++++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 17 deletions(-)

New commits:
commit 9f52261dd7941ec7b338b050479da25c2571f9ac
Author: Uli Schlachter <psychon at znc.in>
Date:   Sun Jun 3 19:35:37 2012 +0200

    xcb: Correctly handle a recording surface's extents
    
    The size of the target area doesn't really have much to do with the size of the
    recording surface that we are painting from. Thus, let's use the recording
    surface's size instead.
    
    Since we apply the transformation before replaying the recording surface, we
    need to transform the recording surface's size via the inverse of our pattern
    matrix to get the size in the target surface. This makes this a little more
    complex.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index c950f5c..adbf0df 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -46,6 +46,7 @@
 #include "cairo-traps-private.h"
 #include "cairo-recording-surface-inline.h"
 #include "cairo-paginated-private.h"
+#include "cairo-pattern-inline.h"
 
 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
 
@@ -1060,30 +1061,55 @@ record_to_picture (cairo_surface_t *target,
     cairo_status_t status;
     cairo_matrix_t matrix;
     cairo_surface_t *tmp;
-    cairo_surface_t *source = pattern->surface;
+    cairo_surface_t *source;
+    cairo_rectangle_int_t limit;
+    cairo_extend_t extend;
 
-    /* XXX: The following is more or less copied from cairo-xlibs-ource.c,
+    /* XXX: The following was once more or less copied from cairo-xlibs-ource.c,
      * record_source() and recording_pattern_get_surface(), can we share a
      * single version?
      */
 
-    /* First get the 'real' recording surface */
-    if (_cairo_surface_is_paginated (source))
-	source = _cairo_paginated_surface_get_recording (source);
-    if (_cairo_surface_is_snapshot (source))
-	source = _cairo_surface_snapshot_get_target (source);
+    /* First get the 'real' recording surface and figure out the size for tmp */
+    source = _cairo_pattern_get_source (pattern, &limit);
     assert (_cairo_surface_is_recording (source));
 
+    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;
+    }
+    extend = pattern->base.extend;
+    if (_cairo_rectangle_contains_rectangle (&limit, extents))
+	extend = CAIRO_EXTEND_NONE;
+    if (extend == CAIRO_EXTEND_NONE && ! _cairo_rectangle_intersect (&limit, extents))
+	return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target);
+
     /* Now draw the recording surface to an xcb surface */
     tmp = _cairo_surface_create_similar_scratch (target,
 						 source->content,
-						 extents->width,
-						 extents->height);
+						 limit.width,
+						 limit.height);
     if (tmp->status != CAIRO_STATUS_SUCCESS) {
 	return (cairo_xcb_picture_t *) tmp;
     }
 
-    cairo_matrix_init_translate (&matrix, extents->x, extents->y);
+    cairo_matrix_init_translate (&matrix, limit.x, limit.y);
     cairo_matrix_multiply (&matrix, &matrix, &pattern->base.matrix);
 
     status = _cairo_recording_surface_replay_with_clip (source,
@@ -1097,7 +1123,7 @@ record_to_picture (cairo_surface_t *target,
     /* Now that we have drawn this to an xcb surface, try again with that */
     _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
     tmp_pattern.surface = tmp;
-    cairo_matrix_init_translate (&tmp_pattern.base.matrix, -extents->x, -extents->y);
+    cairo_matrix_init_translate (&tmp_pattern.base.matrix, -limit.x, -limit.y);
 
     picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
     if (picture->base.status == CAIRO_STATUS_SUCCESS)
commit e704f64d8fcceb220c8c99092c19c2cfd4bd9330
Author: Uli Schlachter <psychon at znc.in>
Date:   Sun Jun 3 16:53:49 2012 +0200

    xcb: Handle recording surfaces differently
    
    Let's say we are painting recording surface 'source' to xcb surface 'target' by
    replaying the source to a temporary surface 'tmp'.
    
    Previously, the xcb backend replayed the recording surface to tmp with just a
    translation and then used that as its source surface with the pattern's
    transformation. That means 'tmp' used the same coordinate system as 'source'.
    
    This patch changes this so that the transformation is applied during the replay
    and painting from 'tmp' to 'target' is just a simple translation, so 'tmp' now
    uses the same coordinate system as 'target'.
    
    This should produce way less better results, because transforming a recording
    surface should have less artifacts than transforming a raster surface.
    
    Fixes: record1414x-* record2x-* record90-* ps-surface-source
    
    Breaks (or rather, "exposes unrelated bug that I have not yet figured out in"):
    record-extend-*-similar
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 7736ed8..c950f5c 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -1084,6 +1084,8 @@ record_to_picture (cairo_surface_t *target,
     }
 
     cairo_matrix_init_translate (&matrix, extents->x, extents->y);
+    cairo_matrix_multiply (&matrix, &matrix, &pattern->base.matrix);
+
     status = _cairo_recording_surface_replay_with_clip (source,
 							&matrix, tmp,
 							NULL);
@@ -1095,13 +1097,7 @@ record_to_picture (cairo_surface_t *target,
     /* Now that we have drawn this to an xcb surface, try again with that */
     _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
     tmp_pattern.surface = tmp;
-
-    if (extents->x | extents->y) {
-	cairo_matrix_t *pmatrix = &tmp_pattern.base.matrix;
-
-	cairo_matrix_init_translate (&matrix, -extents->x, -extents->y);
-	cairo_matrix_multiply (pmatrix, pmatrix, &matrix);
-    }
+    cairo_matrix_init_translate (&tmp_pattern.base.matrix, -extents->x, -extents->y);
 
     picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
     if (picture->base.status == CAIRO_STATUS_SUCCESS)


More information about the cairo-commit mailing list