[cairo] Getting pattern extents.

Donn donn.ingle at gmail.com
Tue Dec 16 04:51:46 PST 2014


Nicola,
  I have produced some code (in vala) using your suggestion. The attached
image shows what's happening.

The larger white rect with the red/green dot and black outline is the
first pattern drawn. At that point I have the data I need to draw the
bbox outline.

The smaller rect, rotated and down, is the second use of the pattern
(the 'stamp' I call it.)

The purple thing to the left it supposed to be the bbox outline around
the second stamp. I used the invert and multiply you spoke of.

If you have any spare time, please help me hack this into some
predictable shape. I want to have a general way to do this, no matter
how deeply nested matrices get.

I really need to get bounding boxes in device *and* user space without
all this pain! I need* them for clipping and for hit-testing.

[* Need is a strong word, this is just a hobby for me! I'm trying to
write a canvas vector drawing app of some kind.]

(If vala is a problem, I can convert it to c and try again.)

Thanks,
/d

I attach the image and here's the code:

-----------------

//HOWTO COMPILE:
// valac --pkg cairo xxx.vala -o test
using Cairo;

double cex1;double cey1;double cex2;double cey2; //clip extents

const double pi2 = 2 * Math.PI;

void scrot( Context cr, double sz, double degs, double x, double y ) {
   cr.scale( sz, sz );
   cr.rotate( (Math.PI/180.0) * degs );
   cr.translate( x, y );
}

void main(string[] args) {

   double w; double h;

   //Make a demo surface.
   Cairo.ImageSurface surface = new Cairo.ImageSurface
(Cairo.Format.ARGB32, 600,600);
   Cairo.Context cr = new Cairo.Context (surface);

   //Paint it
   cr.set_source_rgb(0.5,0.5,0.5);
   cr.paint();

   //center the axes - 0,0 in middle
   var matrix = Cairo.Matrix (1, 0, 0, 1, 300,300 );
   matrix.scale (1, 1);
   cr.transform(matrix); //<-Matrix zero.


   /* !!!!!!!!!!! MATRIX ONE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
   //SCROT1
   cr.save();
   scrot( cr, 1, 0, 0, 0 );
   Matrix otm = cr.get_matrix(); //Record the CTM (Will be the 'old' CTM
in next use.)

         //Make a pattern
         cr.save();
           //Draw it and clip it.
           cr.rectangle( -25,-25,50,50 ); //to get a path down.

           cr.clip_preserve(); //to start clip

           //Following uli_test.vala in extents under rot dir
           //Gonna save, set identity, and THEN get the extents...
           /*
           !
           ! This works! Amazd. I get an axis-aligned device space rect.
           !
           */
           cr.save();
             cr.identity_matrix();
             cr.clip_extents (out cex1, out cey1, out cex2, out cey2);
             //these vars are now in ... i think ... device space.
             //BECAUSE of the identity call before the extents call.
             stdout.printf("clip axis-aligned ds extents:
%G,%G,%G,%G\n",cex1,cey1,cex2,cey2);
           cr.restore();

           //Draw again but to a 'group'
           cr.push_group();
             cr.set_source_rgb(1,1,1);
             cr.fill();
           Pattern pat = cr.pop_group(); //grab a cache of that drawing.

         cr.restore(); //ends that clip. Also end identity voodoo.

         //Draw it. Should I clip?
         cr.set_source( pat );
         cr.paint();

         //okay - let's try to visualize those numbers:
         cr.save();

           w = cex2 - cex1; h = cey2 - cey1;

           cr.identity_matrix(); //Goes into device space.
           //i.e. My USER SPACE COORDS are now the same
           //as DEVICE SPACE. Go figure.
           //ALSO the rotation is gone - the rect is axis aligned.

           //Some dots to mark the two points
           cr.set_source_rgb(1,0,0);
           cr.arc(cex1,cey1,4,0,pi2);
           cr.fill();

           cr.set_source_rgb(0,1,0);
           cr.arc(cex2,cey2,4,0,pi2);
           cr.fill();

           //The actual bbox rectangle.
           cr.rectangle( cex1, cey1, w, h );
           cr.set_source_rgb(0,0,0);
           cr.stroke();

         cr.restore();

         /* !!!!!!!!!!! MATRIX TWO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

         //Now ... Move the CTM and draw again.
         //Can we locate a bbox over this new pattern stamp?

         //SCROT2
         cr.save();
         scrot( cr, 0.5, 67, 100, -50 );
         Matrix ctm = cr.get_matrix(); //This matrix

           //Draw it again - stamp it.
           cr.set_source( pat );
           cr.paint();

           //Nicola's idea: Pure black magic this... :O
           otm.invert();
           ctm.multiply(ctm,otm); //ctm is now changed. ctm = ctm * otm

           ctm.transform_point( ref cex1, ref cey1 );
           ctm.transform_point( ref cex2, ref cey2 );

           //The numbers look like they're in USER SPACE.
           stdout.printf("After transforming the point:
%G,%G,%G,%G\n",cex1,cey1,cex2,cey2);

           //Try drawing something with these numbers:
             cr.set_source_rgb(1,0,1);
             cr.rectangle( cex1, cey1, cex2-cex1, cey2-cey1);
             cr.stroke();

             //dots for the two points.
             cr.set_source_rgb(1,0,0);
             cr.arc(cex1,cey1,4,0,pi2);
             cr.arc(cex2,cey2,4,0,pi2);
             cr.fill();


         //END SCROT2
         cr.restore();

   //END SCROT1
   cr.restore();

   surface.write_to_png ("img.png");
}

------------------
/d
-------------- next part --------------
A non-text attachment was scrubbed...
Name: img.png
Type: image/png
Size: 3984 bytes
Desc: not available
URL: <http://lists.cairographics.org/archives/cairo/attachments/20141216/5677203d/attachment.png>


More information about the cairo mailing list