sábado, mayo 25, 2013

Nice cairo trick to draw transparent shapes with borders

I have learned a new cairo trick, and how I didn't find this explained in any place will share it here.

Imagine you want draw two figures with a border, is really easy:


The code is:


#!/usr/bin/python

from gi.repository import Gtk


class MinimalCairoTest(Gtk.Window):

    def __init__(self):
        super(MinimalCairoTest, self).__init__()
        self.set_size_request(300, 300)
        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_line_width(10)

        cr.set_source_rgb(1.0, 0.0, 0.0)
        cr.rectangle(140, 20, 120, 120)
        cr.fill_preserve()

        cr.set_source_rgb(0.0, 0.0, 1.0)
        cr.stroke()

        cr.set_source_rgb(1.0, 1.0, 0.0)
        cr.arc(150, 150, 70, 0, 2 * 3.14)
        cr.fill_preserve()
        cr.set_source_rgb(0.0, 1.0, 1.0)
        cr.set_line_width(10)
        cr.stroke()


MinimalCairoTest()
Gtk.main()

If we want draw the same figures using alpha, we can do:




#!/usr/bin/python

from gi.repository import Gtk


class MinimalCairoTest(Gtk.Window):

    def __init__(self):
        super(MinimalCairoTest, self).__init__()
        self.set_size_request(300, 300)
        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_line_width(10)

        # now the same but using alpha
        cr.set_source_rgba(1.0, 0.0, 0.0, 0.3)
        cr.rectangle(140, 20, 120, 120)
        cr.fill_preserve()

        cr.set_source_rgba(0.0, 0.0, 1.0, 0.3)
        cr.stroke()

        cr.set_source_rgba(1.0, 1.0, 0.0, 0.3)
        cr.arc(150, 150, 70, 0, 2 * 3.14)
        cr.fill_preserve()
        cr.set_source_rgba(0.0, 1.0, 1.0, 0.3)
        cr.set_line_width(10)
        cr.stroke()


MinimalCairoTest()
Gtk.main()





No very good. The problem is, the area filled and the border are superposed, because the path is defined by the middle of the stroke, and ignores the line width[1].



I tried use the stroke as a mask, to avoid filling the area defined by the width of the stroke [2]:


#!/usr/bin/python

from gi.repository import Gtk
import cairo


class MinimalCairoTest(Gtk.Window):

    def __init__(self):
        super(MinimalCairoTest, self).__init__()
        self.set_size_request(300, 300)
        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_line_width(10)

        cr.rectangle(140, 20, 120, 120)
        cr.set_source_rgba(1.0, 0.0, 0.0, 0.3)
        cr.fill_preserve()

        # use the border as a mask
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.set_source_rgba(1.0, 1.0, 1.0, 1)
        cr.stroke_preserve()
        cr.set_operator(cairo.OPERATOR_OVER)

        cr.set_source_rgba(0.0, 0.0, 1.0, 0.3)
        cr.stroke()

        cr.arc(150, 150, 70, 0, 2 * 3.14)
        cr.set_source_rgba(1.0, 1.0, 0.0, 0.3)
        cr.fill_preserve()

        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.set_source_rgba(1.0, 1.0, 1.0, 1)
        cr.stroke_preserve()
        cr.set_operator(cairo.OPERATOR_OVER)

        cr.set_source_rgba(0.0, 1.0, 1.0, 0.3)
        cr.stroke()


MinimalCairoTest()
Gtk.main()





There are a problem: the border looks like if is not transparent. The problem really is the cairo operator source, with white, clear all what is in the surface.

I tried different alternatives, and finally asked in #cairo irc channel. The solution was provided by Søren Sandmann itself:


#!/usr/bin/python
 
from gi.repository import Gtk
import cairo
 
 
class MinimalCairoTest(Gtk.Window):
 
    def __init__(self):
        super(MinimalCairoTest, self).__init__()
        self.set_size_request(300, 300)
        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_line_width(10)

        cr.push_group()
        cr.rectangle(140, 20, 120, 120)
        cr.set_source_rgba(1.0, 0.0, 0.0, 1)
        cr.fill_preserve()
        cr.set_source_rgba(0.0, 0.0, 1.0, 1)
        cr.stroke()
        cr.pop_group_to_source()
        cr.paint_with_alpha(0.3)

        cr.push_group()
        cr.arc(150, 150, 70, 0, 2 * 3.14)
        cr.set_source_rgba(1.0, 1.0, 0.0, 1)
        cr.fill_preserve()
        cr.set_source_rgba(0.0, 1.0, 1.0, 1)
        cr.stroke()
        cr.pop_group_to_source()
        cr.paint_with_alpha(0.3)
 
MinimalCairoTest()
Gtk.main()


Excelent!
And the code is even cleaner. push_group creates a temporary surface, and can be painted, with alpha, using pop_group_to_source and paint_with_alpha.






[1] http://cairographics.org/tutorial/
[2] http://cairographics.org/operators/

domingo, enero 13, 2013

More Wikipedia news. Automatic index!

In one week with mixed news, I received a two good news, +Kartik Kumar Perisetla and +Anish Mangal prepared a Hindi version of the wikipedia activity, and 
+Ignacio Rodríguez worked in a Portuguese version. Kartik wrote a nice post about this too.

I asked to Kartik what other languages can be of interest in India, and he replied: "In india, Hindi, Gujrati and Punjabi are most common languages is North and West India; Telugu, Tamil, Malyalam, Kannada, Bengali are common in South and West india". Without doubt, India is a challenge!

One part of the process to create a offline wikipedia activity is tedious right now, create the list of articles used to start the selection, and prepare the index.html page used as home with the links to that articles. We have a good selection of pages in the English version, and usually is a good idea translate this selection and later add or remove a few articles. Then I decided create a script to use the interwiki links in the English articles to create a list of articles and index page  to use as a base.

My first experiments can be seen here:

A Farsi version:  

A Guaraní version:

A Italian version:

The script add a class to the links without a translation, and show it with a red background.
Of course, this does not do all the job, in a few cases there are garbage., somebody need check the words, found the remaining translations, add or remove articles depending on the target audience, etc, but I think is a  nice improvement.

sábado, enero 12, 2013

Informe del SugarDay del 15/11 en Buenos Aires

Ufff, este post tiene dos meses sin publicarse.
El SugarDay realizado durante la PyCon en noviembre, fue un éxito.
Participaron unas 15 personas. Algunos viejos conocidos y unos cuantos nuevos. Durante la mañana, hicimos varias charlas, y por la tarde trabajamos en grupos.
La primer charla fue una introducción al proyecto OLPC y SugarLabs.
La segunda, "Sugar en la Escuela" a cargo de +Laura Rosenfeld, +Yanel Cepeda y +Alvar Maciel, trató acerca de los usos que se le dá al software, las posibilidades y aportó interesantes sugerencias para el mejoramiento del mismo.

En la tercera charla, "Mate Marote", +Diego Fernández Slezak y +Matias Lopez y Resenfeld, del Laboratorio de Inteligencia Artificial Aplicada de la U.B.A, nos contaron acerca de sus investigaciones relacionadas con las neurociencias, y como con pequeñas aplicaciones se pueden desarrollar determinadas habilidades, como la memoria o la concentración. Una vez realizadas pruebas en laboratorio, Diego, Matias y su equipo, desarrollaron una actividad para las Xo, con juegos que desarrollan estas habilidades, y también una plataforma que permite agregar más juegos en la medida que se desarrollen. La charla concluyó con una invitación a programadores interesados en participar. La actividad para las XO fue puesta en uso en La Rioja, y ya han podido evaluar los primeros resultados.

  


Por último, hablamos de los desarrollos que se hicieron a lo largo del último año en OLPC y SugarLabs. Fundamentalmente, mostramos los prototipos de la nueva XO-4 y los cambios en Sugar para uso con touch.

Luego del almuerzo, fuimos trabajando por grupos. Algunos vieron como mejorar la performance de MateMarote y su uso de PyGame, otros instalaron entornos de desarrollo, algunos trabajaron en solucionar bugs y otros simplemente intercambiaron experiencias.

Fue productivo, mi agradecimiento a los organizadores de la PyCon por darnos este espacio.

.............


