In this recipe, we will create a shape, or a Surface using Cairo verbs, from an image in SVG format.

Ingredients

You’ll need:

  • python
  • python-cairo

This packages are very common, so you may probably have them installed.

First of all: the Gtk skeleton

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.

Now, drawing time

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… :p 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…

Sources

References



blog comments powered by Disqus