[cairo] [Patch] Adjustments to XTransform in the xlib backend

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Thu Sep 18 10:46:50 PDT 2008

Soeren Sandmann wrote:
> The xlib test suite fails in some variants of the
> rotate-image-surface-paint test. This is due to the lack of an
> adjustment of the transformation matrix that is done in the image
> backend, but not in the xlib backend. The adjustment in question is
> documented by this comment:
>         /* The conversion above breaks cairo's translation invariance:
>          * a translation of (a, b) in device space translates to
>          * a translation of (xx * a + xy * b, yx * a + yy * b)
>          * 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
>          * space and adjust pixman's transform to agree with cairo's
>         at
>          * that point. */
> in cairo-matrix.c. I don't fully understand what the adjustment is
> trying to accomplish, but if it is necessary for the image backend, it
> is probably also necessary for the RENDER one since they have the same
> precision issues.

The point of the adjustment is to improve translation invariance of
transformed patterns; in particular a pattern should look the same
if translated an integral number of pixels.

Without the adjustment, the following scenario is possible:

Say xx = yy = 0.51 (and xy = yx = 0) in cairo's matrix, but its rounded
pixman equivalent has xx = yy = 0.5. (In reality, the rounding error
will be smaller.)

Now that means that for every 100 pixel in device space, pixman's sample
coordinate is 1 pixel off from cairo's intended sample coordinate. There
is nothing we can do about that without increasing pixman's precision,
or lowering cairo's.

In fact there's often only one point where pixman's and cairo's
transformation agree - I call that the 'anchor' below. What the
adjustment does is change the position of the anchor.

Without the adjustment in _cairo_matrix_to_pixman_matrix, the anchor
is (close to) the device space origin. As a result, the sample position
would also be off by 1 if we simply translate the pattern by 100 pixels
in device space, breaking translation invariance.

The adjustment instead makes the pattern origin the anchor.
To accomplish that, it transforms the pattern origin (0,0) to device
space using *cairo*'s matrix, and then adjusts pixman's matrix so that
transforming the anchor to pattern space will result in (0,0).

This recovers translation invariance.

(The choice of the pattern origin as the point of reference is
arbitrary, although justified by the fact that most patterns are
sampled near their origin.)

See also

> The attached patch fixes, but someone who understands why the
> adjustment is done should probably look it over.

Yes, the patch makes perfect sense.


More information about the cairo mailing list