Ubuntu Opportunistic Developers Week March 2010 - Creating stunning interfaces with Cairo - Laszlo Pandy - Mar 3 2010

(12:01:55 PM) laszlok: Hello everyone, i'm gonna be talking about using cairo with python today
(12:02:30 PM) laszlok: I haven't prepared any slides, but I'll be using some links
(12:02:57 PM) laszlok: and it will be less structured than usual, so feel free to shout out or ask questions at any time in #ubuntu-classroom-chat
(12:03:20 PM) laszlok: I won't mind taking a large detour, we'll probably have plenty of time for it
(12:03:52 PM) laszlok: So cairo is a drawing API
(12:04:05 PM) laszlok: if you know about SVG graphics, it does the same sort of thing
(12:04:27 PM) laszlok: it has strokes, fills, gradients, etc
(12:04:49 PM) laszlok: Its also a very modern drawing api
(12:04:55 PM) laszlok: the library was written quite recently
(12:05:34 PM) laszlok: I mean modern in that it has good alpha support, and really good antialiasing
(12:05:46 PM) laszlok: so when you draw graphics they scale well and look very clean
(12:06:17 PM) laszlok: unlike previous generation APIs like Java graphics (don't get me started)
(12:07:07 PM) laszlok: Cairo integrates really well with GTK, in fact most widgets in GTK are now drawn using cairo
(12:07:42 PM) laszlok: I will show you how to use it with GTK and also how to use some other cairo backends like svg, pdf, and png
(12:08:26 PM) laszlok: In terms of creating stunning interfaces, it can be done with cairo. If you create a stunning GTK app then you are doing it with cairo anyway ;)
(12:08:42 PM) laszlok: however cairo is low level
(12:09:15 PM) laszlok: if you are using cairo directly you are drawing all the lines and calculating all the geometry yourself
(12:10:09 PM) laszlok: There was a talk yesterday about goocanvas, which uses cairo and gives a much higher level view. You can deal with objects instead of geometry calculations.
(12:10:36 PM) laszlok: But if anyone has questions about that, please ask
(12:10:55 PM) laszlok:
(12:11:29 PM) laszlok: here is a page on the cairo website with some sample code and how it will look
(12:11:45 PM) laszlok: the code is in C, but it is quite similar to python as you will see
(12:12:55 PM) laszlok: QUESTION: Can we build all the application interface using Cairo (except for the Window container)?
(12:13:59 PM) laszlok: yes you can, but it will involve a lot of trickiness if you want to detect mouse clicks on many different objects
(12:14:37 PM) laszlok: it will work fine for a simple drawing, but once you start using lots of objects you might find the geometry to figure out which one is clicked it too much
(12:14:53 PM) laszlok: this is why things like goocanvas were invented; to automate those things
(12:15:39 PM) laszlok: QUESTION: can we use cairo to create the interface separate from the logic that runs the program?
(12:15:58 PM) laszlok: yes, in the same way that you would have a GTK interface separate from the program logic
(12:16:20 PM) laszlok: QUESTION: maybe for later, is there a preferred way of doing animations in cairo?
(12:16:53 PM) laszlok: cairo does not provide support for animations, so it has to be done essentially the same as animations in other drawing apis
(12:17:36 PM) laszlok: that means having a timer to redraw the screen and have code to redraw the whole screen (or just the parts that change)
(12:18:24 PM) laszlok: so as you can see in the samples, cairo has primitives for arcs, lines, etc.
(12:18:45 PM) laszlok: Thinking about an interface in these primitives is a bit low level, but it gives you the great flexibility
(12:19:07 PM) laszlok: QUESTION: Does the animation redraw method you just described use a lot of cpu power?
(12:19:23 PM) laszlok: if your drawing is complex, it probably will
(12:19:51 PM) laszlok: but cairo is quite efficient, and allows you flexibility for caching drawings
(12:20:27 PM) laszlok: for example if you have a background which requires a long time to draw, you can draw it to an ImageSurface in memory instead
(12:20:39 PM) laszlok: and then it is one operation to draw it on screen
(12:21:20 PM) laszlok: QUESTION: would like to add to performance that strokes are the ones that are expensive.
(12:21:37 PM) laszlok: that's not a question ;)
(12:22:09 PM) laszlok:
(12:22:35 PM) laszlok: here is the python documentation for cairo
(12:22:49 PM) laszlok: that is good reference when looking at the next link
(12:23:03 PM) laszlok:
(12:23:19 PM) laszlok: here is some poorly commented python code I prepared
(12:23:29 PM) laszlok: QUESTION: waht are all the required components to start working on cairo+python?
(12:23:36 PM) laszlok: only cairo, python and pycairo
(12:24:03 PM) laszlok: if you want to render directly on screen (as opposed to png or svg) you should have pygtk installed as well
(12:24:45 PM) laszlok: for example, in the code i prepared I am importing both gtk and cairo
(12:25:03 PM) laszlok: copy and paste this code into your editor
(12:25:14 PM) laszlok: if you run it with no arguments you will get a gtk window
(12:25:41 PM) laszlok: if you give it 'png', 'svg' or 'pdf' as an argument, it will generate that kind of file
(12:25:59 PM) laszlok: so lets take a look at the GTK code, in the DrawingInterface class
(12:26:50 PM) laszlok: it creates a window, and adds a gtk.DrawingArea
(12:27:14 PM) laszlok: the DrawingArea is a widget which is like a blank canvas we can draw to
(12:28:00 PM) laszlok: then we set the size of the window, and show it
(12:28:07 PM) laszlok: not much to see there
(12:28:33 PM) laszlok: the expose event is the event when the X server tells the window to redraw itself
(12:28:47 PM) laszlok: so this is what we are using to trigger our drawing code
(12:29:27 PM) laszlok: also notice that in the GTK code the cairo context is created directy from the widget. GTK is integrated with cairo and makes it easy
(12:29:54 PM) laszlok: the context is what holds all the information about your drawing as you add lines and shapes
(12:30:31 PM) laszlok: the draw_rounded_rentangle() method is converted from the C example on
(12:30:47 PM) laszlok: if you compare them you can see it is mostly identical code
(12:31:08 PM) laszlok: QUESTION: please explain the underlying functiosn used in on_expose
(12:31:23 PM) laszlok:
(12:31:51 PM) laszlok: in on_expose we create the cairo context associated with the widget
(12:32:01 PM) laszlok: so when we draw using that context, it will draw on the widget
(12:32:30 PM) laszlok: widget.get_allocation() returns a renctangle with the width and height of the window, so we know how much space we have to draw
(12:32:50 PM) laszlok: and self.drawing.draw() calls the method on the drawing class three lines below that
(12:33:10 PM) laszlok: QUESTION: will the get_allocation be called only after drawing.draw is called?
(12:33:16 PM) laszlok: this is equivalent to:
(12:33:25 PM) laszlok: rectangle = widget.get_allocation()
(12:33:34 PM) laszlok: self.drawing.draw(ctx, rectangle)
(12:34:13 PM) laszlok: so the draw() method can know the size of the widget
(12:34:48 PM) laszlok: by default, the DrawingArea widget is the default gtk colour
(12:35:08 PM) laszlok: so in the draw() method I create a rectangle the size of the widget and fill it with white
(12:35:34 PM) laszlok: the context remembers things like rectangles i have created, and also what colour i set it
(12:36:00 PM) laszlok: after I call fill() the rectangle is removed from the context and put on the screen, but the colour is still set
(12:36:14 PM) laszlok: so remember to change your colour or it will be whatever you set it previously
(12:36:28 PM) laszlok: QUESTION: Is it possible to do some basic 3d transformation? (Like perspective on GIMP)
(12:36:38 PM) laszlok: cairo is a 2d canvas, but you can do transformation
(12:36:52 PM) laszlok: to fake a perspective
(12:37:20 PM) laszlok: take a look at
(12:38:04 PM) laszlok: In get_gradient()
(12:38:15 PM) laszlok: you can see cairo makes gradients really simple
(12:38:56 PM) laszlok: you create a gradient with a start and end point to define how long the colour change will be and in what direction
(12:39:14 PM) laszlok: and then you set stops on the gradient, just like you would do on inkscape or other graphics programs
(12:39:36 PM) laszlok: the first argument to add_color_stop_rgb is the offset between 0 and 1
(12:39:51 PM) laszlok: so i set two colour stops. One at the beginning and one at the end
(12:40:21 PM) laszlok: you can easily add a third one in set it to offset 0.5 and your gradient will blend three colours
(12:41:09 PM) laszlok: now look at the bottom part of the code where it says if arg == 'pdf':
(12:41:40 PM) laszlok: i mentioned earlier about using image surfaces to store your drawing in memory
(12:41:58 PM) laszlok: surfaces also allow you do store in files
(12:42:07 PM) laszlok: QUESTION: can you set the gradient to go through the hues in the opposite direction?
(12:42:09 PM) laszlok: yes
(12:42:15 PM) laszlok: either reverse the offsets
(12:42:27 PM) laszlok: (set the first one to offset 1, and second to offset 0)
(12:43:34 PM) laszlok: or reverse the pairs of (x,y) parameters to the LinearGradient constructor
(12:44:08 PM) laszlok: QUESTION: does the context variable acts as a placeholder or as a memory buffer?
(12:44:30 PM) laszlok: it is the same as the drawing context created from the GTK widget except it writes to a file
(12:45:10 PM) laszlok: so it will store your drawing in memory and write it to the file when you complete a fill() or stroke()
(12:45:25 PM) laszlok: QUESTION: How to make it write to a jpg file?
(12:46:05 PM) laszlok: JPG file compression is meant for pictures where there are not perfectly smooth lines
(12:46:30 PM) laszlok: PNG compression works much better for drawings, things with smooth and sharp borders
(12:46:58 PM) laszlok: so cairo does not support JPG directly, i would write to svg or png and use imagemagick to convert it
(12:48:41 PM) laszlok: so as you can see, cairo surfaces make it really easy to export to other formats
(12:49:09 PM) laszlok: and if you were writing on windows or mac, you would use a surface specifically for the platform and the rest of the api would be the same
(12:50:14 PM) laszlok: any questions?
(12:50:47 PM) laszlok: QUESTION: does cairo do that "redraw only changed parts" automagically, or do we manually tell what changed ?
(12:50:52 PM) laszlok: you could have to do that manually
(12:51:08 PM) laszlok: in this case i redraw the white rectangle each time, therefore blanking the entire screen
(12:51:25 PM) laszlok: this is something that goocanvas would also automate for you
(12:52:26 PM) laszlok: QUESTION: How difficult is it to use cairo in combination with pygoocanvas?  (For example, if I wanted to draw/animate something like a progress indicator on top of my goocanvas while waiting for goocanvas to update during a slow operation.)
(12:52:47 PM) laszlok: that seems like a strange use case, but it should work
(12:52:57 PM) laszlok: theoretically you can use cairo to draw on top of any GTK widget
(12:53:04 PM) laszlok: as long as the proper flags are set
(12:55:03 PM) laszlok: QUESTION: What are the advantages of using cairo directly instead of through goocanvas?
(12:55:27 PM) laszlok: goocanvas is much higher level
(12:55:36 PM) laszlok: and cairo is very lightweight
(12:56:05 PM) laszlok: if you are doing something simple and want the flexibility, or don't mind doing the drawing manually then cairo is the way to go
(12:56:40 PM) laszlok: its really easy to get started with, and can work with GTK mouse clicks, etc well for simpler things
(12:57:08 PM) laszlok: if you know you have a bunch of objects you want to drag around on the screen, goocanvas will probably make your life much easier
(12:57:55 PM) laszlok: QUESTION: the png format uses the format_argb32 constant. the manual shows 3 more. can u tell the formats they specify?
(12:58:18 PM) laszlok: referring to
(12:58:50 PM) laszlok: FORMAT_ARGB32 is colour surface with alpha support
(12:59:10 PM) laszlok: FORMAT_RGB24 is the same without alpha support so you will not be able to do transparency
(12:59:40 PM) laszlok: the others are for alpha only masks and do not store colour values
(01:00:20 PM) laszlok: these formats are for image surfaces. You may need to specify alpha only if you want to make a transparency mask

MeetingLogs/OpWeek1003/CairoUI (last edited 2010-03-03 18:54:04 by pool-71-182-100-128)