[Cairo] mouse pointer and cairo

Bill Spitzak spitzak at d2.com
Sun Oct 12 18:47:07 PDT 2003

On Saturday 11 October 2003 11:31 am, Carl Worth wrote:

> We'll have to decide our own semantics for these operations.
> PostScript returns true if the pixel containing the given point would
> be painted by stroke or fill. But that may or may not be the
> definition we want when doing anti-aliased graphics. The other obvious
> choice would be to compute geometrically correct containment without
> reference to the device pixel grid.

> I'd be glad for some guidance from those with relevant user-interface
> design experience.

=== Hit area device ===

OpenGL does hit detection by a different mechanism. In Cairo terms it would 
be a special drawing surface, which is a 1x1 pixel that stores a number. The 
program selects this special drawing surface, and then scales and transforms 
so the "hit area" (a small square around the mouse cursor) is projected to 
fill this 1x1 area. There is also a call that is pretty much "set the number 
to put in there", this number acts a lot like the current color. When you 
draw anything to this surface it does normal drawing, but if the pixel would 
change, it instead records the current number in a list. You can get all the 
numbers back with another call. You can make the detection area a shape other 
than a rectangle by setting a clipping path to that shape before drawing.

The main advantage of this is that you get hit detection with little or no 
extra work once you have code that can draw objects.

The big disadvantage of this is that it does not detect which object was 
closest to the mouse. For opaque objects that are thicker than 1 pixel it 
works great. For points and lines my program has to iterate through all the 
objects and do it's own calculation to figure out which one is closest to the 

Perhaps though this can be used in Cairo, with these extra changes:

1. Make the "number" reliably hold a void* pointer, not just an integer.

2. Return how opaque the object is. Programs can use this to decide if the 
user was clicking through an almost-transparent window on the foreground 
object. More importantly, transparent areas of images and letters can return 
but the program can skip them if it wants.

3. Somehow return a distance value. This should be the distance between the 
center of the pixel from the nearest line or vertex (squared to avoid the 
need for sqrt). Make it negative if the pixel is inside the a filled shape. 

=== the "in_fill" call ===

If you do this, I would definately use the geometrically correct solution 
where it returns whether an inifintely small point at x,y is in the region. 
Actually I would return a distance value, like above. This is the distance 
squared to the nearest line or point, negated if the point is inside the 
shape. It is ok if curves are decomposed into straight lines before the 
calculation is done.

Is x and y transformed by the current transformation? Probably it should be, 
but then we must be able to push the transform, draw a path, pop the 
transform back, and then do the test. Alternatively there could be a call 
that is "remember the x,y now", this may be good for testing against many 
objects, and starts to look like the hit area desgn.

Does this return false if x and y are inside the path but outside the clip 
region? I'm not sure.

> The PostScript versions of these operators also allow the user to test
> for intersection with an arbitrary region instead of a point, (the
> region is specified as a userpath). This might be another reason to
> expose a cairo_path_t object.

This could be done by clipping to one path, then building another, and then 
having a call that returns true if the resulting path is non-empty.

                   ,~,~,~,~ ~ ~ ~ ~
     /\_       _|_========___         Bill Spitzak
 ~~~/\/\\~~~~~~\____________/~~~~~~~~ spitzak at d2.com

More information about the cairo mailing list