[cairo] Extents under rotation

Chris Wilson chris at chris-wilson.co.uk
Sun Dec 1 05:09:03 PST 2013


On Sun, Dec 01, 2013 at 02:59:26PM +0200, Donn wrote:
> Hi,
> I have found some email talk about this online, but no solution.
> When you rotate a matrix, draw something and then use path_extents
> to measure it, you get a result that's bigger than it should be.
> 
> Here's a demo in Vala:
> 
> ---
> 
> // valac --pkg cairo badextents.vala -o test
> // View the img.png file after running "test"
> 
> using Cairo;
> void main(string[] args) {
> 
>   double x1;
>   double x2;
>   double y1;
>   double y2;
> 
>   Cairo.ImageSurface surface = new Cairo.ImageSurface
> 	(Cairo.Format.ARGB32, 500, 500);
>   Cairo.Context cr = new Cairo.Context (surface);
> 
>   //centre the axes - 0,0 in middle
>   var matrix = Cairo.Matrix (1, 0, 0, 1, 250,250 );
>   matrix.scale (1, 1);
>   cr.transform(matrix);
> 
>     cr.arc (0.0, 0.0, 30.0, 0, 2*Math.PI);
>     cr.set_source_rgb(1,0,0);
>     cr.fill_preserve();
> 
>     cr.path_extents (out x1, out y1, out x2, out y2);
>     stdout.printf("Extents: %G|%G|%G|%G\n", x1,y1,x2,y2);
>     //Draw the bbox as calculated by extents
>     cr.rectangle(x1,y1,(x2-x1),(y2-y1));
>     cr.set_source_rgb(0,0,0);
>     cr.stroke();
> 
>     //Now, rotate that circle 45 degrees (and move it over a bit)
>     cr.translate(90,0);
>     cr.rotate((Math.PI/180.0)*45); //45 degree rot
> 
>       cr.arc (0.0, 0.0, 30.0, 0, 2*Math.PI);
>       cr.set_source_rgb(1,0,0);
>       cr.fill_preserve();
> 
>       cr.path_extents (out x1, out y1, out x2, out y2);
>       stdout.printf("Extents: %G|%G|%G|%G\n", x1,y1,x2,y2);
>       //Draw the bbox as calculated by extents -- this is wrong.
>       //Why is the rect so much bigger?
>       //Is there any way to get the proper user-space coords?
>       cr.rectangle(x1,y1,(x2-x1),(y2-y1));
>       cr.set_source_rgb(0,0,0);
>       cr.stroke();
> 
>   surface.write_to_png ("img.png");
> }
> ---
> 
> Is there a way to get the user-space extents of that second circle
> such that the rect fits properly?
> 
> In my other code, I am doing an identity_matrix() and then extents.
> This gives me a rect in device space, which is fine. However, I also
> need that rect in user space.

The extents is in userspace. The bounds are found in device space and
then rotated back to userspace. This introduces the enlargement you see
above.

One solution would be to rotate the path back into userspace before
determining the bounds such that they are tight.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the cairo mailing list