Unos días después de la PyCon, fui a presenciar la defensa de la tesis de licenciatura de Matias con su trabajo acerca de MateMarote. Dos puntos me resultaron particularmente interesantes: primero, cuando explicó los antecedentes, nos hizo acordar que hace unos pocos años, las notebooks eran objetos muy poco comunes, aun en un ámbito como la carrera de sistemas de la UBA, en esa época, hablar de una computadora por niño, era aun más loco de lo que hoy resulta. El segundo punto interesante, fue su explicación de las características innovadoras de Sugar, aun no disponibles en otros entornos. Después de un tiempo inmerso en el trabajo de resolver problemas, y hacer pequeñas mejoras, todos los días, fue refrescante escucharlo de alguien ajeno al proyecto.

sábado, noviembre 03, 2012

OLPC in BBC Horizons program

En el capítulo dedicado a "Accesible Tecnology", la tercera parte muestra el uso de las XO en Ntugi, Kenya.
El deployment es obra de un grupo canadiense de voluntarios y se puede leer una interesante resseña de su trabajo aqui.
Para ver el video, seguir este link y seleccionar la tercera parte.

lunes, octubre 22, 2012

La Confusión de la Tortuga

Quiero compartir una muy buena noticia, la traducción al español del libro “Turtle Confusion” de Barry Newell. Este libro plantea en el diálogo entre una tortuga y un docente, una colección de problemas a resolver, pero tambien comentarios acerca de como plantear estos problemas para que sean de utilidad a los alumnos. La versión original fué puesta por el autor bajo dominio público y autorizó su traduccion, que fué hecha por Melina Lucía Coronel y revisada y editada por Manuel Kaufmann, la imagen de la tapa es de Manuel Quiñones.
Esto no termina aqui, alentado por la repercusión, Barry ha decidido escribir una guia para docentes, con pistas acerca de los acertijos que en forma de poemas se incluyen en cada capítulo. Además Melina ya ha comenzado la traducción de otro libre del mismo autor: "Turtles Speak Mathematics".
Es interesante mencionar que Barry Newell es astrónomo y docente y vive en Australia, y Melina Lucía Coronel es Profesora de Inglés, y vive en Entre Ríos, Argentina, por lo que se trata de una colaboración intercontinental.... La magia de internet. También es interesante ver el desarrollo del proyecto, ya que se llevó a cabo completamente en github.
Pueden leer el libro on line o descargarlo, y también usar la actividad TurtleConfusion en Sugar


Me gusta mucho uno de los comentarios del autor acerca de como usar el cuadernillo:
"Se intenta que el material en éste cuadernillo sea de alguna manera confuso a primera vista. En la vida real, no podemos evitar sentirnos confundidos de vez en cuando. Éste sentimiento de confusión nos indica que nuestro entendimiento de una situación en particular es inadecuada... En otras palabras, la confusión representa una oportunidad para aprender.
Los adultos deberían reconocer el peligro que existe en proteger a los jóvenes de los sentimientos de confusión. La vida no nos ofrece sus problemas en una secuencia de paquetitos cuidadosamente graduada, cada una de los cuales se puede resolver por el ‘alumno promedio’ en una hora de clase. Se lo debemos a nuestros alumnos, a la posibilidad de sentirse confundidos a veces; a permitirles aprender de lidiar con, y hasta beneficiarse de, la confusión; a permitirles desarrollar respuestas, en lugar de entrar en pánico, frente a situaciones en las que pueden sentirse inicialmente sobrepasados."

Pequeñas lecciones aprendidas usando Cairo (1)

Portando actividades de gtk2 a gtk3 aprendimos algunos trucos relacionados con Cairo.
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.

sábado, septiembre 22, 2012

SugarLabs Day en la PyCon Argentina 2012

Del 12 al 17 de Noviembre, se realizará en Buenos Aires "PyCon Argentina 2012", la cuarta edición de la Conferencia sobre el lenguaje de programación Python, Software Libre y tecnologías relacionadas, en la Universidad Nacional de Quilmes (Bernal, Gran Buenos Aires), UrbanStation y EducacionIT (Capital Federal)
En ese ámbito, tendremos un día completo, el Jueves 15, para Sugar, comenzando con un taller para ayudar a quienes se inician, y continuando con hacking por grupos de acuerdo a los intereses de los participantes.
Seguramente tendremos nuevos desarrollos y "juguetes" para compartir :)
En los días posteriores hay muchas charlas de primer nivel, que son muy nuevas para descubrir nuevas tecnólogías y a la comunidad Python. Nuestro compañero Manuel Quiñones, por ejemplo, dará una charla acerca de port a Gtk3. Pueden consultar el cronograma completo y la lista de oradores. La inscripción es gratuita, pero se necesita preinscribirse por web porque hay cupos limitados. Tienen más informacion en la invitacion, y cuando se anoten, no olviden ir a la página de proyectos, y anotarse para participar en el SugarLabs Day.

