diff options
Diffstat (limited to 'src/cairo-matrix.c')
-rw-r--r-- | src/cairo-matrix.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index b644dec8..6dfe537f 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -865,7 +865,9 @@ _cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radi void _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, - pixman_transform_t *pixman_transform) + pixman_transform_t *pixman_transform, + double xc, + double yc) { static const pixman_transform_t pixman_identity_transform = {{ {1 << 16, 0, 0}, @@ -875,11 +877,9 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, if (_cairo_matrix_is_identity (matrix)) { *pixman_transform = pixman_identity_transform; - } - else { + } else { cairo_matrix_t inv; - double x,y; - pixman_vector_t vector; + unsigned max_iterations; 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); @@ -899,9 +899,10 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, * for cairo, while pixman uses rounded versions of xx ... yy. * This error increases as a and b get larger. * - * To compensate for this, we fix the point (0, 0) in pattern + * To compensate for this, we fix the point (xc, yc) in pattern * space and adjust pixman's transform to agree with cairo's at - * that point. */ + * that point. + */ if (_cairo_matrix_is_translation (matrix)) return; @@ -911,22 +912,38 @@ _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 (0, 0) */ - x = 0, y = 0; - 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 (0, 0). We can now compensate - * for the resulting error */ - pixman_transform->matrix[0][2] -= vector.vector[0]; - pixman_transform->matrix[1][2] -= vector.vector[1]; + /* find the pattern space coordinate that maps to (xc, yc) */ + xc += .5; yc += .5; /* offset for the pixel centre */ + max_iterations = 5; + 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). + * We can now compensate for the resulting error. + */ + x -= xc; + y -= yc; + 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 (--max_iterations); } } |