# [cairo] Transformations usage

Daniele Dario d.dario76 at gmail.com
Wed Dec 6 10:46:26 UTC 2017

```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?

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);

```