[cairo] create an image from window for printing

Fabian Förg fabian.foerg at gmx.de
Sat Jan 20 08:25:29 PST 2007

Kalle Vahlman wrote:
> 2007/1/19, Fabian Förg <fabian.foerg at gmx.de>:
>> Hello,
>> is it possible to capture a gtk-window, save it as an image file and use
>> that file for printing with cairo?
>> At first, I tried this:
>> pixmap = gdk_pixmap_new(window->window, window->allocation.width,
>> window->allocation.height, -1);
>> This should save the window as a pixmap.
> Actually it doesn't. It just creates a pixmap that has the same depth
> that the gdkwindow does. The content of that pixmap is undefined at
> that point, if I'm not mistaken.
Thank you for the hint.
>> In order to print it, I tried gdk_cairo_set_source_pixbuf, but the
>> function requires a pixbuf as an argument.
>> How can I convert the pixmap to a pixbuf and is my approach alright?
> First, you can get a pixbuf directly from the window with the function
>  gdk_pixbuf_get_from_drawable()
> Secondly, I haven't tried the printing code of Gtk+ yet myself
> (assuming that is what you are using), but I gather from these
> questions and the API docs that it offers you a cairo context to which
> you draw your stuff for printing.
Yes, I use the Gtk+ printing API, and it offers me a GtkPrintContext.
> So rather than converting the window to a pixbuf in between, you are
> probably better off geting a cairo surface for the window and simply
> painting that to the context you get from the printing system. The Gdk
> Cairo helpers don't offer it directly, but you can get it by aquiring
> the context and asking the target surface from it:
>  cairo_context = gdk_cairo_create(window->window);
>  surface = cairo_get_target(cairo_context);
> and then you can set the surface as the source for the printing context:
>  cairo_set_source_surface (printing_context, surface);
> and do whatever transforms and tricks you want to with it (fitting it
> to the page size or such) before painting it to the surface.
> Cheers,
Thanks for your suggestions. I tried the following:
("appl_t" is a private struct which contains "cairo_t *cairo_context;").

void output(appl_t * appl)
    GtkWidget *window;

    /* ... */
    /* this function creates the window which should be printed 
afterwards */

    /* create a cairo_context of the screen */
    appl->cairo_context = gdk_cairo_create(window->window);

static void draw_page(GtkPrintOperation * operation, GtkPrintContext * 
              int page_nr, appl_t * appl)
    cairo_t *cr;
    cairo_surface_t *surface;
    gdouble print_width, print_height, scale_x, scale_y;
    gint surface_width, surface_height;

    /* transform the print_context into a cairo_context */
    cr = gtk_print_context_get_cairo_context(print_context);

    /* create a surface from cairo_context (the captured window) */
    surface = cairo_get_target(appl->cairo_context);

    /* prevent surface from being destroyed */

    /* get width and heigth of print_context */
    print_width = gtk_print_context_get_width(print_context);
    print_height = gtk_print_context_get_height(print_context);

    /* get width and height of surface */
    surface_width = cairo_image_surface_get_width(surface);
    surface_height = cairo_image_surface_get_height(surface);
    g_print("\nsurface_width: %i\n", surface_width);

    /* calculate the scale factors */
    scale_x = (gdouble) print_width / surface_width;
    scale_y = (gdouble) print_height / surface_height;
    g_print("scale_x: %g\n", scale_x);

    /* scale surface, so it fits the complete print_context */

    /* set surface as source for cr */
    cairo_set_source_surface(cr, surface, 0., 0.);

    /* the cairo surface can be destroyed now */

    /* paint cr */

g_print shows that surface_width is 0. Why?
Moreover, I have these questions:
- How can I scale the surface, so that it fits the complete selected paper?
- How can I change the background color of the captured window, i. e. 
change the theme/style of the window?


More information about the cairo mailing list