[cairo] Extents under rotation

Uli Schlachter psychon at znc.in
Sat Dec 7 10:22:18 PST 2013


On 07.12.2013 08:31, Donn wrote:
> On 06/12/2013 17:13, Bill Spitzak wrote:
>> The matrices are multiplied before this is done, so this error does not 
>> accumulate. For instance if you rotate by 45 degrees and then back by 45 
>> degrees, it will act like a rotation of 0 and produce your expected 
>> bounding box, rather than enlarging the bounding box twice.
> I'm sure I will face these things soon when I institute picking beyond a 
> basic bbox hit approach.

That sounds like it could be a job for cairo_in_fill/stroke/clip(), but that
does not tell you which part of the path/clip was hit.

> Bill, Do you have a way to draw a tight bbox in user-space around a path?
> I have tried various things like getting the extents in device space (by 
> doing a identity_matrix call before extents) and then using device_to_user
> on each returned x,y coordinate -- in order to try get those corners *in
> user space* and I just can't get it right.

Doesn't this result in a non-axis-aligned rectangle? Anyway, if I had to do
this, I would try something like this:

/* Helper function to save some variable assignments */
void device_to_user_line(cairo_t *cr, double x, double y)
  cairo_device_to_user (cr, &x, &y);
  cairo_line_to (cr, x, y);

  double x1, y1, x2, y2;
  double x, y;

  cairo_save (cr);
  cairo_identity_matrix (cr);
  cairo_path_extents (cr, &x1, &y1, &x2, &y2);
  cairo_restore (cr);

  /* Make sure there is no current path and the next line_to becomes a move */
  cairo_new_path (cr);
  /* Top left corner */
  device_to_user_line (cr, x1, y1);
  /* Top right corner */
  device_to_user_line (cr, x2, y1);
  /* Bottom right corner */
  device_to_user_line (cr, x2, y2);
  /* Bottom left corner */
  device_to_user_line (cr, x1, y2);
  cairo_close_path (cr);

  cairo_stroke (cr);

(Disclaimer: completely untested)

> I'd like to draw an X shape over my original path: At first I have a 
> complex shape - so I want to measure extents and thereafter substitute a 
> simple X shape [*] that can be drawn quickly(into user/local space) and 
> re-measured by extents in the future.
> [*] X from top-left to bottom-right and reverse. Or just a rect, or just 
> four dots in the bbox corners.

Uhm. So the above code should do just this, right?

"For saving the Earth.. and eating cheesecake!"

More information about the cairo mailing list