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

Chris Wilson <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
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 <[email protected]>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.