[cairo] context.save and in_fill - still lost in the woods

Carl Worth cworth at cworth.org
Mon Nov 26 16:04:00 PST 2007

On Mon, 26 Nov 2007 11:45:18 +0200, Donn wrote:
> > The trick is to create a path and then reset the transformation matrix to
> > the identity transform before calling in_fill, like this:
> Thanks for the help. Seeing it in-place in the code helps me more than theory.

I'm glad the code snippets help. But do you have the theory straight
yet? If not, then you'll just keep running into problems. So please
continue to ask questions if any concepts are unclear and we'll do our
best to help you out. And that process will also hopefully help us to
improve the cairo documentation.

A comment like this one is pretty scary for example:

	self.cr.identity_matrix  ( ) # VITAL LINE :: I don't know why.

Here's one attempt at the basics.

There are two coordinate systems in cairo that are essential to
understand. "User space" and "device space". Device space is always
aligned with the target device, (like the pixel grid of your
display). User space is the coordinate space for positions that you
pass back and forth across the cairo API.

There's a transformation that maps user space coordinates to
device-space coordinates. Initially, this transformation is an
identity matrix so that user space and device space are
equivalent. But as you call things like cairo_scale, cairo_rotate, and
cairo_scale you're effectively transforming the user-space axes.

You can limit the scope of these transformations by doing them inside
a cairo_save/restore pair. If your line above is so mysteriously vital
it's probably because you have a transformation happening somewhere
without a cairo_save/restore pair so the transformation is making it
from one loop iteration to the next, and thereby getting applied
multiple times, (bad news).

As for the hit testing of cairo_in_fill. This is one case where your
program likely receives a device-space coordinate, (from the window
system tracking the pointer). Since the cairo API deals with
user-space coordinates, but you've got a device-space coordinate for
the mouse, what you have to do before calling cairo_in_fill is to make
user-space the same as device-space. That's why the helpful code you
received is:

	cairo_save (cr);
	cairo_set_identity_matrix (cr);
	hit = cairo_in_fill (cr, x, y);
	cairo_restore (cr);

That performs a temporary modification of the transformation so that
user space matches device space, checks if the desired point is inside
the current path, and then restores the original transformation.

I hope that's all quite clear.

> I have found that, in my actual app, I have had to do another SetToCenter()
> transform just after the identity_matrix() call for my mouse x,y to mesh with
> where stuff is being drawn. But, it's back to working again. (For how long?
> He groans... :) )

That seems odd. Where is the mouse x,y coordinate coming from? Is it
somehow relative to a coordinate system with 0,0 in the center of the
page instead of relative to the upper-left of the target device? If
so, that would explain it, (but it would still be an odd setup). The
principle here is that whatever coordinate system your mouse (x,y) is,
that's the same coordinate system you need to setup for user space
before calling cairo_in_fill.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20071126/38979d3e/attachment.pgp 

More information about the cairo mailing list