[cairo] Transformations usage

Daniele Dario d.dario76 at gmail.com
Mon Dec 11 12:23:55 UTC 2017


Hi Bill,
thanks for the hints.

Spent some time to figure out how it works but finally I got something
working :-)

The first issue I had was that cairo_translate (cr, -X, -Y) seems
wrong: if I use X, Y I get it working properly.

Daniele.

On Wed, 2017-12-06 at 10:29 -0800, Bill Spitzak wrote:
> It is  probably easier to use a series of cairo transforms. But I
> think the main problem is that the y in the matrix needs to be
> height-offset.
> 
> If you have a point XY in your map that you want to be in the center
> of the window, I would do this:
> 
>  cairo_translate(cr, -X, -Y); // put center at 0,0
>  cairo_scale(cr, 1, -1); // flip from y-up to y-down
>  cairo_rotate(cr, r); // rotate ccw by r degrees
>  cairo_scale(cr, s, s); // scale where s is pixels/meter
>  cairo_translate(cr, w/2, h/2); // move center back to center of
> window of size w×h
> 
> 
> On Wed, Dec 6, 2017 at 2:46 AM, Daniele Dario <d.dario76 at gmail.com>
> wrote:
> > Hello everyone,
> > I'm trying to create my own widget on GTK+ to display a clip of a
> > 2D
> > map where I placed some polygons. The point of view can be moved
> > inside
> > the map and may rotate.
> > 
> > The main idea is that I draw the map on a cairo_surface_t once and
> > than
> > on expose event I use coordinates of POV to center the device
> > surface
> > to paint on the map, rotate the map, scale, clip and paint.
> > 
> > To start I tried to use a transformation matrix to be able to draw
> > using native coordinates on a surface but I'm getting confused on
> > how
> > transformation affects drawing.
> > 
> > At the end of the code below I expect to have a map painted on the
> > surface. In order to paint it on the widget I'd need another
> > transformation because:
> > - map size in the example is 165x165 and scale is 1 pixel = 1 [m]
> > - widget will have a different ratio
> > 
> > Can someone point me out on some examples or with some hint on how
> > to
> > achieve what I'm looking for?
> > 
> > Thanks in advance,
> > Daniele.
> > 
> > /*
> >  * Create a surface for the map:
> >  *  - 1 pixel = 1 [m]
> >  *  - assume map width >= height
> >  *  - coordinates of polygons are relative to an
> >  *    arbitrary origin placed at
> >  *    O = (x = height/2, y = height/2)
> >  */
> > gint site_width = 165;
> > gint site_height = 165;
> > cairo_surface_t *map = cairo_image_surface_create
> > (CAIRO_FORMAT_ARGB32,
> >         site_width, site_height);
> > 
> > /* Origin coordinates are relative */
> > gdouble offset = site_height / 2.;
> > 
> > /* Create a context to draw on the surface */
> > cr = cairo_create (map);
> > 
> > /*
> >  * FIXME: Need a transformation in order to use
> >  * coordinates relative to O:
> >  *  - x axis is correct just needs translation of offset
> >  *  - y axis is inverse and needs translation of offset
> >  */
> > cairo_matrix_t mat;
> > cairo_matrix_init (&mat, 1.0, 0.0, 0.0, -1.0, offset, offset);
> > cairo_transform (cr, &mat);
> > 
> > /* TODO: draw all objects on the map */
> > /* Array of (x,y) coordinates to represent a polygon */
> > GtkScuiPoint v1 [4] = {
> >         { -20., -40.},
> >         { -20.,   0.},
> >         { -50.,   0.},
> >         { -50., -40.}
> > };
> > 
> > //cairo_set_line_width (cr, 0.1);
> > 
> > cairo_set_source_rgba (cr, 1., 0., 0., .7);
> > 
> > /* Wrapper to draw and fill polygon  */
> > scui_cairo_draw_polygon (cr, TRUE, v1, 4);
> > 
> > GtkScuiPoint v2 [4] = {
> >         { 40.,  0.},
> >         { 40., 20.},
> >         { 20., 20.},
> >         { 20.,  0.}
> > };
> > 
> > cairo_set_source_rgba (cr, 0., 0., 1., .7);
> > 
> > /* Wrapper to draw an empty polygon  */
> > scui_cairo_draw_polygon (cr, FALSE, v2, 4);
> > 
> > /* TODO: Store surface to avoid re-painting it */
> > 
> > /* Destroy context */
> > cairo_destroy (cr);
> > 
> > 
> > --
> > cairo mailing list
> > cairo at cairographics.org
> > https://lists.cairographics.org/mailman/listinfo/cairo


More information about the cairo mailing list