mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 18:08:03 +02:00
V5: Use NEAREST filter when possible
(changed to use determinant funciton and remove debug printf) Modifies _cairo_matrix_has_unity_scale to return true for 90 degree rotations by allowing error caused by inaccuracy in trig functions. This fails after 14 additions of M_PI_2 to itself as a float argument to cairo_rotate, but the failure is in the detection of the integer translate, not in the trig components. I believe this is due to the matrix inversion, which may need similar rounding. Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
This commit is contained in:
parent
7d44f8d47e
commit
1d9f4ae520
3 changed files with 26 additions and 20 deletions
|
|
@ -748,23 +748,32 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#define SCALING_EPSILON _cairo_fixed_to_double(1)
|
||||
|
||||
/* This only returns true if the matrix is 90 degree rotations or
|
||||
* flips. It appears calling code is relying on this. It will return
|
||||
* false for other rotations even if the scale is one. Approximations
|
||||
* are allowed to handle matricies filled in using trig functions
|
||||
* such as sin(M_PI_2).
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_matrix_has_unity_scale (const cairo_matrix_t *matrix)
|
||||
{
|
||||
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;
|
||||
|
||||
return TRUE;
|
||||
/* check that the determinant is near +/-1 */
|
||||
double det = _cairo_matrix_compute_determinant (matrix);
|
||||
if (fabs (det * det - 1.0) < SCALING_EPSILON) {
|
||||
/* check that one axis is close to zero */
|
||||
if (fabs (matrix->xy) < SCALING_EPSILON &&
|
||||
fabs (matrix->yx) < SCALING_EPSILON)
|
||||
return TRUE;
|
||||
if (fabs (matrix->xx) < SCALING_EPSILON &&
|
||||
fabs (matrix->yy) < SCALING_EPSILON)
|
||||
return TRUE;
|
||||
/* If rotations are allowed then it must instead test for
|
||||
* orthogonality. This is xx*xy+yx*yy ~= 0.
|
||||
*/
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* By pixel exact here, we mean a matrix that is composed only of
|
||||
|
|
|
|||
|
|
@ -3363,6 +3363,7 @@ _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
|
|||
case CAIRO_FILTER_GOOD:
|
||||
case CAIRO_FILTER_BEST:
|
||||
case CAIRO_FILTER_BILINEAR:
|
||||
case CAIRO_FILTER_FAST:
|
||||
/* If source pixels map 1:1 onto destination pixels, we do
|
||||
* not need to filter (and do not want to filter, since it
|
||||
* will cause blurriness)
|
||||
|
|
@ -3381,7 +3382,6 @@ _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
|
|||
}
|
||||
break;
|
||||
|
||||
case CAIRO_FILTER_FAST:
|
||||
case CAIRO_FILTER_NEAREST:
|
||||
case CAIRO_FILTER_GAUSSIAN:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -414,8 +414,7 @@ _pattern_is_supported (uint32_t flags,
|
|||
cairo_filter_t filter;
|
||||
|
||||
filter = pattern->filter;
|
||||
if (_cairo_matrix_has_unity_scale (&pattern->matrix) &&
|
||||
_cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
|
||||
if (_cairo_matrix_is_pixel_exact (&pattern->matrix))
|
||||
{
|
||||
filter = CAIRO_FILTER_NEAREST;
|
||||
}
|
||||
|
|
@ -1033,9 +1032,7 @@ _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
|
|||
|
||||
filter = pattern->base.filter;
|
||||
if (filter != CAIRO_FILTER_NEAREST &&
|
||||
_cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
|
||||
_cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.x0)) &&
|
||||
_cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.y0)))
|
||||
_cairo_matrix_is_pixel_exact (&pattern->base.matrix))
|
||||
{
|
||||
filter = CAIRO_FILTER_NEAREST;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue