Voy a compartir algunos básicos en este post, y luego algunas cosas que hemos aprendido con respecto a la pérformance, que no son del todo obvias o no son muy sencillas de encontrar.
En primer lugar un ejemplo bien sencillo de la mínima aplicacion para mostrar algo usando cairo en gtk2 y gtk3:
#!/usr/bin/python
import gtk
class MinimalCairoTest(gtk.Window):
def __init__(self):
super(MinimalCairoTest, self).__init__()
self.set_size_request(400, 400)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.__expose_cb)
self.add(darea)
self.show_all()
def __expose_cb(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_rgb(1.0, 0.0, 0.0)
cr.rectangle(20, 20, 120, 80)
cr.fill()
MinimalCairoTest()
gtk.main()
El mismo código usando Gtk3:
#!/usr/bin/python
from gi.repository import Gtk
class MinimalCairoTest(Gtk.Window):
def __init__(self):
super(MinimalCairoTest, self).__init__()
self.set_size_request(400, 400)
self.connect("destroy", Gtk.main_quit)
darea = Gtk.DrawingArea()
darea.connect("draw", self.__draw_cb)
self.add(darea)
self.show_all()
def __draw_cb(self, widget, cr):
cr.set_source_rgb(1.0, 0.0, 0.0)
cr.rectangle(20, 20, 120, 80)
cr.fill()
MinimalCairoTest()
Gtk.main()
Como podemos ver, el cambio más importante es que el "expose-event" es reemplazado por un evento "draw" que ya nos provee un contexto de cairo, en este caso, es el parámetro cr.
Lo que veremos en pantalla es simplemente:
No muy interesante, pero nos sirve de base para seguir avanzando.
Si queremos mostrar una imagen centrada en la pantalla podemos hacer:
#!/usr/bin/python
from gi.repository import Gtk
import cairo
png_test_file = '/usr/share/icons/gnome/256x256/emotes/face-cool.png'
class MinimalCairoTest(Gtk.Window):
def __init__(self):
super(MinimalCairoTest, self).__init__()
self.set_size_request(400, 400)
self.connect("destroy", Gtk.main_quit)
# read the png file and create a surface
self._im_surface = cairo.ImageSurface.create_from_png(png_test_file)
darea = Gtk.DrawingArea()
darea.connect("draw", self.__draw_cb)
self.add(darea)
self.show_all()
def __draw_cb(self, widget, cr):
# get window width & heigth
win_width = self.get_allocation().width
win_height = self.get_allocation().height
# show the image centered
cr.translate((win_width - self._im_surface.get_width()) / 2,
(win_height - self._im_surface.get_height()) / 2)
cr.set_source_surface(self._im_surface)
cr.paint()
MinimalCairoTest()
Gtk.main()
Y veremos:
Lo primero a tener en cuenta, es que aun usando los bindings dinámicos para Gtk3, los bindings dinámicos para Cairo no estan listos por eso hacemos "import cairo" y no "from gi.repository import Cairo"
En el último ejemplo de este post, vamos a aplicar una transformación simple, para mostrar la imagen a la mitad de su tamaño (copio solo el metodo __draw_cb, ya que el resto es igual)
def __draw_cb(self, widget, cr):
# get window width & heigth win_width = self.get_allocation().width win_height = self.get_allocation().height # show the image centered scale = 0.5 image_width = self._im_surface.get_width() * scale image_height = self._im_surface.get_height() * scale cr.translate((win_width - image_width) / 2, (win_height - image_height) / 2) cr.scale(scale, scale) cr.set_source_surface(self._im_surface) cr.paint()
En este caso veremos:
Lo interesante es ver que pasa si cambiamos el orden en las operaciones de cairo efectuadas (translate, scale, set_surface, paint).
Si hacemos el scale despues del set_surface:
cr.translate((win_width - image_width) / 2,
(win_height - image_height) / 2)
cr.set_source_surface(self._im_surface)
cr.scale(scale, scale)
cr.paint()
La imagen es transladada correctamente, pero no se escala:
Y si hacemos el scale antes del translate:
cr.scale(scale, scale)
cr.translate((win_width - image_width) / 2,
(win_height - image_height) / 2)
cr.set_source_surface(self._im_surface)
cr.paint()
La escala afecta al translate, por lo que se translada menos de lo que debería:
Este caso es sencillo, porque hay una sola transformación efectuada, pero por ejemplo cuando hay escalados y rotaciones, se complica un poco más, y hay que tener bien en cuenta el orden en el que se aplican las transformaciones.
En un próximo post voy a escribir acerca de algunos puntos para lograr buena performance usando Cairo.
No hay comentarios.:
Publicar un comentario