http://cairographics.org/tutorial
  • wget http://cairographics.org/cairo-tutorial.tar.gz
  • tar xzf cairo-tutorial.tar.gz
  • cd cairo-tutorial
  • make
  • cat README
  • IRC: irc.freenode.net #cairo
    Carl Worth Red Hat, Inc. linux.conf.au 2006-01-26 http://cairographics.org Jaggies Fuzzies Fireworks
  • Let application authors know there are options
  • Learn to use cairo—patch the applications
  • Write your own cairo-using applications
  • Various shell cairo programs #include <cairo.h> #include <cairo-xlib.h> int main (void) { Display *dpy = XOpenDisplay (0); Window w = XCreateSimpleWindow (dpy,RootWindow (dpy, 0), 0, 0, WIDTH, HEIGHT, 0, 0, WhitePixel (dpy, 0)); cairo_surface_t *surface = cairo_xlib_surface_create (dpy, w, DefaultVisual (dpy, DefaultScreen (dpy)), WIDTH, HEIGHT); XEvent ev; XSelectInput (dpy, w, ExposureMask); XMapWindow (dpy, w); while (XNextEvent (dpy, &ev) == 0) if (ev.type == Expose && !ev.xexpose.count) { cairo_t *cr = cairo_create (surface); draw (cr); cairo_destroy (cr); } } #include <gtk/gtk.h> static gboolean handle_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data) { cairo_t *cr = gdk_cairo_create (widget->window); draw (cr); cairo_destroy (cr); return FALSE; } int main (int argc, char **argv) { GtkWidget *window, *drawing_area; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT); drawing_area = gtk_drawing_area_new (); gtk_container_add (GTK_CONTAINER (window), drawing_area); g_signal_connect (drawing_area, "expose-event", G_CALLBACK (handle_expose), NULL); gtk_widget_show_all (window); gtk_main (); } #include <cairo.h> int main (void) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); cr = cairo_create (surface); draw (cr); cairo_surface_write_to_png (surface, "foo.png"); cairo_surface_destroy (surface); cairo_destroy (cr); return 0; } #include <cairo.h> #include <cairo-pdf.h> int main (void) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_pdf_surface_create ("foo.pdf", WIDTH, HEIGHT); cr = cairo_create (surface); draw (cr); cairo_show_page (cr); cairo_surface_destroy (surface); cairo_destroy (cr); return 0; } #!/usr/bin/env python import gtk import cairo def expose (widget, event): cr = widget.window.cairo_create () draw (cr) win = gtk.Window () win.connect ('destroy', gtk.main_quit) win.set_default_size(WIDTH, HEIGHT) drawingarea = gtk.DrawingArea () win.add (drawingarea) drawingarea.connect ('expose_event', expose) win.show_all () gtk.main () #!/usr/bin/env python import cairo surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT) cr = cairo.Context (surface) draw (cr) surface.write_to_png ('foo.png') autoimport Cairo; cairo_t cr = new (WIDTH, HEIGHT); draw (cr);
  • C++ (cairomm)
  • Haskell (hscairo)
  • Java (CairoJava, cairo-java)
  • Common Lisp (cl-cairo)
  • Nickle (cairo-5c)
  • Objective Caml (cairo-ocaml)
  • perl (cairo-perl)
  • python (pycairo)
  • ruby (rcairo)
  • squeak (cairo-squeak)
  • http://cairographics.org/tutorial http://cairographics.org/cairo-tutorial.tar.gz
  • tar xzf cairo-tutorial.tar.gz
  • cd cairo-tutorial
  • make
  • cat README
  • IRC: irc.freenode.net #cairo
    Here comes the fun part
    • Paths
      • construction
      • filling, stroking
    • Images
      • loading from disk
      • using as source
      • transforming/filtering
    • Text
      • “Toy” API
      • “Full” API
    • Paths
      • cairo_stroke
      • cairo_fill
    • Images
      • cairo_paint
      • cairo_mask
      • cairo_paint_with_alpha
    • Text
      • cairo_show_text (“toy”)
      • cairo_show_glyphs (“full”)
    • Paths consist of lines and splines:
      • cairo_move_to
      • start new sub path, set current point
      • cairo_line_to
      • add line segment to path
      • cairo_curve_to
      • add Bézier spline to path
      • cairo_close_path
      • add line segment to last move_to point
    • cairo_stroke
      • Paints the path itself as stroked by a pen
      • Controlled by various stroke parameters:
        • cairo_set_line_width
        • cairo_set_line_cap
        • cairo_set_line_join
        • cairo_set_miter_limit
        • cairo_set_dash
    • CAIRO_LINE_CAP_BUTT
    • CAIRO_LINE_CAP_ROUND
    • CAIRO_LINE_CAP_SQUARE
    • CAIRO_LINE_JOIN_BEVEL
    • CAIRO_LINE_JOIN_ROUND
    • CAIRO_LINE_JOIN_MITER
  • Adds a line segment (if necessary) to the
  • start of the path
  • Draws a join from that line to the first
  • element of the path
    • Paints the “inside” of the path
    • Two different ways to determine inside-ness
      • cairo_set_fill_rule:
      • CAIRO_FILL_RULE_WINDING CAIRO_FILL_RULE_EVEN_ODD
  • To test a point for inside-ness, imagine a ray
  • from the point and extending to infinity (any direction) and examine path crossings
  • EVEN_ODD counts crossings and fills when odd
  • WINDING counts up/down for left/right crossings
  • and fills when the final number is not zero
  • All drawing occurs with the source pattern
  • Uniform-color sources can be set
  • with or without alpha:
    • cairo_set_source_rgb
    • cairo_set_source_rgba
  • cairo_stroke and cairo_fill consume the path
  • Variants are available to preserve the path:
    • cairo_stroke_preserve
    • cairo_fill_preserve
  • This is a variation from PostScript and PDF
    • The cairo approach differs in different ways
    • We think this way is better (of course)
    • cairo_rectangle
    • cairo_arc
    • cairo_text_path
    • cairo_glyph_path
    • Relative-coordinate variants:
      • cairo_rel_move_to
      • cairo_rel_line_to
      • cairo_rel_curve_to
    • Single matrix combines rotation, translation,
    • scale and shear
    • Non-projective transformations
      • Pen doesn't change shape along the stroke
    • Transformations are cumulative
      • translate, scale != scale, translate
    • cairo_save and cairo_restore
    • Very useful for bracketing function bodies
    • Eliminates graphics state side effects
    • NOTE: Path is not part of graphics state
      • Path is not affected by cairo_save/restore
      • Useful for path-generating functions
  • cairo_clip
  • Intersects path with current clip to further
  • restrict drawing
  • Pixel-aligned clipping is much faster
  • cairo_clip_preserve is available as well
    • Surface patterns
      • Image from disk
      • Results of cairo drawing
    • Gradient patterns
      • linear gradients
      • radial gradients
    • “Toy” API:
      • Useful for demos like we are writing today
      • No real layout—not useful for the majority
      • of writing systems in the world
    • “Full” API:
      • User must do OS-dependent font selection
      • User must access font glyph IDs directly
      • User must do all text layout
    • Simple font selection
      • family, weight, slant
      • OS independent
      • No font listing support
    • UTF-8 text drawing and extents functions
    • Still supports full font transformations
  • Just use pango
  • C has no exceptions
  • Checking each return is tedious
  • C programmers rarely bother
  • Lots of broken programs result
  • Cairo stores status value when error occurs
  • API “shuts down” when an error occurs
  • All cairo functions are benign
  • (and well defined) after any error.
  • cairo_status can be called when convenient
  • Error status values propagate across objects