martes, julio 10, 2012

PyCamp 2012

Que bueno que estuvo el PyCamp! Pude participar solamente 2 días, pero fueron muy productivos.
  • Me senté con Hugo Ruscitti, autor de Pilas, que está trabajando en una librería para hacer más sencillo el uso de cairo desde python. Es interesante, porque trabajando con cairo, a nivel de aplicaciones, se nota que es de más bajo nivel que lo que se necesita, y las operaciones son complicadas, y suceptibles a errores.
  • Diego Sarmentero, de NinjaIDE,me explicó, como aprovechar su código para hacer  autocompletado  y análisis de clases en Develop.
  • Con Martín Gaitan, estuvimos explorando como crear ebooks (en formato epub), con las páginas obtenidas de una lista de urls (repo). Quiero hacer algo con eso en Browse, por ejemplo creando un ebook con las páginas seleccionadas en los bookmarks. Hay que analizar un poco el grado de limpieza que se quiere hacer en el html.
  • Con Manuel Quiñones hicimos una larga sesión de trabajo en el port de sugar a gtk3, y logramos que arranque, aunque por ahora solo se ve una pantalla blanca y la toolbar superior.
  • Mostramos Sugar y ayudamos a preparar entornos de desarrollo a varios interesados, en algunos casos usando VM y en otros con sugar-build.
Un evento excelente, con conversaciones interesantes en cada comida, y muy bien ambiente.


martes, abril 17, 2012

Reunión Sugarlabs Argentina - Marzo 2012

Sin duda una de las mejores reuniones de los últimos tiempos, organizada por Hector y con la ayuda de un buen asado :)

Contamos con una buena participación, Valentin Basel y sus robots (de Córdoba), Manuel (manuq) Quiñones (de Santa Fé), Manuel (humitos) Kaufmann de Entre Rios, y los locales Hector (karucha) Sanchez, Alejandro (alecu) Cura, Hugo (pilas)Ruscitti y yo. Luego de comer y charlar bastante, malabarismos y demas divertimentos, hicimos planes para este año.

Unos cuantos vamos a participar en el PyCamp, en Verónica del 6 al 9 de Julio. Va a ser una buena oportunidad para difundir Sugar en la comunidad python y encarar algun proyecto en conjunto.

Tambien queremos ir al eduJam, encuientro de desarrolladores a realizarse el 11 y 12 de mayo en Montevideo.

Por último, durante la PyCon 2012, a realizarse del 12 al 17 de noviembre en Quilmes, Buenos Aires, nos han propuesto destinar un día completo de la semana para Sugar, por lo que hay que organizarlo. Para difundir esto, hemos decidido participar de los distintos PyDay que se realizan en diferentes ciudades, probablemente con una lighting talk, que prepararemos en la lista de correo.

Asi que va a ser un año con buena actividad, y lo bueno es que lo podemos preparar con tiempo.

Wikipedia (3)

En este post, por ahora el último acerca de las actividades wikipedia, les comento cual es el estado actual.
Las actividades wikipedia en ingles y español que ya existían fueron actualizadas. Han crecido un poco de tamaño por lo que tengo que hacer una nueva seleccion de artículos.
Ademas, se han agregado versiones en polaco, frances, quechuakinyarwanda, y una actividad basada en la Simple English wikipedia, con artículos más reducidos.
Armar nuevas actividades en otros idiomas es muy sencillo. si alguien está interesado en participar en el proceso, estoy disponible para ayudarlo a comenzar, no es necesario programar.
--------------
In this post, for now the last about the wikipedia activities, I want comment what is the current state.
Wikipedia activities in English and Spanish than already existed were updated. Have grown slightly in size so I have to make a new selection of items.
We have added versions in Polish, French, Quechua and Kinyarwanda, and an activity based on the Simple English Wikipedia, with smaller articles.
Assemble new activities in other languages ​​is easy. if anyone is interested in participating in the process, I am available to help you start, no programming is required.