Search code examples
x11cairo

cairo graphics library: how can I transfer data between two xlib surfaces?


I want to use the Cairo graphics library to copy the content of one X11 window to another X11 window. I create two surfaces using cairo_xlib_surface_create(). Now I want to copy a region from the source surface (position xs, ys, size ws, hs) to a given position on the destination surface (position xd, yd), where it should also become visible.

How would I accomplish this? Would I go through a Cairo image surface as in this example: https://stackoverflow.com/a/18290221/3852630? This goes from source X11 surface to image surface; how can I copy back from the image surface to the destination X11 surface? And how do I consider the regions above?

Or is the way to go through cairo_surface_map_to_image() where I would map the X11 surfaces to images surfaces? But how to proceed from there, how to I transfer data between the image surfaces?

Or am I abusing Cairo and should better do it directly via X11, like this one: https://stackoverflow.com/a/4965236/3852630?

Thanks a lot for your help!


Solution

  • Cairo does not care what kind of surfaces you have. The following function should copy a rectangular area between two cairo_surface_ts. Variable names should be just as in your question.

    // Untested, treat this as pseudo-code
    void copy_some_area(cairo_surface_t* source, int xs, int ys, int ws, int hs,
                        cairo_surface_t* target, int xd, int yd) {
        cairo_t *cr = cairo_create (target);
        cairo_set_source_surface (cr, source, xd - xs, yd - ys);
        cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
        cairo_rectangle (cr, xd, yd, ws, hs);
        cairo_fill (cr);
        cairo_destroy (cr);
    }
    

    This function:

    • creates a cairo context
    • uses the source surface as the source for the context so that the offset between the two surfaces is as wanted (cairo_set_source_surface gets the coordinates where the top left corner of the surface should appear).
    • tells cairo to "just copy" without any alpha blending or stuff
    • informs cairo about the rectangle that should be filled
    • fills the rectangle
    • cleans up by destroying the context again

    where it should also become visible.

    Uhm, perhaps you also want a call to cairo_surface_flush(target); to make really, really, really sure that cairo actually did the drawing and did not just remember it for later.