Cairo: usar un SVG como figura ("Cairo Groups")

gtkPythonArco

En esta receta, crearemos una figura, o un Surface usando la nomenclatura de Cairo, a partir de una imagen en formato SVG.

Ingredientes

  • python
  • python-cairo

Son paquetes muy comunes, así que es muy posible que ya los tengas instalados.

Lo primero de todo: El esqueleto GTK

Este código es muy simple. Si no has trabajado nunca con GTK, por favor, echa un vistazo a alguno de los manuales que hay por Internet…

El objetivo es tener un “Context” de Cairo, el objeto principal para dibujar cosas en Cairo. Es fácil, tenemos un método muy útil en gtk.gdk.window que hace el trabajo por nosotros: cairo_create(). La ventana que vamos a usar está dentro de un DrawingArea, así que:

#!/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… Sticking out tongue 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. Smiling And that’s all, folks!
Thanks for reading.

Código fuente

Referencias

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de oscarah

What is this?

What is this?

"aviso: la dereferencia de punteros de tipo castigado romperá las reglas de alias estricto" --GCC 4.3.1

Imagen de admin

La "traducción" de tu

La "traducción" de tu receta

Imagen de oscarah

¿Pero porque veo los dos

¿Pero porque veo los dos posts? Se supone que solo debería verse en el idioma seleccionado, ¿no?

"aviso: la dereferencia de punteros de tipo castigado romperá las reglas de alias estricto" --GCC 4.3.1

Imagen de admin

Demasiado alcohol, supongo

Demasiado alcohol, supongo Smiling

It's an administrative decision. Because very few people will do bilingual versions of their recipes or posts, es mejor que todo el mundo vea todo, de otro modo se perderían parte del contenido. Tu post ha sido un experimento, I'm sorry.