Edenia
Edenia

Reputation: 2528

Scaling with cairo causes painted image to appear on a different position

I have a pretty simple setup: Everything happens within overridden "draw" method of a GtkDrawingArea placed inside a viewport in a scrolled window. The drawing area size is 1000000x1000000. It draws a pixbuf centered at the center of the drawing area with:

cairo_set_source_surface(cr, pixbufSurface, xPos, yPos); // middle center

cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);

cairo_paint_with_alpha(cr, transp);

The problem is that I have to use cairo_scale() to simply scale the drawn pixbuf, while still keeping it at the same position, but it moves it very far away instead. The scaling is by virtue of a scaleFactor variable. I suspect that I'll have to move the transformation matrix and I brute-forced some values:

  1. cairo_translate(cr, -500000, -500000); which works if scaleFactor is 2
  2. cairo_translate(cr, -1500000, -1500000); which works if scaleFactor is 4

but I have no idea how the numbers are correlated to each other.

Upvotes: 0

Views: 635

Answers (3)

Simon Christian
Simon Christian

Reputation: 1

N.B. If you are rendering several images in the same cairo context, some of which are scaled, remember to save and restore the cr before and after each scaled image or the scaling changes will hang around for the subsequent images drawn after the scaled image. Took me a while to work that one out...

        cairo_save (cr);
        
        ...

        cairo_restore (cr);

Upvotes: 0

Edenia
Edenia

Reputation: 2528

Basically what Gnoom said with a few additions:

  1. Perform cairo_scale(cr, z, z) before drawing pixbufs
  2. For every pixbuf being drawn, add cairo_translate(cr, (xpos*(1-z)/z), (ypos*(1-z)/z)); prior to rendering
  3. After rendering cairo_translate(cr, -(xpos*(1-z)/z), -(ypos*(1-z)/z));

Upvotes: 0

Gnoom
Gnoom

Reputation: 193

If you're at position (x,y) first, and scale with z, then afterwards you're at (zx, zy).

You're at the center, so at (500000, 500000), so if you scale with 2, you'll end up at (1000000, 1000000) and if you scale with 4, you'll end up at (2000000,2000000)

So you can transform back afterwards with ((1-z) * 500000, (1-z) * 500000)

cairo_scale(cr, scaleFactor, scaleFactor); 
cairo_translate(cr, 500000 * (1-scaleFactor), 500000 * (1-scaleFactor));

You can also transform first with (-500000, - 500000), then scale, and then transform back with (500000, 500000), but that only works in certain cases.

cairo_translate(cr, -500000, -500000);
cairo_scale(cr, scaleFactor, scaleFactor); 
cairo_translate(cr, 500000, 500000);

Just check if any of that works, or if you encounter other problems.

Upvotes: 1

Related Questions