Re: Getting pattern extents.

Donn <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
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

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
img.png (image/png, 3.9 KB) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.