[cairo-commit] 2 commits - src/cairo-image-surface.c src/cairo-matrix.c src/cairo-pattern.c test/scale-offset-image.ps.ref.png test/scale-offset-image.ref.png test/scale-offset-similar.ps.ref.png test/scale-offset-similar.ref.png

Chris Wilson ickle at kemper.freedesktop.org
Wed Nov 5 03:36:18 PST 2008


 src/cairo-image-surface.c            |    4 +-
 src/cairo-matrix.c                   |   53 +++++++++++++++++++++--------------
 src/cairo-pattern.c                  |    7 +++-
 test/scale-offset-image.ps.ref.png   |binary
 test/scale-offset-image.ref.png      |binary
 test/scale-offset-similar.ps.ref.png |binary
 test/scale-offset-similar.ref.png    |binary
 7 files changed, 39 insertions(+), 25 deletions(-)

New commits:
commit e811173311ebe76d47eebcf5c6c5c798f9d3ea72
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 5 10:59:15 2008 +0000

    [matrix] Compensate pixman_matrix in device space.
    
    We wish to reduce the visible error when converting to a pixman matrix, so
    perform the compensation in device space instead of pattern space.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index f84cf7f..0efdb7a 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1159,8 +1159,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
 	goto finish;
 
     status = _cairo_image_surface_set_attributes (src, &attributes,
-						  src_x + width / 2.,
-						  src_y + height / 2.);
+						  dst_x + width / 2.,
+						  dst_y + height / 2.);
     if (status)
 	goto CLEANUP_SOURCE;
 
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 555c4fe..0c7f305 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -879,8 +879,6 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
         *pixman_transform = pixman_identity_transform;
     } else {
         cairo_matrix_t inv;
-        double x,y;
-        pixman_vector_t vector;
 
         pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
         pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
@@ -913,24 +911,37 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
         if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
             return;
 
-        /* find the device space coordinate that maps to (xc, yc) */
-        x = xc, y = yc;
-        cairo_matrix_transform_point (&inv, &x, &y);
-
-        /* transform the resulting device space coordinate back
-         * to the pattern space, using pixman's transform */
-        vector.vector[0] = _cairo_fixed_16_16_from_double (x);
-        vector.vector[1] = _cairo_fixed_16_16_from_double (y);
-        vector.vector[2] = 1 << 16;
-
-        if (! pixman_transform_point_3d (pixman_transform, &vector))
-            return;
-
-        /* Ideally, the vector should now be (xc, yc). We can now compensate
-         * for the resulting error */
-        pixman_transform->matrix[0][2] +=
-	    _cairo_fixed_16_16_from_double (xc) - vector.vector[0];
-        pixman_transform->matrix[1][2] +=
-	    _cairo_fixed_16_16_from_double (yc) - vector.vector[1];
+        /* find the pattern space coordinate that maps to (xc, yc) */
+	xc += .5; yc += .5; /* offset for the pixel centre */
+	do {
+	    double x,y;
+	    pixman_vector_t vector;
+	    cairo_fixed_16_16_t dx, dy;
+
+	    vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
+	    vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
+	    vector.vector[2] = 1 << 16;
+
+	    if (! pixman_transform_point_3d (pixman_transform, &vector))
+		return;
+
+	    x = pixman_fixed_to_double (vector.vector[0]);
+	    y = pixman_fixed_to_double (vector.vector[1]);
+	    cairo_matrix_transform_point (&inv, &x, &y);
+
+	    /* Ideally, the vector should now be (xc, yc) [offset for pixel
+	     * centre]. We can now compensate for the resulting error.
+	     */
+	    x -= xc; x += .5;
+	    y -= yc; y += .5;
+	    cairo_matrix_transform_distance (matrix, &x, &y);
+	    dx = _cairo_fixed_16_16_from_double (x);
+	    dy = _cairo_fixed_16_16_from_double (y);
+	    pixman_transform->matrix[0][2] -= dx;
+	    pixman_transform->matrix[1][2] -= dy;
+
+	    if (dx == 0 && dy == 0)
+		break;
+	} while (TRUE);
     }
 }
commit c95eebc92316ad50840fab1cec6c14b6c3e50fa5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 5 09:56:02 2008 +0000

    [pattern] Split the translation between the matrix and [xy]_offset
    
    pixman limits the src] co-ordinates (and thus [xy]_offset] to 16bits,
    so we need to be careful how much of the translation vector to push into
    [xy]_offset. Since the range is the same for both, split the integer
    component between the matrix and the offset.
    
    test/scale-offset* now at least shows the source image, even if it is
    misplaced.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 5a6bf6c..9d476cd 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2000,8 +2000,11 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pat
 	assert (invert_status == CAIRO_STATUS_SUCCESS);
 
 	if (m.x0 != 0. || m.y0 != 0.) {
-	    x = floor (m.x0);
-	    y = floor (m.y0);
+	    /* pixman also limits the [xy]_offset to 16 bits so evenly
+	     * spread the bits between the two.
+	     */
+	    x = floor (m.x0 / 2);
+	    y = floor (m.y0 / 2);
 	    attr->x_offset -= x;
 	    attr->y_offset -= y;
 	    cairo_matrix_init_translate (&m, x, y);
diff --git a/test/scale-offset-image.ps.ref.png b/test/scale-offset-image.ps.ref.png
index b87612a..1aed28d 100644
Binary files a/test/scale-offset-image.ps.ref.png and b/test/scale-offset-image.ps.ref.png differ
diff --git a/test/scale-offset-image.ref.png b/test/scale-offset-image.ref.png
index 325bdf4..8c6b0fe 100644
Binary files a/test/scale-offset-image.ref.png and b/test/scale-offset-image.ref.png differ
diff --git a/test/scale-offset-similar.ps.ref.png b/test/scale-offset-similar.ps.ref.png
index a60e9ad..7002b2e 100644
Binary files a/test/scale-offset-similar.ps.ref.png and b/test/scale-offset-similar.ps.ref.png differ
diff --git a/test/scale-offset-similar.ref.png b/test/scale-offset-similar.ref.png
index 325bdf4..8c6b0fe 100644
Binary files a/test/scale-offset-similar.ref.png and b/test/scale-offset-similar.ref.png differ


More information about the cairo-commit mailing list