[cairo] Path_extents after coordinate system is rotated.

Uli Schlachter psychon at znc.in
Sat Apr 11 00:05:16 PDT 2015


Am 11.04.2015 um 04:43 schrieb Lawrence D'Oliveiro:
> On Wed, 08 Apr 2015 15:05:31 +0200, Stefan Salewski wrote:
> 
>> Seems that new path_extents() after rotation is not
>> calculated from path itself, but from initial path_extents().
> 
> Ah, but what happens if you, say, rotate the coordinate system before
> constructing the path, and leave it rotated while asking for the
> path_extents?
[...]

The user -> surface coordinate transformation matrix is applied while the path
is constructed. So when you rotate by 90° and move to point (0, 1), cairo
internally records a move to (1, 0). Thanks to this, later transformations do
not influence earlier path operations. The user coordinate system only exists in
the API.

When you request the extents of a path, these extents are, too, first calculated
in the surface coordinate system. Then the four corners of this rectangle are
transformed into user space and a new bounding rectangle is computed.

> However,
> 
>     print \
>       (
>         ctx
>             .identity_matrix()
>             .new_path()
>             .rotate(45 * qahirah.deg)
>             .rectangle(path_rect)
>             .path_extents
>       )
> 
> prints
> 
>     Rect(-0.999893, -0.999893, 1.99979, 1.99979)

ASCII art in the coordinate space including the rotation / in the context
coordinate system (the inner rectangle is what we want to draw, the outer
rectangle is described below):

     2
    /\
  1----\
 /|    |\
/ |    | \
0 |    | 5
\ |    | /
 \|    |/
  \----4
    \/
    3

Same image rotated by 45° aka without the transformation / in the surface
coordinate system / what you actually draw.

0--1---2
|  /\  |
| /  \ |
|/    \|
|\    /|
| \  / |
|  \/  |
3--4---5

In this example, we first calculate the extents in the surface space (which is
the same as your earlier example does). These are the extents seen in the bottom
image.

>     Rect(-0.707031, -0.707031, 1.41406, 1.41406)

This rectangle describes the points 0, 2, 3, 5 in the above image.

These extents are then transformed to user space aka rotated by 45°. This is
equivalent to the extents of the rectangle in the first image. Notice that there
is some "free space" e.g. between the point 0 and where the rectangle actually
starts. This is why you get these larger numbers:

>     Rect(-0.999893, -0.999893, 1.99979, 1.99979)

The approach implemented by cairo is a lot faster as if it would try calculating
tight extents.

I hope this clears things up.

Cheers,
Uli
-- 
Bitte nicht mit dem verbleibenden Auge in den Laser gucken.
 - Vincent Ebert


More information about the cairo mailing list