2
votes

I want to draw a triangle and text using C++ and Cairo like this:

|\
| \
|PP\
|___\

If I add the triangle and the text using Cairo I get:

 ___
|   /
|PP/
| /
|/

So the y-axis is from top to bottom, but I want it from bottom to top. So I tried to changed the viewpoint matrix (cairo_transform(p, &mat);) or scale the data (cairo_scale(p, 1.0, -1.0);). I get:

|\
| \
|bb\
|___\

Now the triangle is the way I want it BUT the TEXT is MIRRORED, which I do not want to be mirrored.

Any idea how to handle this problem?

3
Why don't you create the correct triangle right from the start, keeping in mind that Cairo uses another axis orientation as we do with pen and paper? To me, the transform seems not like the preferred way to go.lupz
Thank you for your answer. Anyhow I can't do it that way, because it is not only one triangle but a complex drawing which is created by a hard to understand algorithm. This algorithm already exists and it can't be changed. Of course I could write another algorithm that flips the y-coordinate of every drawing element but moves text. Well it is just that I hoped there is a way to draw with Cairo the usual way, but probably there is not.user3144699
Well... Flipping the y-coordinate of the algorithm's output would be the way to go. Text may be more complicated. When adding the text to the algorithm's result -> ok. When it is a part of the result it might be flipped too. You would have to distinguish between drawing and text. But you might have to recalculate the texts position. It may be possible to feed the algorithm itselft with flipped coordinates to get the desired output.lupz
"You would have to distinguish between drawing and text." Yes. "But you might have to recalculate the texts position." Yes. Yes, this is of course an option. I am just wondering that I am the only person who is not satisfied with the standard Cairo coordinate system. And that one may not change it to a standard math coordinate system.user3144699

3 Answers

7
votes

I was in a similar situation as the OP that required me to change a variety of coordinates in the cartesian coordinate system with the origin at the bottom left. (I had to port an old video game that was developed with a coordinate system different from Cairo's, and because of time constraints/possible calculation mistakes/port precision I decided it was better to not rewrite the whole bunch) Luckily, I found an okay approach to change Cairo's coordinate system. The approach is based around Cairo's internal transformation matrix, that transforms Cairo's input to the user device. The solution was to change this matrix to a reflection matrix, a matrix that mirrors it's input through the x-axis, like so:

cairo_t *cr;
cairo_matrix_t x_reflection_matrix; 
cairo_matrix_init_identity(&x_reflection_matrix); // could not find a oneliner
/* reflection through the x axis equals the identity matrix with the bottom 
left value negated  */
x_reflection_matrix.yy = -1.0;
cairo_set_matrix(cr, &x_reflection_matrix);
// This would result in your drawing being done on top of the destination 
// surface, so we translate the surface down the full height
cairo_translate(cr, 0, SURFACE_HEIGHT); // replace SURFACE_HEIGHT
// ... do your drawing

There is one catch however: text will also get mirrored. To solve this, one could alter the font transformation matrix. The required code for this would be:

cairo_matrix_t font_reflection_matrix;
// We first set the size, and then change it to a reflection matrix
cairo_set_font_size(cr, YOUR_SIZE);
cairo_get_font_matrix(cr, &font_reflection_matrix);
// reverse mirror the font drawing matrix
font_reflection_matrix.yy = font_reflection_matrix.yy * -1;
cairo_set_font_matrix(cr, &font_reflection_matrix);
1
votes

Answer:

Rethink your coordinates and pass them correctly to cairo. If your coordinates source has an inverted axis, preprocess them to flip the geometry. That would be called glue code, and it is ofter neccessary.

Stuff:

It is a very common thing with 2D computer graphics to have the origin (0,0) in the top left corner and the y-axis heading downwards (see gimp/photoshop, positioning in html, webgl canvas). As allways there are other examples too (PDFs). I'm not sure what the reason is, but I would assume the reading direction on paper (from top to bottom) and/or the process of rendering/drawing an image on a screen. To me, it seems to be the easiest way to procedurally draw an image at some position from the first to the last pixel (you don't need to precalculate it's size).

I don't think that you are alone with your oppinion. But I don't think that there is a standard math coordinate system. Even the very common carthesian coordinate system is incomplete when the arrows that indicate axis direction are missing.

1
votes

Summary: From the discussion I assume that there is only one coordinate system used by Cairo: x-axis to the right, y-axis down. If one needs a standard math coordinate system (x-axis to the right, y-axis up) one has to preprocess the data.