diff options
Diffstat (limited to 'cairo/cairo_slides.py')
-rwxr-xr-x | cairo/cairo_slides.py | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/cairo/cairo_slides.py b/cairo/cairo_slides.py new file mode 100755 index 0000000..4689506 --- /dev/null +++ b/cairo/cairo_slides.py @@ -0,0 +1,553 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +# Copyright 2007 Carl Worth <cworth@redhat.com> +# Copyright 2007 Behdad Esfahbod <besfahbo@redhat.com> + +# A slides file should populate the variable slides with +# a list of tuples. Each tuple should have: +# +# - Slide content +# - User data +# - Canvas width +# - Canvas height +# +# Slide content can be a string, a list of strings, +# a function returning one of those, or a generator +# yielding strings. The user data should be a dictionary or +# None, and is both used to communicate options to the +# renderer and to pass extra options to the theme functions. +# +# A function-based slide content will be passed a renderer object. +# Renderer is an object similar to a cairo.Context and +# pangocairo.CairoContext but has its own methods too. +# The more useful of them here are put_text, put_image, and +# set_allocation. See their pydocs. + +slides = [] +def slide_add(f, data=None, width=800, height=600): + slides.append ((f, data, width, height)) + return f + +import pango, pangocairo, cairo, os, signal + +# We use slide data to tell the theme who's speaking. +# That is, which side the bubble should point to. +behdad = -1 +cworth = +1 +whois = None +def who(name): + global whois + whois = name +# And convenience functions to add a slide. Can be +# used as a function decorator, or called directly. +def slide_who(f, who, data=None): + if data: + data = dict (data) + else: + data = {} + data['who'] = who + return slide_add (f, data) +def slide(f, data=None): + return slide_who (f, whois, data=data) +def slide_noone(f, data=None): + return slide_who (f, None, data=data) +def slide_cworth(f, data=None): + return slide_who (f, cworth, data=data) +def slide_behdad(f, data=None): + return slide_who (f, behdad, data=data) + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (400, 100) + r.put_text ( +"""Co-maintaining cairo: +cool community +cool code""", desc="50", valign=1) + + r.move_to (0, 450) + r.put_text ("""Behdad Esfahbod\n<span font_desc="16">besfahbo@<span foreground="#c00">redhat</span>.com</span>""", + desc="20", halign=1, valign=-1) + + r.move_to (800, 450) + r.put_text ("""Carl Worth\n<span font_desc="16">cworth@<span foreground="#c00">redhat</span>.com</span>""", + desc="20", halign=-1, valign=-1) + +who (cworth) + +slide_noone("Intro") + +slide("Rendering model") + +def paint_checkers (cr): + image = cairo.ImageSurface (cairo.FORMAT_RGB24, 30, 30) + cr2 = cairo.Context (image) + cr2.rectangle ( 0, 0, 15, 15) + cr2.rectangle (15, 15, 15, 15) + cr2.set_source_rgb (.75, .75, .75) + cr2.fill () + cr2.rectangle (15, 0, 15, 15) + cr2.rectangle ( 0, 15, 15, 15) + cr2.set_source_rgb (.94, .94, .94) + cr2.fill () + checker = cairo.SurfacePattern (image) + checker.set_filter (cairo.FILTER_NEAREST) + checker.set_extend (cairo.EXTEND_REPEAT) + cr.set_source (checker) + cr.paint () + +def gnome_foot_path (cr): + # Originally 96 x 118, scaling to fit in 80x80 + cr.save () + cr.translate ((96 - 80) / 2., 0) + cr.scale (80. / 118., 80. / 118.) + cr.move_to (86.068, 1.) + cr.curve_to (61.466, 0., 56.851, 35.041, 70.691, 35.041) + cr.curve_to (84.529, 35.041, 110.671, 0., 86.068, 0.) + cr.move_to (45.217, 30.699) + cr.curve_to (52.586, 31.149, 60.671, 2.577, 46.821, 4.374) + cr.curve_to (32.976, 6.171, 37.845, 30.249, 45.217, 30.699) + cr.move_to (11.445, 48.453) + cr.curve_to (16.686, 46.146, 12.12, 23.581, 3.208, 29.735) + cr.curve_to (-5.7, 35.89, 6.204, 50.759, 11.445, 48.453) + cr.move_to (26.212, 36.642) + cr.curve_to (32.451, 35.37, 32.793, 9.778, 21.667, 14.369) + cr.curve_to (10.539, 18.961, 19.978, 37.916, 26.212, 36.642) + cr.line_to (26.212, 36.642) + cr.move_to (58.791, 93.913) + cr.curve_to (59.898, 102.367, 52.589, 106.542, 45.431, 101.092) + cr.curve_to (22.644, 83.743, 83.16, 75.088, 79.171, 51.386) + cr.curve_to (75.86, 31.712, 15.495, 37.769, 8.621, 68.553) + cr.curve_to (3.968, 89.374, 27.774, 118.26, 52.614, 118.26) + cr.curve_to (64.834, 118.26, 78.929, 107.226, 81.566, 93.248) + cr.curve_to (83.58, 82.589, 57.867, 86.86, 58.791, 93.913) + cr.line_to (58.791, 93.913) + cr.restore () + +@slide +def imaging_model (r): + + paint_checkers (r.cr) + + r.allocate (100, 130, 550, 450) + r.cr.translate (200, 130) + + ### Column 1 + r.cr.save () + + r.cr.move_to (0, 0) + r.cr.set_source_rgb (0, 0, 0) + r.put_text ("source", height=40, valign=-1) + + def done_with_header (): + r.cr.translate (-40, 20) + done_with_header () + + # Solid source + def set_solid_source (): + r.cr.set_source_rgba (.87, .64, .13, 0.6) + set_solid_source () + r.cr.rectangle (0, 0, 80, 80) + r.cr.fill () + + def next_row (): + r.cr.translate (0, 110) + + next_row () + + # Linear source + def set_linear_source (): + linear = cairo.LinearGradient (0, 0, 0, 80) + linear.add_color_stop_rgba (0.0, .96, .43, .11, 1.0) + linear.add_color_stop_rgba (0.2, .96, .43, .11, 1.0) + linear.add_color_stop_rgba (0.5, .96, .43, .11, 0.2) + linear.add_color_stop_rgba (0.8, .11, .22, .96, 1.0) + linear.add_color_stop_rgba (1.0, .11, .22, .96, 1.0) + r.cr.set_source (linear) + set_linear_source () + r.cr.rectangle (0, 0, 80, 80) + r.cr.fill () + + next_row () + + # Radial source + def set_radial_source (): + radial = cairo.RadialGradient (40, 40, 0, 40, 40, 40) + radial.add_color_stop_rgba (0.0, .55, .15, .63, 1.0) + radial.add_color_stop_rgba (0.3, .55, .15, .63, 1.0) + radial.add_color_stop_rgba (1.0, .91, .89, .39, 0.5) + r.cr.set_source (radial) + set_radial_source () + r.cr.rectangle (0, 0, 80, 80) + r.cr.fill () + + next_row () + + # Image pattern source + def set_image_source (): + image = cairo.ImageSurface.create_from_png ("pumpkin-small.png") + r.cr.set_source_surface (image, 0, 0) + set_image_source () + r.cr.paint () + + r.cr.restore () + + def next_column (): + r.cr.translate (200, 0) + + next_column () + + ### Column 2 + r.cr.save () + + r.cr.move_to (0, 0) + r.cr.set_source_rgb (0, 0, 0) + r.put_text ("mask", height=40, valign=-1) + + done_with_header () + + # Gnome foot + gnome_foot_path (r.cr) + r.cr.set_line_width (1.0) + r.cr.stroke () + + next_row () + + # Gnome foot + gnome_foot_path (r.cr) + r.cr.set_line_width (1.0) + r.cr.stroke () + + next_row () + + # 'G' + def draw_G (): + r.cr.move_to (40, 0) + r.put_text ("<b>G</b>", height=80, valign=1) + draw_G () + + next_row () + + # Radial mask + def get_radial_mask_pattern (): + radial = cairo.RadialGradient (40, 40, 0, 40, 40, 40) + radial.add_color_stop_rgba (0.0, 0, 0, 0, 1.0) + radial.add_color_stop_rgba (0.3, 0, 0, 0, 1.0) + radial.add_color_stop_rgba (1.0, 0, 0, 0, 0.0) + return radial + r.cr.set_source (get_radial_mask_pattern ()) + r.cr.rectangle (0, 0, 80, 80) + r.cr.fill () + + r.cr.restore () + next_column () + + ### Column 3 + r.cr.save () + + r.cr.move_to (0, 0) + r.cr.set_source_rgb (0, 0, 0) + r.put_text ("source\nIN mask\nOVER dest", height=120, valign=-1) + + done_with_header () + + # Stroked GNOME foot + set_solid_source () + gnome_foot_path (r.cr) + r.cr.set_line_width (6) + r.cr.stroke () + + next_row () + + # Filled GNOME foot + set_linear_source () + gnome_foot_path (r.cr) + r.cr.fill () + + next_row () + + # Filled 'G' + set_radial_source () + draw_G () + + next_row () + + # Masked image + set_image_source () + r.cr.mask (get_radial_mask_pattern ()) + + r.cr.restore () + + return "" + +who (cworth) + +slide_noone("History") + +@slide +def trapezoid (r): + r.set_line_width (1) + r.set_source_rgb (0, 0, 0) + pixel_size = 800 / 10 + for x in range(0 - 50, 800 + 50, pixel_size): + r.move_to (x, -50) + r.line_to (x, 600 + 50) + r.stroke () + for y in range(0 - 50, 600 + 50, pixel_size): + r.move_to (-50, y) + r.line_to (800 + 50, y) + r.stroke () + r.scale (pixel_size / 10, pixel_size / 10) + + # Interior + r.save () + r.move_to (0, 25) + r.line_to (100, 25) + r.line_to (100, 50) + r.line_to (0, 50) + r.close_path () + r.clip () + + r.move_to (30, 20) + r.line_to (10, 60) + r.line_to (75, 55) + r.line_to (65, 15) + r.close_path () + r.clip () + + r.set_source_rgba (.2, .2, .7, 0.5) + r.paint () + r.restore () + + # top + r.set_source_rgb (0, 0, 0) + r.move_to (0, 25) + r.put_text ("top", desc="5", halign=1, valign=-1) + r.move_to (0, 25) + r.line_to (100, 25) + r.stroke () + + # bottom + r.move_to (100, 50) + r.put_text ("bottom", desc="5", halign=-1, valign=-1) + r.move_to (0, 50) + r.line_to (100, 50) + r.stroke () + + # left + r.set_source_rgb (.2, .6, .2) + r.move_to (30, 20) + r.put_text ("left", desc="5", halign=1, valign=-1) + r.move_to (30, 20) + r.line_to (10, 60) + r.stroke () + + # right + r.set_source_rgb (.8, .2, .2) + r.move_to (65, 15) + r.put_text ("right", desc="5", halign=-1, valign=-1) + r.move_to (65, 15) + r.line_to (75, 55) + r.stroke () + + r.allocate (0, 0, 100, 60) + +pid = None + +@slide +def geotv (r): + r.move_to (400, 300) + r.put_image ("geotv.jpg", width=900) + r.move_to (100, 400) + r.set_source_rgb (1, 1, 1) + r.put_text ("April 2002", desc="40", halign=1) + yield "" + if r.viewer.is_interactive(): + global pid + if not r.viewer.is_test_run() and not r.viewer.is_slideshow() and not pid: + pid = os.spawnlp (os.P_NOWAIT, 'mplayer', 'mplayer', '-fs', 'geotv.mpg') + print "mplayer spawned with pid %d" % pid + yield "" + pid = None + +@slide +def first_post (r): + r.move_to (400, 300) + r.put_text("""Subject: Xr API strawman +To: Keith Packard <keithp@keithp.com> +Date: Tue, 4 Jun 2002 19:55:06 +0000 + +Hi Keith, + +I read up a bit on PostScript. It's the obvious source of the +proposals you were making. + +I like it much better than GL as a model for Xr. It's cleaner in +general, (IMHO). And PS has larger overlap with the primitives we want +in Xr, (eg. bezier curves as opposed to just triangle meshes). + +So, here's what I'm thinking of so far. This sticks fairly close to +PostScript, (but with an explicit rather than an implicit state +object). + +Feedback welcome, + +-Carl""", desc="Monospace", markup=False, width=800, height=600, align=pango.ALIGN_LEFT) + +@slide +def api_strawman (r): + r.move_to (400, 300) + r.put_text("""/* Opaque state structure */ +typedef struct _XrState XrState; + +/* Functions for manipulating state objects */ + +/* XXX: Do we want to add `State' to any of these functions? + eg. XrStateCreate, XrStateClone? */ +XrState *XrCreate(void); +void XrDestroy(XrState *xrs); + +void XrSave(XrState *xrs); +void XrRestore(XrState *xrs); + +XrState *XrClone(XrState *xrs); + +/* Modify state */ +void XrSetPicture(XrState *xrs, XrPicture) +void XrSetColor(XrState *xrs, XrColor); + +/* XXX: XrSetLineWidth, XrSetLineCap, XrSetLineJoin, XrSetDash, ... */ + +/* Path creation */ + +/* XXX: I'm thinking that it might make sense to do away with the + notion of a "current path" in the state object and instead + provide functions to manipulate an opaque XrPath object. This + would add one more argument to XrStroke/XrFill, but it would + unify support for PS "user paths" */ + +void XrNewPath(XrState *xrs); +void XrMoveTo(XrState *xrs, double x, double y); +void XrLineTo(XrState *xrs, double x, double y); +void XrClosePath(XrState *xrs); + +/* XXX: XrRLineTo, XrArc, XrCurveTo, XrRCurveTo, ... */ + +/* Render current path */ +void XrStroke(XrState *xrs); +void XrFill(XrState *xrs);""", desc="Monospace", markup=False, width=800, height=600, align=pango.ALIGN_LEFT) + +def list_slide (l, data=None): + def s (r): + yield l[0] + for i in l[1:]: + yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +list_slide ([ + '<b>Committers</b>', + '2002 2', + '2003 11', + '2004 12', + '2005 26', + '2006 54', + '2007 <span foreground="#888">44</span>', + ], data={'align': pango.ALIGN_LEFT}) + +who (behdad) + +list_slide ([ + "<b>Backends</b>", + "2002-06 Xlib", + "2003-02 image", + "2003-10 PostScript", + '2004-04 <span foreground="#888">XCB</span>', + '2004-09 <span foreground="#888">glitz</span>', + "2005-01 Win32", + "2005-01 PDF", + '2005-01 <span foreground="#888">Quartz</span>', + "2005-12 SVG", + '2005-12 <span foreground="#888">BeOS</span>', + '2005-12 <span foreground="#888">directfb</span>', + '2006-09 <span foreground="#888">OS/2</span>', + '2007-02 <span foreground="#888">Quartz (<i>New!</i>)</span>', + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "<b>Bindings</b>", + "C++", + "Common Lisp", + "D", + "Haskell", + "Java", + ".NET", + "Nickle", + "O'Caml", + "Perl", + "PHP", + "Python", + "Ruby", + "Scheme", + "Squeak", + ]) + +slide_noone ("News") + +slide_behdad ("Mutex rework") + +slide_cworth ("Error-handling") + +slide_behdad ("Great malloc hunt") + +slide_cworth ("PDF hotness") + +slide_behdad ("Xlib work queue") + +slide_noone ("Lessons") + +who (behdad) + +@slide +def git (r): + yield "If you don't <i>git</i> it,\nyou don't get it" + + yield "\n\nIt's the\nRight Thing To Do" + r.move_to (400, 300) + r.put_image ("street.jpg", height=650) + r.set_allocation (50, 0, 800, 550) + yield "" + +@slide +def git2 (r): + yield "Tiny commits" + + yield "\n\n<i>Earn points faster</i>" + r.move_to (400, 300) + r.put_image ("apply-now.png", height=50) + yield "" + +who (cworth) + +slide ("Commit-access\nfor everyone!") + +who (behdad) + +slide ("Tricking others\ninto doing <i>their</i> work") + +who (cworth) + +slide ("Don't go AWOL") + +slide_noone ("Why do we\nlove cairo?") + +slide_noone ('Why do <span foreground="#c00"><i>you</i></span>\nlove cairo?') + +if __name__ == "__main__": + import slippy + import cairo_theme + slippy.main (slides, cairo_theme) |