commit 8509bb51a947f6e966228fe8879000be5461e29c Author: Owen W. Taylor Date: Fri Apr 4 23:45:19 2008 -0400 Make pattern bounds tighter for pixel-exact transformations cairo-matrix.c cairoint.: Add _cairo_matrix_is_pixel_exact cairo-pattern.c: Treat pixel-exact transformations like they were always FILTER_NEAREST diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index d10d156..7262d90 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -600,6 +600,36 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix, return FALSE; } +/* By pixel exact here, we mean a matrix that is composed only of + * 90 degree rotations, flips, and and integer translations. If + * we transform an image with a pixel-exact matrix, filtering + * is not useful. + */ +cairo_private cairo_bool_t +_cairo_matrix_is_pixel_exact(const cairo_matrix_t *matrix) +{ + cairo_fixed_t x0_fixed, y0_fixed; + + if (matrix->xy == 0.0 && matrix->yx == 0.0) { + if (!(matrix->xx == 1.0 || matrix->xx == -1.0)) + return FALSE; + if (!(matrix->yy == 1.0 || matrix->yy == -1.0)) + return FALSE; + } else if (matrix->xx == 0.0 && matrix->yy == 0.0) { + if (!(matrix->xy == 1.0 || matrix->xy == -1.0)) + return FALSE; + if (!(matrix->yx == 1.0 || matrix->yx == -1.0)) + return FALSE; + } else { + return FALSE; + } + + x0_fixed = _cairo_fixed_from_double (matrix->x0); + y0_fixed = _cairo_fixed_from_double (matrix->y0); + + return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed); +} + /* A circle in user space is transformed into an ellipse in device space. diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index e1d4b5c..6aed729 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -2000,10 +2000,15 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern, case CAIRO_FILTER_GOOD: case CAIRO_FILTER_BEST: case CAIRO_FILTER_BILINEAR: - x1 -= 0.5; - y1 -= 0.5; - x2 += 0.5; - y2 += 0.5; + /* We assume that the backend will not blur out the image + * when a pixel-for-pixel copy is possible. + */ + if (!_cairo_matrix_is_pixel_exact(&imatrix)) { + x1 -= 0.5; + y1 -= 0.5; + x2 += 0.5; + y2 += 0.5; + } break; case CAIRO_FILTER_FAST: case CAIRO_FILTER_NEAREST: diff --git a/src/cairoint.h b/src/cairoint.h index 01ad567..768e6b3 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2051,6 +2051,9 @@ cairo_private cairo_bool_t _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix, int *itx, int *ity); +cairo_private cairo_bool_t +_cairo_matrix_is_pixel_exact(const cairo_matrix_t *matrix); + cairo_private double _cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);