In this recipe, we will create a shape, or a Surface using Cairo verbs, from an image in SVG format.
This packages are very common, so you may probably have them installed.
This code is very simple. If you aren’t used to working with Gtk, please, see one of the manuals on the Internet…
The target is to have a Cairo Context, the main object to draw things on Cairo. This is easy, as we have an useful method on gtk.gdk.window that does the work for us: cairo_create(). The window we are going to use is inside a DrawingArea, so:
#!/usr/bin/env python # -*- mode: python; coding: utf-8 -*- import gtk import cairo class Test: def __init__(self): mw = gtk.Window(gtk.WINDOW_TOPLEVEL) mw.connect("delete-event", gtk.main_quit) mw.set_size_request(400, 400) da = gtk.DrawingArea() da.connect("expose_event", self.on_expose) mw.add(da) # Source image, loaded as a pixbuf self._img = gtk.gdk.pixbuf_new_from_file("photos.svg") mw.show_all() if __name__ == "__main__": t = Test() try: gtk.main() except KeyboardInterrupt: gtk.main_quit()
Ok. Nothing new until here. I’ve loaded the SVG using a gtk.gdk.pixbuf because Cairo can use this as a source, so drawing it is simple. Moreover, I’ve connected the expose_event of the drawing area to a method of Test.
Take a look into the method on_expose():
def on_expose(self, widget, event): cr = widget.window.cairo_create() # Normal image cr.set_source_pixbuf(self._img, 175, 50) cr.paint() # Black shape of same image cr.push_group() cr.set_source_pixbuf(self._img, 175, 150) cr.paint() src = cr.pop_group() cr.set_source_rgb(0, 0, 0) cr.mask(src) # Blue shape of same image, with alpha cr.set_source_pixbuf(self._img, 175, 250) cr.paint() cr.push_group() cr.set_source_pixbuf(self._img, 175, 250) cr.paint() src = cr.pop_group() cr.set_source_rgba(.5, .5, 1, .4) cr.mask(src)
As you can see, there are three drawn things. The first one is the SVG as is, using a plain paint() method. Easy. The result may be:
Of course, without the border and the shadows… The second item we see is more interesting. I’m going to use the alpha channel in the original SVG as a mask: where the image is transparent, nothing is drawn, so only the opaque pixels are used to paint. To achieve this, I’m using a feature of Cairo called groups. A group is like a layer where you can draw things. The difference is that this ‘layer’ can be used later as a pattern or as a surface.
This time, I’ll only paint in black, which gives this:
¡Voilá! As you can imagine, if you use other color, blue for example, and paint with alpha enabled, you could get something like a shinning effect, like this:
which is the third item in our example. And that’s all, folks!
Thanks for reading.
PD: This is my first post in English, please, don’t take this into account…