[cairo] [PATCH] V3: Use NEAREST filter when possible

Chris Wilson chris at chris-wilson.co.uk
Tue Aug 12 11:59:53 PDT 2014


On Tue, Aug 12, 2014 at 11:47:58AM -0700, Bill Spitzak wrote:
> Further fix to use a #define for the epsilon value.
> 
> Make _cairo_matrix_has_unity_scale return true for approximate 90 rotations
> to work around inaccuracy of sin/cos(M_PI_2).
> 
> 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.
> ---
>  src/cairo-matrix.c             |   39 +++++++++++++++++++++++++--------------
>  src/cairo-pattern.c            |    2 +-
>  src/cairo-xcb-surface-render.c |    7 ++-----
>  3 files changed, 28 insertions(+), 20 deletions(-)
> 
> diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
> index ba975be..881e37d 100644
> --- a/src/cairo-matrix.c
> +++ b/src/cairo-matrix.c
> @@ -748,23 +748,34 @@ _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 dsquared = matrix->xx * matrix->yy - matrix->xy * matrix->yx;
> +    printf("d is %g\n", dsquared);
> +    dsquared *= dsquared;
> +    if (fabs (dsquared - 1.0) < SCALING_EPSILON) {

double det = _cairo_matrix_compute_determinant(matrix);
if (fabs(det * det - 1.0) < SCALING_EPSILON) {

With that minor adjustment,

Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the cairo mailing list