[cairo] How can I scale a calro surface

Owen Taylor otaylor at redhat.com
Tue Jan 24 09:28:08 PST 2006

On Tue, 2006-01-24 at 10:46 -0600, Meryl Silverburgh wrote:
> How can I scale a calro surface?
> I have the following code, but it does not work (does not scale):
>  cairo_t* cr = cairo_create(tmpSurf);
>     double scale = 0.5;
>     cairo_scale (cr, scale, scale);
>     cairo_surface_write_to_png(tmpSurf, "tmpSurf.png");
> Can you please tell me why it does not work?

Jonathan's answer tells you why the above doesn't work, but it is
actually a fairly subtle how to do it correctly. (I think 
explaining the following would make a good section for the docs.)

 cairo_surface_t *
 scale_surface (cairo_surface_t *old_surface, 
                int old_width, int old_height,
                int new_width, int_new_height
    cairo_surface_t *new _surface = cairo_surface_create_similar(old_surface, new_width, new_height);
    cairo_t *cr = cairo_create (new_surface);

    /* Scale *before* setting the source surface (1) */
    cairo_scale (cr, (double)new_width / old_width, (double)new_height / old_height);
    cairo_set_source_surface (cr, old_surface, 0, 0);

    /* To avoid getting the edge pixels blended with 0 alpha, which would 
     * occur with the default EXTEND_NONE. Use EXTEND_PAD for 1.2 or newer (2)
    cairo_pattern_set_extend (cairo_get_source(cr), CAIRO_EXTEND_REFLECT); 

     /* Replace the destination with the source instead of overlaying */
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);

    /* Do the actual drawing */
    cairo_paint (cr);
    cairo_destroy (cr);

    return new_surface;

[Untested code warning].


(1) I'm pretty sure we implemented locking for the pattern transform
    like this but I may be misremembering.

(2) Calling get_source() and modifying the implicit source create by
    set_source_surface() is a little hacky, but I think we consider
    it legitimate, and it saves a bunch of typing.

More information about the cairo mailing list