From 124b479090d81db9d861030ba817a98777786572 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 9 Jan 2014 00:24:48 +0800 Subject: Move slide decks into subdirectories --- Fi_garamond_sort_001.png | Bin 135549 -> 0 bytes IgreenNY.jpg | Bin 82564 -> 0 bytes Makefile | 11 - Metal_movable_type.jpg | Bin 1881547 -> 0 bytes Printer_in_1568-ce.png | Bin 326701 -> 0 bytes README | 3 + README-SLIDES.TXT | 3 - apply-now.png | Bin 5631 -> 0 bytes behdad.svg | 114 - berlin.jpg | Bin 416892 -> 0 bytes cairo.svg | 190 -- cairo/apply-now.png | Bin 0 -> 5631 bytes cairo/behdad.svg | 114 + cairo/cairo.svg | 190 ++ cairo/cairo_slides.py | 553 +++++ cairo/cairo_theme.py | 140 ++ cairo/cworth.svg | 105 + cairo/geotv.jpg | Bin 0 -> 245066 bytes cairo/geotv.mpg | Bin 0 -> 6375140 bytes cairo/guadec.svg | 86 + cairo/pumpkin-small.png | Bin 0 -> 13135 bytes cairo/redhat.svg | 366 ++++ cairo/slippy.py | 1 + cairo/southpark.mp3 | Bin 0 -> 6416384 bytes cairo/street.jpg | Bin 0 -> 393575 bytes cairo_slides.py | 553 ----- cairo_theme.py | 140 -- cairoprinting/behdad.svg | 114 + cairoprinting/cairo.svg | 190 ++ cairoprinting/cairoprinting_slides.py | 417 ++++ cairoprinting/cairoprinting_theme.py | 142 ++ cairoprinting/johnny_automatic_laser_printer.svg | 1502 +++++++++++++ cairoprinting/pumpkin-small.png | Bin 0 -> 13135 bytes cairoprinting/redhat.svg | 366 ++++ cairoprinting/slippy.py | 1 + cairoprinting_slides.py | 417 ---- cairoprinting_theme.py | 142 -- cworth.svg | 105 - freetextstack/behdad.svg | 114 + freetextstack/freetextstack_slides.py | 227 ++ freetextstack/freetextstack_theme.py | 133 ++ freetextstack/slippy.py | 1 + freetextstack_slides.py | 227 -- freetextstack_theme.py | 133 -- geotv.jpg | Bin 245066 -> 0 bytes geotv.mpg | Bin 6375140 -> 0 bytes gnome-ar.png | Bin 269729 -> 0 bytes gnome-is-people.png | Bin 1056447 -> 0 bytes gnome-white.svg | 93 - gnome.svg | 93 - gnu-bold.svg | 241 --- gnu-color.jpg | Bin 21496 -> 0 bytes gnu-color.png | Bin 95209 -> 0 bytes gnu-official.svg | 2492 ---------------------- gnu/gnu-bold.svg | 241 +++ gnu/gnu-color.jpg | Bin 0 -> 21496 bytes gnu/gnu-color.png | Bin 0 -> 95209 bytes gnu/gnu-official.svg | 2492 ++++++++++++++++++++++ gnu/gnu_slides.py | 118 + gnu/gnu_theme.py | 81 + gnu/slippy.py | 1 + gnu_slides.py | 118 - gnu_theme.py | 81 - grancanariadesktopsummit.png | Bin 11629 -> 0 bytes gtkprinting/Printer_in_1568-ce.png | Bin 0 -> 326701 bytes gtkprinting/behdad.svg | 114 + gtkprinting/gtkprinting_slides.py | 25 + gtkprinting/gtkprinting_theme.py | 137 ++ gtkprinting/redhat.svg | 366 ++++ gtkprinting/slippy.py | 1 + gtkprinting_slides.py | 25 - gtkprinting_theme.py | 137 -- guadec.svg | 86 - harfbuzz/IgreenNY.jpg | Bin 0 -> 82564 bytes harfbuzz/behdad.svg | 114 + harfbuzz/harfbuzz_slides.py | 207 ++ harfbuzz/harfbuzz_theme.py | 133 ++ harfbuzz/slippy.py | 1 + harfbuzz_slides.py | 207 -- harfbuzz_theme.py | 133 -- johnny_automatic_laser_printer.svg | 1502 ------------- n810.jpg | Bin 37327 -> 0 bytes olpc.jpg | Bin 136265 -> 0 bytes openmoko.jpg | Bin 28658 -> 0 bytes pumpkin-small.png | Bin 13135 -> 0 bytes redhat.svg | 366 ---- screenshot-gnome-desktop.png | Bin 791544 -> 0 bytes southpark.mp3 | Bin 6416384 -> 0 bytes stateoftext/behdad.svg | 114 + stateoftext/grancanariadesktopsummit.png | Bin 0 -> 11629 bytes stateoftext/slippy.py | 1 + stateoftext/stateoftext_slides.py | 234 ++ stateoftext/stateoftext_theme.py | 130 ++ stateoftext_slides.py | 234 -- stateoftext_theme.py | 130 -- street.jpg | Bin 393575 -> 0 bytes textextraction/Fi_garamond_sort_001.png | Bin 0 -> 135549 bytes textextraction/Metal_movable_type.jpg | Bin 0 -> 1881547 bytes textextraction/behdad.svg | 114 + textextraction/cairo.svg | 190 ++ textextraction/redhat.svg | 366 ++++ textextraction/slippy.py | 1 + textextraction/textextraction_slides.py | 183 ++ textextraction/textextraction_theme.py | 136 ++ textextraction_slides.py | 183 -- textextraction_theme.py | 136 -- turkey-flag.svg | 20 - turkey/behdad.svg | 114 + turkey/berlin.jpg | Bin 0 -> 416892 bytes turkey/gnome-ar.png | Bin 0 -> 269729 bytes turkey/gnome-is-people.png | Bin 0 -> 1056447 bytes turkey/gnome-white.svg | 93 + turkey/n810.jpg | Bin 0 -> 37327 bytes turkey/olpc.jpg | Bin 0 -> 136265 bytes turkey/openmoko.jpg | Bin 0 -> 28658 bytes turkey/screenshot-gnome-desktop.png | Bin 0 -> 791544 bytes turkey/slippy.py | 1 + turkey/turkey-flag.svg | 20 + turkey/turkey_slides.py | 220 ++ turkey/turkey_theme.py | 133 ++ turkey_slides.py | 220 -- turkey_theme.py | 133 -- 122 files changed, 10846 insertions(+), 8665 deletions(-) delete mode 100644 Fi_garamond_sort_001.png delete mode 100644 IgreenNY.jpg delete mode 100644 Makefile delete mode 100644 Metal_movable_type.jpg delete mode 100644 Printer_in_1568-ce.png create mode 100644 README delete mode 100644 README-SLIDES.TXT delete mode 100644 apply-now.png delete mode 100644 behdad.svg delete mode 100644 berlin.jpg delete mode 100644 cairo.svg create mode 100644 cairo/apply-now.png create mode 100644 cairo/behdad.svg create mode 100644 cairo/cairo.svg create mode 100755 cairo/cairo_slides.py create mode 100644 cairo/cairo_theme.py create mode 100644 cairo/cworth.svg create mode 100644 cairo/geotv.jpg create mode 100644 cairo/geotv.mpg create mode 100644 cairo/guadec.svg create mode 100644 cairo/pumpkin-small.png create mode 100644 cairo/redhat.svg create mode 120000 cairo/slippy.py create mode 100644 cairo/southpark.mp3 create mode 100644 cairo/street.jpg delete mode 100755 cairo_slides.py delete mode 100644 cairo_theme.py create mode 100644 cairoprinting/behdad.svg create mode 100644 cairoprinting/cairo.svg create mode 100755 cairoprinting/cairoprinting_slides.py create mode 100644 cairoprinting/cairoprinting_theme.py create mode 100644 cairoprinting/johnny_automatic_laser_printer.svg create mode 100644 cairoprinting/pumpkin-small.png create mode 100644 cairoprinting/redhat.svg create mode 120000 cairoprinting/slippy.py delete mode 100755 cairoprinting_slides.py delete mode 100644 cairoprinting_theme.py delete mode 100644 cworth.svg create mode 100644 freetextstack/behdad.svg create mode 100755 freetextstack/freetextstack_slides.py create mode 100644 freetextstack/freetextstack_theme.py create mode 120000 freetextstack/slippy.py delete mode 100755 freetextstack_slides.py delete mode 100644 freetextstack_theme.py delete mode 100644 geotv.jpg delete mode 100644 geotv.mpg delete mode 100644 gnome-ar.png delete mode 100644 gnome-is-people.png delete mode 100644 gnome-white.svg delete mode 100644 gnome.svg delete mode 100644 gnu-bold.svg delete mode 100644 gnu-color.jpg delete mode 100644 gnu-color.png delete mode 100644 gnu-official.svg create mode 100644 gnu/gnu-bold.svg create mode 100644 gnu/gnu-color.jpg create mode 100644 gnu/gnu-color.png create mode 100644 gnu/gnu-official.svg create mode 100755 gnu/gnu_slides.py create mode 100644 gnu/gnu_theme.py create mode 120000 gnu/slippy.py delete mode 100755 gnu_slides.py delete mode 100644 gnu_theme.py delete mode 100644 grancanariadesktopsummit.png create mode 100644 gtkprinting/Printer_in_1568-ce.png create mode 100644 gtkprinting/behdad.svg create mode 100755 gtkprinting/gtkprinting_slides.py create mode 100644 gtkprinting/gtkprinting_theme.py create mode 100644 gtkprinting/redhat.svg create mode 120000 gtkprinting/slippy.py delete mode 100755 gtkprinting_slides.py delete mode 100644 gtkprinting_theme.py delete mode 100644 guadec.svg create mode 100644 harfbuzz/IgreenNY.jpg create mode 100644 harfbuzz/behdad.svg create mode 100755 harfbuzz/harfbuzz_slides.py create mode 100644 harfbuzz/harfbuzz_theme.py create mode 120000 harfbuzz/slippy.py delete mode 100755 harfbuzz_slides.py delete mode 100644 harfbuzz_theme.py delete mode 100644 johnny_automatic_laser_printer.svg delete mode 100644 n810.jpg delete mode 100644 olpc.jpg delete mode 100644 openmoko.jpg delete mode 100644 pumpkin-small.png delete mode 100644 redhat.svg delete mode 100644 screenshot-gnome-desktop.png delete mode 100644 southpark.mp3 create mode 100644 stateoftext/behdad.svg create mode 100644 stateoftext/grancanariadesktopsummit.png create mode 120000 stateoftext/slippy.py create mode 100755 stateoftext/stateoftext_slides.py create mode 100644 stateoftext/stateoftext_theme.py delete mode 100755 stateoftext_slides.py delete mode 100644 stateoftext_theme.py delete mode 100644 street.jpg create mode 100644 textextraction/Fi_garamond_sort_001.png create mode 100644 textextraction/Metal_movable_type.jpg create mode 100644 textextraction/behdad.svg create mode 100644 textextraction/cairo.svg create mode 100644 textextraction/redhat.svg create mode 120000 textextraction/slippy.py create mode 100755 textextraction/textextraction_slides.py create mode 100644 textextraction/textextraction_theme.py delete mode 100755 textextraction_slides.py delete mode 100644 textextraction_theme.py delete mode 100644 turkey-flag.svg create mode 100644 turkey/behdad.svg create mode 100644 turkey/berlin.jpg create mode 100644 turkey/gnome-ar.png create mode 100644 turkey/gnome-is-people.png create mode 100644 turkey/gnome-white.svg create mode 100644 turkey/n810.jpg create mode 100644 turkey/olpc.jpg create mode 100644 turkey/openmoko.jpg create mode 100644 turkey/screenshot-gnome-desktop.png create mode 120000 turkey/slippy.py create mode 100644 turkey/turkey-flag.svg create mode 100755 turkey/turkey_slides.py create mode 100644 turkey/turkey_theme.py delete mode 100755 turkey_slides.py delete mode 100644 turkey_theme.py diff --git a/Fi_garamond_sort_001.png b/Fi_garamond_sort_001.png deleted file mode 100644 index f7b944d..0000000 Binary files a/Fi_garamond_sort_001.png and /dev/null differ diff --git a/IgreenNY.jpg b/IgreenNY.jpg deleted file mode 100644 index fedef80..0000000 Binary files a/IgreenNY.jpg and /dev/null differ diff --git a/Makefile b/Makefile deleted file mode 100644 index 5b278f3..0000000 --- a/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: stateoftext - @: - -%: - ./$@_slides.py - -%_slides.pdf %_slides.svg %_slides.ps: slippy.py %_slides.py %_theme.py - ./$*_slides.py -o $@ - -clean: - $(RM) *_slides.ps *_slides.pdf *_slides.svg *.pyc diff --git a/Metal_movable_type.jpg b/Metal_movable_type.jpg deleted file mode 100644 index 75b6c97..0000000 Binary files a/Metal_movable_type.jpg and /dev/null differ diff --git a/Printer_in_1568-ce.png b/Printer_in_1568-ce.png deleted file mode 100644 index 80d34b4..0000000 Binary files a/Printer_in_1568-ce.png and /dev/null differ diff --git a/README b/README new file mode 100644 index 0000000..c1e0792 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +This is Slippy, a pycairo-based slide design tool. +For samples, see the subdirectories. +The tool can generate PDF decks as well as present. diff --git a/README-SLIDES.TXT b/README-SLIDES.TXT deleted file mode 100644 index 54dbd37..0000000 --- a/README-SLIDES.TXT +++ /dev/null @@ -1,3 +0,0 @@ -For source code generating this slides please see: - - http://cgit.freedesktop.org/~behdad/slippy/ diff --git a/apply-now.png b/apply-now.png deleted file mode 100644 index e437f75..0000000 Binary files a/apply-now.png and /dev/null differ diff --git a/behdad.svg b/behdad.svg deleted file mode 100644 index 8000f9f..0000000 --- a/behdad.svg +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - diff --git a/berlin.jpg b/berlin.jpg deleted file mode 100644 index 25d1fd2..0000000 Binary files a/berlin.jpg and /dev/null differ diff --git a/cairo.svg b/cairo.svg deleted file mode 100644 index 49a049e..0000000 --- a/cairo.svg +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cairo/apply-now.png b/cairo/apply-now.png new file mode 100644 index 0000000..e437f75 Binary files /dev/null and b/cairo/apply-now.png differ diff --git a/cairo/behdad.svg b/cairo/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/cairo/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/cairo/cairo.svg b/cairo/cairo.svg new file mode 100644 index 0000000..49a049e --- /dev/null +++ b/cairo/cairo.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +# Copyright 2007 Behdad Esfahbod + +# 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\nbesfahbo@redhat.com""", + desc="20", halign=1, valign=-1) + + r.move_to (800, 450) + r.put_text ("""Carl Worth\ncworth@redhat.com""", + 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 ("G", 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 +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 ([ + 'Committers', + '2002 2', + '2003 11', + '2004 12', + '2005 26', + '2006 54', + '2007 44', + ], data={'align': pango.ALIGN_LEFT}) + +who (behdad) + +list_slide ([ + "Backends", + "2002-06 Xlib", + "2003-02 image", + "2003-10 PostScript", + '2004-04 XCB', + '2004-09 glitz', + "2005-01 Win32", + "2005-01 PDF", + '2005-01 Quartz', + "2005-12 SVG", + '2005-12 BeOS', + '2005-12 directfb', + '2006-09 OS/2', + '2007-02 Quartz (New!)', + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Bindings", + "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 git 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\nEarn points faster" + 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 their work") + +who (cworth) + +slide ("Don't go AWOL") + +slide_noone ("Why do we\nlove cairo?") + +slide_noone ('Why do you\nlove cairo?') + +if __name__ == "__main__": + import slippy + import cairo_theme + slippy.main (slides, cairo_theme) diff --git a/cairo/cairo_theme.py b/cairo/cairo_theme.py new file mode 100644 index 0000000..46377a7 --- /dev/null +++ b/cairo/cairo_theme.py @@ -0,0 +1,140 @@ +# Written by Behdad Esfahbod, 2007 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .07 +logo_margin = .09 +footer_margin = .05 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = logo_margin * height + f = footer_margin * height + p = padding * min (width, height) + p2 = 2 * p + + # Blue sky + sky = cairo.LinearGradient (0, 0, 0, height) + sky.add_color_stop_rgba (0, .60, .65, 1, 1.0) + sky.add_color_stop_rgba (1, .92, .93, 1, 1.0) + cr.set_source (sky) + cr.paint () + + # Brown earth + cr.set_source_rgb (158/255., 87/255., 0/255.) + cr.rectangle (0, height, width, -p2) + cr.fill () + + # GUADEC logo on the bottom + cr.move_to (.5 * width, height-p2) + cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) + fw, fh = renderer.put_text ("GUADEC 2007, Birmingham, UK", height=f-p2, valign=-1) + cr.move_to (.5 * (width - fw), height-p2) + renderer.put_image ("guadec.svg", height=f-p2, valign=-1, halign=-1) + + # Red Hat/cairo logos at the top + cr.move_to (p, p) + renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) + + cr.move_to (width-p, p) + renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + cr.move_to (width-p, height-p) + renderer.put_image ("cworth.svg", width = s-p2, valign=-1, halign=-1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0, 0, 0) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore() + cr.clip () + cr.set_source_rgb (1, 1, 1) + cr.paint () + + cr.set_source_rgb (0, 0, 0) diff --git a/cairo/cworth.svg b/cairo/cworth.svg new file mode 100644 index 0000000..02d75f9 --- /dev/null +++ b/cairo/cworth.svg @@ -0,0 +1,105 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/cairo/geotv.jpg b/cairo/geotv.jpg new file mode 100644 index 0000000..d4d0cc3 Binary files /dev/null and b/cairo/geotv.jpg differ diff --git a/cairo/geotv.mpg b/cairo/geotv.mpg new file mode 100644 index 0000000..471c95f Binary files /dev/null and b/cairo/geotv.mpg differ diff --git a/cairo/guadec.svg b/cairo/guadec.svg new file mode 100644 index 0000000..2306140 --- /dev/null +++ b/cairo/guadec.svg @@ -0,0 +1,86 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/cairo/pumpkin-small.png b/cairo/pumpkin-small.png new file mode 100644 index 0000000..8e0e570 Binary files /dev/null and b/cairo/pumpkin-small.png differ diff --git a/cairo/redhat.svg b/cairo/redhat.svg new file mode 100644 index 0000000..89315b6 --- /dev/null +++ b/cairo/redhat.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cairo/slippy.py b/cairo/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/cairo/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/cairo/southpark.mp3 b/cairo/southpark.mp3 new file mode 100644 index 0000000..39ed8fa Binary files /dev/null and b/cairo/southpark.mp3 differ diff --git a/cairo/street.jpg b/cairo/street.jpg new file mode 100644 index 0000000..6467f16 Binary files /dev/null and b/cairo/street.jpg differ diff --git a/cairo_slides.py b/cairo_slides.py deleted file mode 100755 index 4689506..0000000 --- a/cairo_slides.py +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -# Copyright 2007 Carl Worth -# Copyright 2007 Behdad Esfahbod - -# 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\nbesfahbo@redhat.com""", - desc="20", halign=1, valign=-1) - - r.move_to (800, 450) - r.put_text ("""Carl Worth\ncworth@redhat.com""", - 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 ("G", 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 -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 ([ - 'Committers', - '2002 2', - '2003 11', - '2004 12', - '2005 26', - '2006 54', - '2007 44', - ], data={'align': pango.ALIGN_LEFT}) - -who (behdad) - -list_slide ([ - "Backends", - "2002-06 Xlib", - "2003-02 image", - "2003-10 PostScript", - '2004-04 XCB', - '2004-09 glitz', - "2005-01 Win32", - "2005-01 PDF", - '2005-01 Quartz', - "2005-12 SVG", - '2005-12 BeOS', - '2005-12 directfb', - '2006-09 OS/2', - '2007-02 Quartz (New!)', - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Bindings", - "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 git 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\nEarn points faster" - 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 their work") - -who (cworth) - -slide ("Don't go AWOL") - -slide_noone ("Why do we\nlove cairo?") - -slide_noone ('Why do you\nlove cairo?') - -if __name__ == "__main__": - import slippy - import cairo_theme - slippy.main (slides, cairo_theme) diff --git a/cairo_theme.py b/cairo_theme.py deleted file mode 100644 index 46377a7..0000000 --- a/cairo_theme.py +++ /dev/null @@ -1,140 +0,0 @@ -# Written by Behdad Esfahbod, 2007 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .07 -logo_margin = .09 -footer_margin = .05 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = logo_margin * height - f = footer_margin * height - p = padding * min (width, height) - p2 = 2 * p - - # Blue sky - sky = cairo.LinearGradient (0, 0, 0, height) - sky.add_color_stop_rgba (0, .60, .65, 1, 1.0) - sky.add_color_stop_rgba (1, .92, .93, 1, 1.0) - cr.set_source (sky) - cr.paint () - - # Brown earth - cr.set_source_rgb (158/255., 87/255., 0/255.) - cr.rectangle (0, height, width, -p2) - cr.fill () - - # GUADEC logo on the bottom - cr.move_to (.5 * width, height-p2) - cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) - fw, fh = renderer.put_text ("GUADEC 2007, Birmingham, UK", height=f-p2, valign=-1) - cr.move_to (.5 * (width - fw), height-p2) - renderer.put_image ("guadec.svg", height=f-p2, valign=-1, halign=-1) - - # Red Hat/cairo logos at the top - cr.move_to (p, p) - renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) - - cr.move_to (width-p, p) - renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - cr.move_to (width-p, height-p) - renderer.put_image ("cworth.svg", width = s-p2, valign=-1, halign=-1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0, 0, 0) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore() - cr.clip () - cr.set_source_rgb (1, 1, 1) - cr.paint () - - cr.set_source_rgb (0, 0, 0) diff --git a/cairoprinting/behdad.svg b/cairoprinting/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/cairoprinting/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/cairoprinting/cairo.svg b/cairoprinting/cairo.svg new file mode 100644 index 0000000..49a049e --- /dev/null +++ b/cairoprinting/cairo.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cairoprinting/cairoprinting_slides.py b/cairoprinting/cairoprinting_slides.py new file mode 100755 index 0000000..e005ea9 --- /dev/null +++ b/cairoprinting/cairoprinting_slides.py @@ -0,0 +1,417 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +# Copyright 2007 Carl Worth +# Copyright 2007 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_behdad(f, data=None): + return slide_who (f, behdad, data=data) + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (400, 150) + r.put_text ( +"""cairo graphics +http://cairographics.org""", width=800, valign=1) + + r.move_to (0, 450) + r.put_text ("""Behdad Esfahbod\nbesfahbo@redhat.com""", + desc="20", halign=1, valign=-1) + +who (behdad) + +slide_noone("Intro") + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +list_slide ([ + "• PostScript-like 2D model", + "• Porter-Duff compositing model", + '• Easy to use', + "• Multiple backends", + "• Backend-independent drawing", + "• Portable", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Backends", + "2002-06 Xlib", + "2003-02 image", + "2003-10 PostScript", + '2004-04 XCB', + '2004-09 glitz', + "2005-01 Win32", + "2005-01 PDF", + '2005-01 Quartz', + "2005-12 SVG", + '2005-12 BeOS', + '2005-12 directfb', + '2006-09 OS/2', + '2007-02 Quartz (New!)', + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Font backends", + "FreeType+FontConfig", + "Win32", + "ATSUI", + ]) + +list_slide ([ + "Bindings", + "C++", + "Common Lisp", + "D", + "Haskell", + "Java", + ".NET", + "Nickle", + "O'Caml", + "Perl", + "PHP", + "Python", + "Ruby", + "Scheme", + "Squeak", + ]) + +list_slide ([ + "Users", + "GTK+", + "Firefox 3", + "Mono", + 'Inkscape', + 'OpenOffice.org', + '...', + ]) + +list_slide ([ + "cairo_surface_t", + "cairo_t", + "cairo_pattern_t", + "cairo_font_face_t", + "cairo_scaled_font_t", + ], data={'align': pango.ALIGN_LEFT}) + +slide("""cairo_surface_t *surface; +cairo_t *cr; + +surface = cairo_pdf_surface_create ("out.pdf", 100, 100); + +cr = cairo_create (surface); +cairo_move_to (cr, 10, 10); +cairo_line_to (cr, 90, 90); +cairo_stroke (cr); +cairo_destroy (cr); + +cairo_surface_destroy (surface);""", data={'align': pango.ALIGN_LEFT}) + +def paint_checkers (cr): + image = cairo.ImageSurface (cairo.FORMAT_ARGB32, 30, 30) + cr2 = cairo.Context (image) + cr2.rectangle ( 0, 0, 15, 15) + cr2.rectangle (15, 15, 15, 15) + cr2.set_source_rgba (.75, .75, .75, .75) + cr2.fill () + cr2.rectangle (15, 0, 15, 15) + cr2.rectangle ( 0, 15, 15, 15) + cr2.set_source_rgba (1, 1, 1, 0) + cr2.set_operator (cairo.OPERATOR_SOURCE) + 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.7) + 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 ("G", 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 "" + +slide_noone("Vector Backends") + +list_slide (["PS", "PDF", "SVG"]) +list_slide (['Roundtrip', + 'cairo→PS→', + "cairo→PDF→poppler→cairo", + "cairo→SVG→librsvg→cairo", + ], data={'align': pango.ALIGN_LEFT}) +list_slide (['Conversion', + 'PS→', + "PDF→poppler→cairo→SVG", + "SVG→librsvg→cairo→PDF", + ], data={'align': pango.ALIGN_LEFT}) +list_slide (["Anatomy", + "cairo_paginated_surface", + "cairo_meta_surface", + "cairo_analysis_surface", + ], data={'align': pango.ALIGN_LEFT}) +list_slide (["PS", "PDF", "SVG"]) +list_slide (["Font subsetters", + "TrueType", + "OpenType CFF", + "Type1", + "Type1 fallback", + 'Type3', + ]) +list_slide (["New in 1.6", + 'Native gradients', + 'Fine-grained fallback images', + ]) +list_slide (["Planned for 1.8", + 'Improved text extraction', + 'User-fonts', + 'Metadata API', + 'Reduced file size', + 'JPEG support', + ]) +list_slide (["Not Planned Yet", + 'Colorspace API', + 'Higher-level integration', + ]) + +slide ("Q?") + +if __name__ == "__main__": + import slippy + import cairoprinting_theme + slippy.main (slides, cairoprinting_theme) diff --git a/cairoprinting/cairoprinting_theme.py b/cairoprinting/cairoprinting_theme.py new file mode 100644 index 0000000..c0ace83 --- /dev/null +++ b/cairoprinting/cairoprinting_theme.py @@ -0,0 +1,142 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .07 +logo_margin = .09 +footer_margin = .05 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = logo_margin * height + f = footer_margin * height + p = padding * min (width, height) + p2 = 2 * p + + # Blue sky + cr.set_source_rgb (.60, .65, 1) + cr.paint () + + # Brown earth + cr.set_source_rgb (158/255., 87/255., 0/255.) + cr.rectangle (0, height, width, -p2) + cr.fill () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) + renderer.put_text ("OpenPrinting Summit, Montréal, September 24, 2007", height=f-p2, valign=-1) + + # Background image + cr.move_to (width / 2., height / 2.) + renderer.put_image ("johnny_automatic_laser_printer.svg", height = height*.9, width = width*.9) + + # Red Hat/cairo logos at the top + cr.move_to (p, p) + renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) + + cr.move_to (width-p, p) + renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0, 0, 0) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + cr.set_source_rgba (1, 1, 1, .8) + cr.paint () + + cr.set_source_rgb (0, 0, 0) diff --git a/cairoprinting/johnny_automatic_laser_printer.svg b/cairoprinting/johnny_automatic_laser_printer.svg new file mode 100644 index 0000000..261f78f --- /dev/null +++ b/cairoprinting/johnny_automatic_laser_printer.svg @@ -0,0 +1,1502 @@ + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cairoprinting/pumpkin-small.png b/cairoprinting/pumpkin-small.png new file mode 100644 index 0000000..8e0e570 Binary files /dev/null and b/cairoprinting/pumpkin-small.png differ diff --git a/cairoprinting/redhat.svg b/cairoprinting/redhat.svg new file mode 100644 index 0000000..89315b6 --- /dev/null +++ b/cairoprinting/redhat.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cairoprinting/slippy.py b/cairoprinting/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/cairoprinting/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/cairoprinting_slides.py b/cairoprinting_slides.py deleted file mode 100755 index e005ea9..0000000 --- a/cairoprinting_slides.py +++ /dev/null @@ -1,417 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -# Copyright 2007 Carl Worth -# Copyright 2007 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_behdad(f, data=None): - return slide_who (f, behdad, data=data) - -# -# Slides start here -# - -@slide_noone -def title_slide (r): - r.move_to (400, 150) - r.put_text ( -"""cairo graphics -http://cairographics.org""", width=800, valign=1) - - r.move_to (0, 450) - r.put_text ("""Behdad Esfahbod\nbesfahbo@redhat.com""", - desc="20", halign=1, valign=-1) - -who (behdad) - -slide_noone("Intro") - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) - -list_slide ([ - "• PostScript-like 2D model", - "• Porter-Duff compositing model", - '• Easy to use', - "• Multiple backends", - "• Backend-independent drawing", - "• Portable", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Backends", - "2002-06 Xlib", - "2003-02 image", - "2003-10 PostScript", - '2004-04 XCB', - '2004-09 glitz', - "2005-01 Win32", - "2005-01 PDF", - '2005-01 Quartz', - "2005-12 SVG", - '2005-12 BeOS', - '2005-12 directfb', - '2006-09 OS/2', - '2007-02 Quartz (New!)', - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Font backends", - "FreeType+FontConfig", - "Win32", - "ATSUI", - ]) - -list_slide ([ - "Bindings", - "C++", - "Common Lisp", - "D", - "Haskell", - "Java", - ".NET", - "Nickle", - "O'Caml", - "Perl", - "PHP", - "Python", - "Ruby", - "Scheme", - "Squeak", - ]) - -list_slide ([ - "Users", - "GTK+", - "Firefox 3", - "Mono", - 'Inkscape', - 'OpenOffice.org', - '...', - ]) - -list_slide ([ - "cairo_surface_t", - "cairo_t", - "cairo_pattern_t", - "cairo_font_face_t", - "cairo_scaled_font_t", - ], data={'align': pango.ALIGN_LEFT}) - -slide("""cairo_surface_t *surface; -cairo_t *cr; - -surface = cairo_pdf_surface_create ("out.pdf", 100, 100); - -cr = cairo_create (surface); -cairo_move_to (cr, 10, 10); -cairo_line_to (cr, 90, 90); -cairo_stroke (cr); -cairo_destroy (cr); - -cairo_surface_destroy (surface);""", data={'align': pango.ALIGN_LEFT}) - -def paint_checkers (cr): - image = cairo.ImageSurface (cairo.FORMAT_ARGB32, 30, 30) - cr2 = cairo.Context (image) - cr2.rectangle ( 0, 0, 15, 15) - cr2.rectangle (15, 15, 15, 15) - cr2.set_source_rgba (.75, .75, .75, .75) - cr2.fill () - cr2.rectangle (15, 0, 15, 15) - cr2.rectangle ( 0, 15, 15, 15) - cr2.set_source_rgba (1, 1, 1, 0) - cr2.set_operator (cairo.OPERATOR_SOURCE) - 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.7) - 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 ("G", 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 "" - -slide_noone("Vector Backends") - -list_slide (["PS", "PDF", "SVG"]) -list_slide (['Roundtrip', - 'cairo→PS→', - "cairo→PDF→poppler→cairo", - "cairo→SVG→librsvg→cairo", - ], data={'align': pango.ALIGN_LEFT}) -list_slide (['Conversion', - 'PS→', - "PDF→poppler→cairo→SVG", - "SVG→librsvg→cairo→PDF", - ], data={'align': pango.ALIGN_LEFT}) -list_slide (["Anatomy", - "cairo_paginated_surface", - "cairo_meta_surface", - "cairo_analysis_surface", - ], data={'align': pango.ALIGN_LEFT}) -list_slide (["PS", "PDF", "SVG"]) -list_slide (["Font subsetters", - "TrueType", - "OpenType CFF", - "Type1", - "Type1 fallback", - 'Type3', - ]) -list_slide (["New in 1.6", - 'Native gradients', - 'Fine-grained fallback images', - ]) -list_slide (["Planned for 1.8", - 'Improved text extraction', - 'User-fonts', - 'Metadata API', - 'Reduced file size', - 'JPEG support', - ]) -list_slide (["Not Planned Yet", - 'Colorspace API', - 'Higher-level integration', - ]) - -slide ("Q?") - -if __name__ == "__main__": - import slippy - import cairoprinting_theme - slippy.main (slides, cairoprinting_theme) diff --git a/cairoprinting_theme.py b/cairoprinting_theme.py deleted file mode 100644 index c0ace83..0000000 --- a/cairoprinting_theme.py +++ /dev/null @@ -1,142 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .07 -logo_margin = .09 -footer_margin = .05 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = logo_margin * height - f = footer_margin * height - p = padding * min (width, height) - p2 = 2 * p - - # Blue sky - cr.set_source_rgb (.60, .65, 1) - cr.paint () - - # Brown earth - cr.set_source_rgb (158/255., 87/255., 0/255.) - cr.rectangle (0, height, width, -p2) - cr.fill () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) - renderer.put_text ("OpenPrinting Summit, Montréal, September 24, 2007", height=f-p2, valign=-1) - - # Background image - cr.move_to (width / 2., height / 2.) - renderer.put_image ("johnny_automatic_laser_printer.svg", height = height*.9, width = width*.9) - - # Red Hat/cairo logos at the top - cr.move_to (p, p) - renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) - - cr.move_to (width-p, p) - renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0, 0, 0) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - cr.set_source_rgba (1, 1, 1, .8) - cr.paint () - - cr.set_source_rgb (0, 0, 0) diff --git a/cworth.svg b/cworth.svg deleted file mode 100644 index 02d75f9..0000000 --- a/cworth.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - diff --git a/freetextstack/behdad.svg b/freetextstack/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/freetextstack/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/freetextstack/freetextstack_slides.py b/freetextstack/freetextstack_slides.py new file mode 100755 index 0000000..14c772c --- /dev/null +++ b/freetextstack/freetextstack_slides.py @@ -0,0 +1,227 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +if __name__ == "__main__": + import slippy + import sys + import freetextstack_theme as theme + slippy.main (__file__, theme, sys.argv[1:]) + sys.exit (0) + +# Copyright 2007,2009 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_behdad(f, data=None): + return slide_who (f, behdad, data=data) +def slide_image (f, height=650, data=None): + @slide_noone + def image_func (r): + r.move_to (400, 300) + r.put_image (f, height=height) + #r.set_allocation (000, 0, 800, 600) + yield "" + +""" +Free Software stack for Unicode Text Rendering + +The Free Software world has a lot to offer when it comes to building a stack +up from the grounds. Be it building an ARM-based Linux mobile platform or +cross-platform text rendering to rendering downloadable CFF fonts on Windows, +the Free Software stack provides all the bits and pieces one needs to assemble +a high quality OpenType-based Unicode text rendering pipeline with great +flexibility. In this tutorial we will go over the building blocks involved +and how to put them together. + +The session can be divided in three parts logically. The first section +introduces different libraries involved: FreeType, fontconfig, HarfBuzz, +FriBidi, cairo, glib, Pango, GTK+, Qt, and possibly others. In the second +part, we'll focus on hands on development of text rendering code based on the +highlevel Pango+Cairo interface. In the final part, we dig down in the stack +and put together a barebone quick and dirty text rendering system using +FreeType, glib, FriBidi, HarfBuzz, and cairo only, to see first hand how the +different pieces fit together. + +We will also cover licensing and support options and community models of the +libraries involved. What will NOT be covered in this session is how to +cross-compile or otherwise build components. +""" + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (800, 30) + r.put_text ( +"""Free Software\nstack for\nUnicode\nText\nRendering""", +width=800, height=500, valign=1, halign=-1) + + r.move_to (0, 570) + r.put_text ("""Behdad Esfahbod\nbehdad@redhat.com\nhttp://behdad.org/""", height=130, width=300, halign=1, valign=-1) + + +who (behdad) + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) +def step_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 ([ + "Agenda", + "• Introduction", + "• Overview", + "• Community & Culture", + "• Bits and Pieces", + "• Hello World", + "• Digging Deeper", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide([ "Intro", + "• FarsiWeb", + "• Unicode", + "• GNOME", + "• Red Hat", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("Overview") +slide("Flexibility") +list_slide([ "Licensing", + "• BSD-Style", + "• LGPL", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide([ "Community", + "• Mailing list", + "• The team", + "• Bugzilla", + "• IRC", + "• Releases", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("Bits &\nPieces") +slide("FreeType") +slide("Fontconfig") +slide("Glib") +slide("FriBidi") +slide("HarfBuzz") +slide("Cairo") +slide("Pango") +slide("GTK+") +#slide("Qt") + +slide_noone("Hello\nWorld") +slide("Demo\nTime!") + +slide_noone("Digging\nDeeper") +list_slide ([ "Consumers", + "• GUI Toolkits", + "• Web Browsers", + "• Word Processors", + "• Designer Tools", + "• Font Design Tools", + "• Terminal Emulators", + "• Batch Doc Processors", + "• TeX Engines", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ "Demystifying Fontconfig", + "• Patterns", + "• Cache", + "• Config", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ "Pillars of Pango", + "• pango_itemize()", + "• pango_shape()", + "• pango_break()", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ "Further Down", + "• Glib", + "• FreeType", + "• Fontconfig", + "• FriBidi", + "• Cairo", + "• HarfBuzz", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ "More Demos", + "• Vertical text", + "• Online font add/remove", + "• Automatic font installation", + ], data={'align': pango.ALIGN_LEFT}) + + +""" +list_slide ([ "", + "• ", + "• ", + "• ", + "• ", + "• ", + "• ", + ], data={'align': pango.ALIGN_LEFT}) +""" + +slide_noone("Q?") diff --git a/freetextstack/freetextstack_theme.py b/freetextstack/freetextstack_theme.py new file mode 100644 index 0000000..713820a --- /dev/null +++ b/freetextstack/freetextstack_theme.py @@ -0,0 +1,133 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007,2009 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .06 +top_margin = .02 +bottom_margin = .06 +padding = .006 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = top_margin * height + f = bottom_margin * height + p = padding * min (width, height) + p2 = 2 * p + + a = 1 + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) + cr.paint () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgb (0xff/255.*a, 0xda/255.*a, 0x4c/255.*a) + renderer.put_text ("Internationalization & Unicode Conference 33, October 14—16, 2009, San Jose", height=(f-p2)*.8, width=(width-2*s)*.8, valign=-1) + + cr.move_to (width-p, height-p) + #renderer.put_image ("unicode.png", height = f-p2, valign=-1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + a = .7 + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + a = 10 + cr.set_source_rgb (0xfe/255.*a, 0x9a/255.*a, 0x35/255.*a) + cr.paint () + + a = .1 + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) diff --git a/freetextstack/slippy.py b/freetextstack/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/freetextstack/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/freetextstack_slides.py b/freetextstack_slides.py deleted file mode 100755 index 14c772c..0000000 --- a/freetextstack_slides.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -if __name__ == "__main__": - import slippy - import sys - import freetextstack_theme as theme - slippy.main (__file__, theme, sys.argv[1:]) - sys.exit (0) - -# Copyright 2007,2009 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_behdad(f, data=None): - return slide_who (f, behdad, data=data) -def slide_image (f, height=650, data=None): - @slide_noone - def image_func (r): - r.move_to (400, 300) - r.put_image (f, height=height) - #r.set_allocation (000, 0, 800, 600) - yield "" - -""" -Free Software stack for Unicode Text Rendering - -The Free Software world has a lot to offer when it comes to building a stack -up from the grounds. Be it building an ARM-based Linux mobile platform or -cross-platform text rendering to rendering downloadable CFF fonts on Windows, -the Free Software stack provides all the bits and pieces one needs to assemble -a high quality OpenType-based Unicode text rendering pipeline with great -flexibility. In this tutorial we will go over the building blocks involved -and how to put them together. - -The session can be divided in three parts logically. The first section -introduces different libraries involved: FreeType, fontconfig, HarfBuzz, -FriBidi, cairo, glib, Pango, GTK+, Qt, and possibly others. In the second -part, we'll focus on hands on development of text rendering code based on the -highlevel Pango+Cairo interface. In the final part, we dig down in the stack -and put together a barebone quick and dirty text rendering system using -FreeType, glib, FriBidi, HarfBuzz, and cairo only, to see first hand how the -different pieces fit together. - -We will also cover licensing and support options and community models of the -libraries involved. What will NOT be covered in this session is how to -cross-compile or otherwise build components. -""" - -# -# Slides start here -# - -@slide_noone -def title_slide (r): - r.move_to (800, 30) - r.put_text ( -"""Free Software\nstack for\nUnicode\nText\nRendering""", -width=800, height=500, valign=1, halign=-1) - - r.move_to (0, 570) - r.put_text ("""Behdad Esfahbod\nbehdad@redhat.com\nhttp://behdad.org/""", height=130, width=300, halign=1, valign=-1) - - -who (behdad) - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) -def step_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 ([ - "Agenda", - "• Introduction", - "• Overview", - "• Community & Culture", - "• Bits and Pieces", - "• Hello World", - "• Digging Deeper", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide([ "Intro", - "• FarsiWeb", - "• Unicode", - "• GNOME", - "• Red Hat", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("Overview") -slide("Flexibility") -list_slide([ "Licensing", - "• BSD-Style", - "• LGPL", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide([ "Community", - "• Mailing list", - "• The team", - "• Bugzilla", - "• IRC", - "• Releases", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("Bits &\nPieces") -slide("FreeType") -slide("Fontconfig") -slide("Glib") -slide("FriBidi") -slide("HarfBuzz") -slide("Cairo") -slide("Pango") -slide("GTK+") -#slide("Qt") - -slide_noone("Hello\nWorld") -slide("Demo\nTime!") - -slide_noone("Digging\nDeeper") -list_slide ([ "Consumers", - "• GUI Toolkits", - "• Web Browsers", - "• Word Processors", - "• Designer Tools", - "• Font Design Tools", - "• Terminal Emulators", - "• Batch Doc Processors", - "• TeX Engines", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ "Demystifying Fontconfig", - "• Patterns", - "• Cache", - "• Config", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ "Pillars of Pango", - "• pango_itemize()", - "• pango_shape()", - "• pango_break()", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ "Further Down", - "• Glib", - "• FreeType", - "• Fontconfig", - "• FriBidi", - "• Cairo", - "• HarfBuzz", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ "More Demos", - "• Vertical text", - "• Online font add/remove", - "• Automatic font installation", - ], data={'align': pango.ALIGN_LEFT}) - - -""" -list_slide ([ "", - "• ", - "• ", - "• ", - "• ", - "• ", - "• ", - ], data={'align': pango.ALIGN_LEFT}) -""" - -slide_noone("Q?") diff --git a/freetextstack_theme.py b/freetextstack_theme.py deleted file mode 100644 index 713820a..0000000 --- a/freetextstack_theme.py +++ /dev/null @@ -1,133 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007,2009 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .06 -top_margin = .02 -bottom_margin = .06 -padding = .006 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = top_margin * height - f = bottom_margin * height - p = padding * min (width, height) - p2 = 2 * p - - a = 1 - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) - cr.paint () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgb (0xff/255.*a, 0xda/255.*a, 0x4c/255.*a) - renderer.put_text ("Internationalization & Unicode Conference 33, October 14—16, 2009, San Jose", height=(f-p2)*.8, width=(width-2*s)*.8, valign=-1) - - cr.move_to (width-p, height-p) - #renderer.put_image ("unicode.png", height = f-p2, valign=-1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - a = .7 - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - a = 10 - cr.set_source_rgb (0xfe/255.*a, 0x9a/255.*a, 0x35/255.*a) - cr.paint () - - a = .1 - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) diff --git a/geotv.jpg b/geotv.jpg deleted file mode 100644 index d4d0cc3..0000000 Binary files a/geotv.jpg and /dev/null differ diff --git a/geotv.mpg b/geotv.mpg deleted file mode 100644 index 471c95f..0000000 Binary files a/geotv.mpg and /dev/null differ diff --git a/gnome-ar.png b/gnome-ar.png deleted file mode 100644 index 588afac..0000000 Binary files a/gnome-ar.png and /dev/null differ diff --git a/gnome-is-people.png b/gnome-is-people.png deleted file mode 100644 index 342b4f5..0000000 Binary files a/gnome-is-people.png and /dev/null differ diff --git a/gnome-white.svg b/gnome-white.svg deleted file mode 100644 index 0895f53..0000000 --- a/gnome-white.svg +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - TM - diff --git a/gnome.svg b/gnome.svg deleted file mode 100644 index 266c299..0000000 --- a/gnome.svg +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - TM - diff --git a/gnu-bold.svg b/gnu-bold.svg deleted file mode 100644 index e3e4a54..0000000 --- a/gnu-bold.svg +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - - - - - - GNU Head - - - - - - - - - - - - - - Aurelio A. Hecker <aurium@gmail.com> - - - - - Aurelio A. Hecker <aurium@gmail.com> - - - - image/svg+xml - - - en - - - - - diff --git a/gnu-color.jpg b/gnu-color.jpg deleted file mode 100644 index 6409db6..0000000 Binary files a/gnu-color.jpg and /dev/null differ diff --git a/gnu-color.png b/gnu-color.png deleted file mode 100644 index 17619f9..0000000 Binary files a/gnu-color.png and /dev/null differ diff --git a/gnu-official.svg b/gnu-official.svg deleted file mode 100644 index 9a068ae..0000000 --- a/gnu-official.svg +++ /dev/null @@ -1,2492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gnu/gnu-bold.svg b/gnu/gnu-bold.svg new file mode 100644 index 0000000..e3e4a54 --- /dev/null +++ b/gnu/gnu-bold.svg @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + GNU Head + + + + + + + + + + + + + + Aurelio A. Hecker <aurium@gmail.com> + + + + + Aurelio A. Hecker <aurium@gmail.com> + + + + image/svg+xml + + + en + + + + + diff --git a/gnu/gnu-color.jpg b/gnu/gnu-color.jpg new file mode 100644 index 0000000..6409db6 Binary files /dev/null and b/gnu/gnu-color.jpg differ diff --git a/gnu/gnu-color.png b/gnu/gnu-color.png new file mode 100644 index 0000000..17619f9 Binary files /dev/null and b/gnu/gnu-color.png differ diff --git a/gnu/gnu-official.svg b/gnu/gnu-official.svg new file mode 100644 index 0000000..9a068ae --- /dev/null +++ b/gnu/gnu-official.svg @@ -0,0 +1,2492 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gnu/gnu_slides.py b/gnu/gnu_slides.py new file mode 100755 index 0000000..1a30f50 --- /dev/null +++ b/gnu/gnu_slides.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +slides = [] +def slide_add(f, data=None, width=800, height=400): + slides.append ((f, data, width, height)) + return f +import pango +def text_slide (l): + def s (r): + for i in l: + yield i + for i in range (30): + yield '' + slide_add (s, data={'align': pango.ALIGN_LEFT}) + +texts = {} +texts['en'] = """“Free software” is a matter of liberty, not price. To understand the +concept, you should think of “free” as in “free speech”, not as in “free beer.” + +Free software is a matter of the users' freedom to run, copy, +distribute, study, change and improve the software. + +More precisely, it refers to four kinds of freedom, for the users of the +software: +------------------------------------------------------------------------------ +0. The freedom to run the program, for any purpose. +1. The freedom to study how the program works, and adapt it to your needs. + Access to the source code is a precondition for this. +2. The freedom to redistribute copies so you can help your neighbor. +3. The freedom to improve the program, and release your improvements to + the public, so that the whole community benefits. + Access to the source code is a precondition for this. +------------------------------------------------------------------------------ +The concept of these 4 freedoms (0-3) were developed by Richard Stallman. + +To set a good example he started to write a completely free operating system. + +Today Linux based GNU systems are used by millions of people around the world.""" + +texts['de'] = """Bei dem Begriff „Freie Software“ geht es um Freiheit, nicht um den Preis. +Um dieses Konzept richtig begreifen zu können, sollte man an „frei“ wie in +„freie Rede“ denken, und nicht an „Freibier“. + +Bei „Freier Software“ geht es um die Freiheit des Benutzers die Software nach +Belieben zu benutzen, zu kopieren, weiter zu geben, die Software zu studieren, +sowie Änderungen und Verbesserungen an der Software vornehmen zu können. +------------------------------------------------------------------------------ +Genauer gesagt, bezieht sich der Begriff „Freie Software“ auf vier Arten von +Freiheit, die der Benutzer der Software hat: + +0. Die Freiheit, das Programm für jeden Zweck zu benutzen. +1. Die Freiheit, zu verstehen, wie das Programm funktioniert und wie man es + für seine Ansprüche anpassen kann. + Der Zugang zum Quellcode ist dafür Voraussetzung. +------------------------------------------------------------------------------ +2. Die Freiheit, Kopien weiterzuverbreiten, so dass man seinem Nächsten + weiterhelfen kann. +3. Die Freiheit, das Programm zu verbessern und die Verbesserungen der + Allgemeinheit zur Verfügung zu stellen, damit die ganze Gemeinschaft davon + profitieren kann. + Der Zugang zum Quellcode ist dafür Voraussetzung. +------------------------------------------------------------------------------ +Diese 4 Freiheiten (0-3) wurden so von Richard Stallman entworfen. + +Um mit gutem Beispiel voran zu gehen, hat er angefangen, ein vollständig +freies Betriebssystem zu entwickeln. + +Heute werden Linux basierte GNU Systeme von vielen Millionen Anwendern benutzt.""" + +texts['he'] = """"תוכנה חופשית" זה ענײן של חירות, לא של מחיר. כדי להבין את העקרון, +צריך לחשוב על "חופש" כמו ב"חופש הביטוי"...\ +.effectpause +.back 3 + ולא כמו ב"בירה חופשי". + +תוכנה חופשית נוגעת לחופש של משתמשים להריץ, להפיץ הפצת-המשך, ללמוד, +לשנות ולשפר את התוכנה. ליתר דיוק, זה מתײחס לארבעה סוגים של חירות למשתמשי +התוכנה: +------------------------------------------------------------------------------ +0. החופש להריץ את התוכנה, לכל מטרה שהיא. +1. החופש ללמוד איך תוכנה עובדת, ולשנות אותה לצרכיהם. + גישה לקוד המקור היא תנאי מקדים לכך. +2. החופש להפיץ עותקים בהפצה-חוזרת כדי שיוכלו למשל לעזור לשכנים שלהם. +3. החופש לשפר את התוכנה, ולשחרר את השיפורים שלהם לציבור, כך שכל הקהילה תרויח. + גישה לקוד-המקור היא תנאי מקדים לכך. +------------------------------------------------------------------------------ +The concept of these 4 freedoms (0-3) were developed by Richard Stallman. + +To set a good example he started to write a completely free operating system. + +Today Linux based GNU systems are used by millions of people around the world.""" + +import os, re +lang = os.getenv ('LANG') +i = lang.find ('_') +if i > 0: + lang = lang[:i] +text = texts.get (lang, texts['en']) +def break_on_dashlines (text): + s = '' + for line in text.split ('\n'): + if re.match ('^----*$', line): + yield s + s = '' + else: + if s: + s += '\n' + s += line + yield s + +for slide in break_on_dashlines (text): + text_slide (slide) + +if __name__ == "__main__": + import slippy + import gnu_theme + slippy.main (slides, gnu_theme, args = ['--slideshow', '--delay', '0.05', '--repeat']) diff --git a/gnu/gnu_theme.py b/gnu/gnu_theme.py new file mode 100644 index 0000000..0550007 --- /dev/null +++ b/gnu/gnu_theme.py @@ -0,0 +1,81 @@ +import cairo + +logo_height = .3 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + cr.save () + cr.set_operator (cairo.OPERATOR_CLEAR) + cr.paint () + cr.restore () + + cr.move_to (0, height) + global logo_w, logo_h + logo_w, logo_h = renderer.put_image ("gnu-color.png", height=logo_height*height, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width + x = 0 + h = height * (1 - logo_height) + y = 0 + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + xc, yc = logo_w, height - .5 * logo_h + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0, 0, 0) + cr.set_line_width (min (w, h) * .01) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore() + cr.clip () + cr.set_source_rgb (1, 1, 1) + cr.paint () + + cr.set_source_rgb (0, 0, 0) diff --git a/gnu/slippy.py b/gnu/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/gnu/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/gnu_slides.py b/gnu_slides.py deleted file mode 100755 index 1a30f50..0000000 --- a/gnu_slides.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -slides = [] -def slide_add(f, data=None, width=800, height=400): - slides.append ((f, data, width, height)) - return f -import pango -def text_slide (l): - def s (r): - for i in l: - yield i - for i in range (30): - yield '' - slide_add (s, data={'align': pango.ALIGN_LEFT}) - -texts = {} -texts['en'] = """“Free software” is a matter of liberty, not price. To understand the -concept, you should think of “free” as in “free speech”, not as in “free beer.” - -Free software is a matter of the users' freedom to run, copy, -distribute, study, change and improve the software. - -More precisely, it refers to four kinds of freedom, for the users of the -software: ------------------------------------------------------------------------------- -0. The freedom to run the program, for any purpose. -1. The freedom to study how the program works, and adapt it to your needs. - Access to the source code is a precondition for this. -2. The freedom to redistribute copies so you can help your neighbor. -3. The freedom to improve the program, and release your improvements to - the public, so that the whole community benefits. - Access to the source code is a precondition for this. ------------------------------------------------------------------------------- -The concept of these 4 freedoms (0-3) were developed by Richard Stallman. - -To set a good example he started to write a completely free operating system. - -Today Linux based GNU systems are used by millions of people around the world.""" - -texts['de'] = """Bei dem Begriff „Freie Software“ geht es um Freiheit, nicht um den Preis. -Um dieses Konzept richtig begreifen zu können, sollte man an „frei“ wie in -„freie Rede“ denken, und nicht an „Freibier“. - -Bei „Freier Software“ geht es um die Freiheit des Benutzers die Software nach -Belieben zu benutzen, zu kopieren, weiter zu geben, die Software zu studieren, -sowie Änderungen und Verbesserungen an der Software vornehmen zu können. ------------------------------------------------------------------------------- -Genauer gesagt, bezieht sich der Begriff „Freie Software“ auf vier Arten von -Freiheit, die der Benutzer der Software hat: - -0. Die Freiheit, das Programm für jeden Zweck zu benutzen. -1. Die Freiheit, zu verstehen, wie das Programm funktioniert und wie man es - für seine Ansprüche anpassen kann. - Der Zugang zum Quellcode ist dafür Voraussetzung. ------------------------------------------------------------------------------- -2. Die Freiheit, Kopien weiterzuverbreiten, so dass man seinem Nächsten - weiterhelfen kann. -3. Die Freiheit, das Programm zu verbessern und die Verbesserungen der - Allgemeinheit zur Verfügung zu stellen, damit die ganze Gemeinschaft davon - profitieren kann. - Der Zugang zum Quellcode ist dafür Voraussetzung. ------------------------------------------------------------------------------- -Diese 4 Freiheiten (0-3) wurden so von Richard Stallman entworfen. - -Um mit gutem Beispiel voran zu gehen, hat er angefangen, ein vollständig -freies Betriebssystem zu entwickeln. - -Heute werden Linux basierte GNU Systeme von vielen Millionen Anwendern benutzt.""" - -texts['he'] = """"תוכנה חופשית" זה ענײן של חירות, לא של מחיר. כדי להבין את העקרון, -צריך לחשוב על "חופש" כמו ב"חופש הביטוי"...\ -.effectpause -.back 3 - ולא כמו ב"בירה חופשי". - -תוכנה חופשית נוגעת לחופש של משתמשים להריץ, להפיץ הפצת-המשך, ללמוד, -לשנות ולשפר את התוכנה. ליתר דיוק, זה מתײחס לארבעה סוגים של חירות למשתמשי -התוכנה: ------------------------------------------------------------------------------- -0. החופש להריץ את התוכנה, לכל מטרה שהיא. -1. החופש ללמוד איך תוכנה עובדת, ולשנות אותה לצרכיהם. - גישה לקוד המקור היא תנאי מקדים לכך. -2. החופש להפיץ עותקים בהפצה-חוזרת כדי שיוכלו למשל לעזור לשכנים שלהם. -3. החופש לשפר את התוכנה, ולשחרר את השיפורים שלהם לציבור, כך שכל הקהילה תרויח. - גישה לקוד-המקור היא תנאי מקדים לכך. ------------------------------------------------------------------------------- -The concept of these 4 freedoms (0-3) were developed by Richard Stallman. - -To set a good example he started to write a completely free operating system. - -Today Linux based GNU systems are used by millions of people around the world.""" - -import os, re -lang = os.getenv ('LANG') -i = lang.find ('_') -if i > 0: - lang = lang[:i] -text = texts.get (lang, texts['en']) -def break_on_dashlines (text): - s = '' - for line in text.split ('\n'): - if re.match ('^----*$', line): - yield s - s = '' - else: - if s: - s += '\n' - s += line - yield s - -for slide in break_on_dashlines (text): - text_slide (slide) - -if __name__ == "__main__": - import slippy - import gnu_theme - slippy.main (slides, gnu_theme, args = ['--slideshow', '--delay', '0.05', '--repeat']) diff --git a/gnu_theme.py b/gnu_theme.py deleted file mode 100644 index 0550007..0000000 --- a/gnu_theme.py +++ /dev/null @@ -1,81 +0,0 @@ -import cairo - -logo_height = .3 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - cr.save () - cr.set_operator (cairo.OPERATOR_CLEAR) - cr.paint () - cr.restore () - - cr.move_to (0, height) - global logo_w, logo_h - logo_w, logo_h = renderer.put_image ("gnu-color.png", height=logo_height*height, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - x = 0 - h = height * (1 - logo_height) - y = 0 - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - xc, yc = logo_w, height - .5 * logo_h - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0, 0, 0) - cr.set_line_width (min (w, h) * .01) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore() - cr.clip () - cr.set_source_rgb (1, 1, 1) - cr.paint () - - cr.set_source_rgb (0, 0, 0) diff --git a/grancanariadesktopsummit.png b/grancanariadesktopsummit.png deleted file mode 100644 index abed891..0000000 Binary files a/grancanariadesktopsummit.png and /dev/null differ diff --git a/gtkprinting/Printer_in_1568-ce.png b/gtkprinting/Printer_in_1568-ce.png new file mode 100644 index 0000000..80d34b4 Binary files /dev/null and b/gtkprinting/Printer_in_1568-ce.png differ diff --git a/gtkprinting/behdad.svg b/gtkprinting/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/gtkprinting/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/gtkprinting/gtkprinting_slides.py b/gtkprinting/gtkprinting_slides.py new file mode 100755 index 0000000..9738dfa --- /dev/null +++ b/gtkprinting/gtkprinting_slides.py @@ -0,0 +1,25 @@ +#!/usr/bin/python + +def slide_add(f, data=None, width=800, height=600): + if not data: + data = {'who': -1} + slides.append ((f, data, width, height)) + return f + +slides = [] +slide_add ("GTK+ Printing") +slide_add ("History") +slide_add ("Native dialogs\n on Win32 / OS X") +slide_add ("App can add\n widgets / pages\n to dialog") +slide_add ("App can ask\n for notification\n even after spooling") +slide_add ("Cairo\n for rendering") +slide_add ("On Unix,\n passthrough\n Postscript too") +slide_add ('Backends:\nFile\nCUPS\nlpr\nPAPI') +slide_add ("External\n application for\n preview by default\n (evince)") +slide_add ("Async operation\n (not on Win32)\n Redo CUPS convenience API") +slide_add ("That's\n mostly\n it!") + +if __name__ == "__main__": + import slippy + import gtkprinting_theme + slippy.main (slides, gtkprinting_theme) diff --git a/gtkprinting/gtkprinting_theme.py b/gtkprinting/gtkprinting_theme.py new file mode 100644 index 0000000..e2588ff --- /dev/null +++ b/gtkprinting/gtkprinting_theme.py @@ -0,0 +1,137 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .07 +logo_margin = .06 +footer_margin = .05 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + +import math + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = logo_margin * height + f = footer_margin * height + p = padding * min (width, height) + p2 = 2 * p + + cr.set_source_rgb (1, 1, 1) + cr.paint () + + # Background image + cr.move_to (width / 2., height / 2.) + renderer.put_image ("Printer_in_1568-ce.png", width = width) + + cr.save () + cr.rotate (math.pi / 2) + cr.move_to ((height-p2) / 2, - width) + cr.set_source_rgb (0, 0, 0) + renderer.put_text ("OpenPrinting Summit, Montréal, September 25, 2007", height=f-p2, valign=+1) + cr.restore () + + # Red Hat logos at the top + cr.move_to (p, p) + renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0, 0, 0) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + cr.set_source_rgba (1, 1, 1, .9) + cr.paint () + + cr.set_source_rgb (0, 0, 0) diff --git a/gtkprinting/redhat.svg b/gtkprinting/redhat.svg new file mode 100644 index 0000000..89315b6 --- /dev/null +++ b/gtkprinting/redhat.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gtkprinting/slippy.py b/gtkprinting/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/gtkprinting/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/gtkprinting_slides.py b/gtkprinting_slides.py deleted file mode 100755 index 9738dfa..0000000 --- a/gtkprinting_slides.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python - -def slide_add(f, data=None, width=800, height=600): - if not data: - data = {'who': -1} - slides.append ((f, data, width, height)) - return f - -slides = [] -slide_add ("GTK+ Printing") -slide_add ("History") -slide_add ("Native dialogs\n on Win32 / OS X") -slide_add ("App can add\n widgets / pages\n to dialog") -slide_add ("App can ask\n for notification\n even after spooling") -slide_add ("Cairo\n for rendering") -slide_add ("On Unix,\n passthrough\n Postscript too") -slide_add ('Backends:\nFile\nCUPS\nlpr\nPAPI') -slide_add ("External\n application for\n preview by default\n (evince)") -slide_add ("Async operation\n (not on Win32)\n Redo CUPS convenience API") -slide_add ("That's\n mostly\n it!") - -if __name__ == "__main__": - import slippy - import gtkprinting_theme - slippy.main (slides, gtkprinting_theme) diff --git a/gtkprinting_theme.py b/gtkprinting_theme.py deleted file mode 100644 index e2588ff..0000000 --- a/gtkprinting_theme.py +++ /dev/null @@ -1,137 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .07 -logo_margin = .06 -footer_margin = .05 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - -import math - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = logo_margin * height - f = footer_margin * height - p = padding * min (width, height) - p2 = 2 * p - - cr.set_source_rgb (1, 1, 1) - cr.paint () - - # Background image - cr.move_to (width / 2., height / 2.) - renderer.put_image ("Printer_in_1568-ce.png", width = width) - - cr.save () - cr.rotate (math.pi / 2) - cr.move_to ((height-p2) / 2, - width) - cr.set_source_rgb (0, 0, 0) - renderer.put_text ("OpenPrinting Summit, Montréal, September 25, 2007", height=f-p2, valign=+1) - cr.restore () - - # Red Hat logos at the top - cr.move_to (p, p) - renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0, 0, 0) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - cr.set_source_rgba (1, 1, 1, .9) - cr.paint () - - cr.set_source_rgb (0, 0, 0) diff --git a/guadec.svg b/guadec.svg deleted file mode 100644 index 2306140..0000000 --- a/guadec.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/harfbuzz/IgreenNY.jpg b/harfbuzz/IgreenNY.jpg new file mode 100644 index 0000000..fedef80 Binary files /dev/null and b/harfbuzz/IgreenNY.jpg differ diff --git a/harfbuzz/behdad.svg b/harfbuzz/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/harfbuzz/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/harfbuzz/harfbuzz_slides.py b/harfbuzz/harfbuzz_slides.py new file mode 100755 index 0000000..24ccdf5 --- /dev/null +++ b/harfbuzz/harfbuzz_slides.py @@ -0,0 +1,207 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +if __name__ == "__main__": + import slippy + import sys + import harfbuzz_theme + slippy.main (__file__, harfbuzz_theme, sys.argv[1:]) + sys.exit (0) + +# Copyright 2007,2009 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_behdad(f, data=None): + return slide_who (f, behdad, data=data) +def slide_image (f, height=650, data=None): + @slide_noone + def image_func (r): + r.move_to (400, 300) + r.put_image (f, height=height) + #r.set_allocation (000, 0, 800, 600) + yield "" + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (800, 30) + r.put_text ( +"""HarfBuzz\nthe Free and Open\nShaping Engine""", +width=800, height=500, valign=1, halign=-1) + + r.move_to (0, 570) + r.put_text ("""Behdad Esfahbod\nbehdad@redhat.com\nhttp://behdad.org/\nhttp://freedesktop.org/wiki/Software/HarfBuzz""", height=130, halign=1, valign=-1) + + +who (behdad) + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +list_slide ([ + "Agenda", + "• Introduction", + "• History", + "• Old HarfBuzz", + "• New HarfBuzz", + "• Scope", + "• Design", + "• Status", + "• Roadmap", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("Intro") +slide(" حرف باز ") +slide("Free and Open\nUnicode\nShaping Engine") + +slide_noone("History") +slide("FreeType\nOpenType\nLayout") +slide("GNOME\nKDE") +slide("Pango\nQt") + +slide_noone("Old\nHarfBuzz") +slide("2006") +slide("Qt\nShapers") +list_slide([ "Problems", + "• Inefficient", + "• Fragile", + "• Ugly", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("New\nHarfBuzz") +slide("Baking") + +slide_noone("Scope") +list_slide([ "Generic Shaper", + "• OpenType", + "• ATT", + "• Graphite", + "• Fallback", + "• ...", + ], data={'align': pango.ALIGN_LEFT}) +list_slide([ "Just Shaper", + "• No Itemizer", + "• No Bidi", + "• No Line Breaking", + "• No Rasterization", + ], data={'align': pango.ALIGN_LEFT}) +list_slide([ "Goals", + "• Beautiful", + "• Robust", + "• Flexible", + "• Efficient", + "• Portable", + ], data={'align': pango.ALIGN_LEFT}) +list_slide ([ "Consumers", + "• GUI Toolkits", + "• Web Browsers", + "• Word Processors", + "• Designer Tools", + "• Font Design Tools", + "• Terminal Emulators", + "• Batch Doc Processors", + "• TeX Engines", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("Design") +slide("For Humans\nhb_face_t\nhb_font_t\nhb_buffer_t") +slide("Unicode\nCallbacks") +slide("Font\nCallbacks") +slide("SFNT-\nBased") +slide("Garbage-In\nGlyphs-Out") +slide("Fallbacks") +slide("In-Place") +slide("Error\nHandling") +slide("Backend-\nIndependent") +slide("Backend\nAPI") +slide("Thread-\nSafe") +slide("No\nDependencies") +slide("Well\nSome C++") +slide("MIT-\nLicensed") +list_slide ([ "OpenType 1.6", + "• Mark filtering sets", + "• cmap type 14", + "• Mirroring", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone("Status") +slide("OpenType\nLayout") +slide("API\nReview") +slide("Shapers") +slide("Test\nSuite") + + +""" +list_slide ([ "", + "• ", + "• ", + "• ", + "• ", + "• ", + "• ", + ], data={'align': pango.ALIGN_LEFT}) +""" + +@slide +def where_is_my_vote (r): + r.move_to (400, 300) + r.put_image ("IgreenNY.jpg", height=1024) + return "" + +slide_noone("Q?") diff --git a/harfbuzz/harfbuzz_theme.py b/harfbuzz/harfbuzz_theme.py new file mode 100644 index 0000000..713820a --- /dev/null +++ b/harfbuzz/harfbuzz_theme.py @@ -0,0 +1,133 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007,2009 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .06 +top_margin = .02 +bottom_margin = .06 +padding = .006 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = top_margin * height + f = bottom_margin * height + p = padding * min (width, height) + p2 = 2 * p + + a = 1 + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) + cr.paint () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgb (0xff/255.*a, 0xda/255.*a, 0x4c/255.*a) + renderer.put_text ("Internationalization & Unicode Conference 33, October 14—16, 2009, San Jose", height=(f-p2)*.8, width=(width-2*s)*.8, valign=-1) + + cr.move_to (width-p, height-p) + #renderer.put_image ("unicode.png", height = f-p2, valign=-1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + a = .7 + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + a = 10 + cr.set_source_rgb (0xfe/255.*a, 0x9a/255.*a, 0x35/255.*a) + cr.paint () + + a = .1 + cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) diff --git a/harfbuzz/slippy.py b/harfbuzz/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/harfbuzz/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/harfbuzz_slides.py b/harfbuzz_slides.py deleted file mode 100755 index 24ccdf5..0000000 --- a/harfbuzz_slides.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -if __name__ == "__main__": - import slippy - import sys - import harfbuzz_theme - slippy.main (__file__, harfbuzz_theme, sys.argv[1:]) - sys.exit (0) - -# Copyright 2007,2009 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_behdad(f, data=None): - return slide_who (f, behdad, data=data) -def slide_image (f, height=650, data=None): - @slide_noone - def image_func (r): - r.move_to (400, 300) - r.put_image (f, height=height) - #r.set_allocation (000, 0, 800, 600) - yield "" - -# -# Slides start here -# - -@slide_noone -def title_slide (r): - r.move_to (800, 30) - r.put_text ( -"""HarfBuzz\nthe Free and Open\nShaping Engine""", -width=800, height=500, valign=1, halign=-1) - - r.move_to (0, 570) - r.put_text ("""Behdad Esfahbod\nbehdad@redhat.com\nhttp://behdad.org/\nhttp://freedesktop.org/wiki/Software/HarfBuzz""", height=130, halign=1, valign=-1) - - -who (behdad) - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) - -list_slide ([ - "Agenda", - "• Introduction", - "• History", - "• Old HarfBuzz", - "• New HarfBuzz", - "• Scope", - "• Design", - "• Status", - "• Roadmap", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("Intro") -slide(" حرف باز ") -slide("Free and Open\nUnicode\nShaping Engine") - -slide_noone("History") -slide("FreeType\nOpenType\nLayout") -slide("GNOME\nKDE") -slide("Pango\nQt") - -slide_noone("Old\nHarfBuzz") -slide("2006") -slide("Qt\nShapers") -list_slide([ "Problems", - "• Inefficient", - "• Fragile", - "• Ugly", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("New\nHarfBuzz") -slide("Baking") - -slide_noone("Scope") -list_slide([ "Generic Shaper", - "• OpenType", - "• ATT", - "• Graphite", - "• Fallback", - "• ...", - ], data={'align': pango.ALIGN_LEFT}) -list_slide([ "Just Shaper", - "• No Itemizer", - "• No Bidi", - "• No Line Breaking", - "• No Rasterization", - ], data={'align': pango.ALIGN_LEFT}) -list_slide([ "Goals", - "• Beautiful", - "• Robust", - "• Flexible", - "• Efficient", - "• Portable", - ], data={'align': pango.ALIGN_LEFT}) -list_slide ([ "Consumers", - "• GUI Toolkits", - "• Web Browsers", - "• Word Processors", - "• Designer Tools", - "• Font Design Tools", - "• Terminal Emulators", - "• Batch Doc Processors", - "• TeX Engines", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("Design") -slide("For Humans\nhb_face_t\nhb_font_t\nhb_buffer_t") -slide("Unicode\nCallbacks") -slide("Font\nCallbacks") -slide("SFNT-\nBased") -slide("Garbage-In\nGlyphs-Out") -slide("Fallbacks") -slide("In-Place") -slide("Error\nHandling") -slide("Backend-\nIndependent") -slide("Backend\nAPI") -slide("Thread-\nSafe") -slide("No\nDependencies") -slide("Well\nSome C++") -slide("MIT-\nLicensed") -list_slide ([ "OpenType 1.6", - "• Mark filtering sets", - "• cmap type 14", - "• Mirroring", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone("Status") -slide("OpenType\nLayout") -slide("API\nReview") -slide("Shapers") -slide("Test\nSuite") - - -""" -list_slide ([ "", - "• ", - "• ", - "• ", - "• ", - "• ", - "• ", - ], data={'align': pango.ALIGN_LEFT}) -""" - -@slide -def where_is_my_vote (r): - r.move_to (400, 300) - r.put_image ("IgreenNY.jpg", height=1024) - return "" - -slide_noone("Q?") diff --git a/harfbuzz_theme.py b/harfbuzz_theme.py deleted file mode 100644 index 713820a..0000000 --- a/harfbuzz_theme.py +++ /dev/null @@ -1,133 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007,2009 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .06 -top_margin = .02 -bottom_margin = .06 -padding = .006 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = top_margin * height - f = bottom_margin * height - p = padding * min (width, height) - p2 = 2 * p - - a = 1 - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) - cr.paint () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgb (0xff/255.*a, 0xda/255.*a, 0x4c/255.*a) - renderer.put_text ("Internationalization & Unicode Conference 33, October 14—16, 2009, San Jose", height=(f-p2)*.8, width=(width-2*s)*.8, valign=-1) - - cr.move_to (width-p, height-p) - #renderer.put_image ("unicode.png", height = f-p2, valign=-1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - a = .7 - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - a = 10 - cr.set_source_rgb (0xfe/255.*a, 0x9a/255.*a, 0x35/255.*a) - cr.paint () - - a = .1 - cr.set_source_rgb (0xdb/255.*a, 0x52/255.*a, 0x26/255.*a) diff --git a/johnny_automatic_laser_printer.svg b/johnny_automatic_laser_printer.svg deleted file mode 100644 index 261f78f..0000000 --- a/johnny_automatic_laser_printer.svg +++ /dev/null @@ -1,1502 +0,0 @@ - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/n810.jpg b/n810.jpg deleted file mode 100644 index 8547d8a..0000000 Binary files a/n810.jpg and /dev/null differ diff --git a/olpc.jpg b/olpc.jpg deleted file mode 100644 index 88dd948..0000000 Binary files a/olpc.jpg and /dev/null differ diff --git a/openmoko.jpg b/openmoko.jpg deleted file mode 100644 index 19383ee..0000000 Binary files a/openmoko.jpg and /dev/null differ diff --git a/pumpkin-small.png b/pumpkin-small.png deleted file mode 100644 index 8e0e570..0000000 Binary files a/pumpkin-small.png and /dev/null differ diff --git a/redhat.svg b/redhat.svg deleted file mode 100644 index 89315b6..0000000 --- a/redhat.svg +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/screenshot-gnome-desktop.png b/screenshot-gnome-desktop.png deleted file mode 100644 index d406151..0000000 Binary files a/screenshot-gnome-desktop.png and /dev/null differ diff --git a/southpark.mp3 b/southpark.mp3 deleted file mode 100644 index 39ed8fa..0000000 Binary files a/southpark.mp3 and /dev/null differ diff --git a/stateoftext/behdad.svg b/stateoftext/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/stateoftext/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/stateoftext/grancanariadesktopsummit.png b/stateoftext/grancanariadesktopsummit.png new file mode 100644 index 0000000..abed891 Binary files /dev/null and b/stateoftext/grancanariadesktopsummit.png differ diff --git a/stateoftext/slippy.py b/stateoftext/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/stateoftext/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/stateoftext/stateoftext_slides.py b/stateoftext/stateoftext_slides.py new file mode 100755 index 0000000..c51ce94 --- /dev/null +++ b/stateoftext/stateoftext_slides.py @@ -0,0 +1,234 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +# Copyright 2007,2009 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_behdad(f, data=None): + return slide_who (f, behdad, data=data) +def slide_image (f, height=650, data=None): + @slide_noone + def image_func (r): + r.move_to (400, 300) + r.put_image (f, height=height) + #r.set_allocation (000, 0, 800, 600) + yield "" + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (800, 50) + r.put_text ( +"""State\nof\nText\nRendering""", +width=800, height=500, valign=1, halign=-1) + + r.move_to (0, 530) + r.put_text ("""Behdad Esfahbod\nbehdad@gnome.org\nhttp://behdad.org/text""", + desc="12", halign=1, valign=-1) + +who (behdad) + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +slide_noone("Check the paper:\nhttp://behdad.org/text") + +list_slide ([ + "Agenda", + "• The Stack", + "• Shapers", + "• Shaper Consumers", + "• Problems", + "• Recent Advances", + "• More Problems", + "• Road Ahead", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Meet the Stack", + "• Pango", + "• HarfBuzz", + "• FriBidi", + "• Fontconfig", + "• FreeType", + ], data={'align': pango.ALIGN_LEFT}) + +slide("OpenType") +slide("HarfBuzz") + +list_slide ([ + "Other Free Shapers", + "• ICU", + "• m17n", + "• SIL Graphite", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Consumers", + "• GUI Toolkits", + "• Web Browsers", + "• Word Processors", + "• Designer Tools", + "• Font Design Tools", + "• Terminal Emulators", + "• Batch Doc Processors", + "• TeX Engines", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Excellence", + "• Supported Font Formats", + "• Configuration Mechanism", + "• Transparent Font Fallback", + "• Standard Compliance", + "• Minority Scripts", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Problems", + "• Good Enough", + "• Segregated Efforts", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Segregated Efforts", + "• Font packager's fault", + "• Font configuration GUI", + "• Vertical text", + "• Text Layout Summit", + "• unifont.org", + "• Graphite and m17n", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Recent Advances", + "• Streamlining font packaging", + "• Online font add/remove", + "• Automatic font installation", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone ("Demo\nTime!") + +list_slide ([ + "Online font add/remove", + "1. gnome-settings-daemon monitors", + "2. g-s-d rebuilds cache ", + "3. g-s-d signals via XSETTINGS ", + "4. GTK+ catches, drops Pango caches ", + "5. GTK+ sends \"theme-changed\" ", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Automatic font installation", + "1. RPM detects font at pkg build time", + "2. RPM tags package using fc-query", + "3. PackgeKit installs GTK+ module", + "4. GTK+ overrides Pango default fontmap", + "5. PK receives font install request", + "6. Installed fonts are picked up", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Major Problems", + "• CJK Problem", + "• Indic Problem", + "• Latin Problem", + ], data={'align': pango.ALIGN_LEFT}) + +list_slide ([ + "Road Ahead", + "• HarfBuzz: layout, API, merge", + "• Subpixel rendering and positioning", + "• Font chooser dialog", + "• Font configurator", + "• Font websites", + "• Font viewer", + "• Application fonts", + ], data={'align': pango.ALIGN_LEFT}) + +""" +list_slide ([ + "", + "• ", + "• ", + "• ", + "• ", + "• ", + "• ", + ], data={'align': pango.ALIGN_LEFT}) +""" + +@slide +def where_is_my_vote (r): + r.set_source_rgb (0, .9, 0) + r.paint () + r.set_source_rgb (1, 1, 1) + return "Where\nis\nMy Vote?" + +slide_noone("Q?") + +if __name__ == "__main__": + import slippy + import stateoftext_theme + import sys + #slippy.main (slides, stateoftext_theme) + #slippy.main ("stateoftext_slides.py", "stateoftext_theme.py") + slippy.main (slides, "stateoftext_theme.py") + sys.exit (0) + diff --git a/stateoftext/stateoftext_theme.py b/stateoftext/stateoftext_theme.py new file mode 100644 index 0000000..2c9f4a7 --- /dev/null +++ b/stateoftext/stateoftext_theme.py @@ -0,0 +1,130 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007,2009 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .08 +top_margin = .02 +bottom_margin = .14 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = top_margin * height + f = bottom_margin * height + p = padding * min (width, height) + p2 = 2 * p + + cr.set_source_rgb (128/255., 255/255., 148/255.) + cr.paint () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgba (0,.2,0) + renderer.put_text ("July 5th, 2009", height=(f-p2)*.5, valign=-1) + + cr.move_to (width-p, height-p) + renderer.put_image ("grancanariadesktopsummit.png", height = f-p2, valign=-1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + a = .5 + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (64/255.*a, 128/255.*a, 64/255.*a) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + cr.set_source_rgba (.92, .98, 1, 1) + cr.paint () + + cr.set_source_rgb (96/255.*a, 128/255.*a, 96/255.*a) diff --git a/stateoftext_slides.py b/stateoftext_slides.py deleted file mode 100755 index c51ce94..0000000 --- a/stateoftext_slides.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -# Copyright 2007,2009 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_behdad(f, data=None): - return slide_who (f, behdad, data=data) -def slide_image (f, height=650, data=None): - @slide_noone - def image_func (r): - r.move_to (400, 300) - r.put_image (f, height=height) - #r.set_allocation (000, 0, 800, 600) - yield "" - -# -# Slides start here -# - -@slide_noone -def title_slide (r): - r.move_to (800, 50) - r.put_text ( -"""State\nof\nText\nRendering""", -width=800, height=500, valign=1, halign=-1) - - r.move_to (0, 530) - r.put_text ("""Behdad Esfahbod\nbehdad@gnome.org\nhttp://behdad.org/text""", - desc="12", halign=1, valign=-1) - -who (behdad) - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) - -slide_noone("Check the paper:\nhttp://behdad.org/text") - -list_slide ([ - "Agenda", - "• The Stack", - "• Shapers", - "• Shaper Consumers", - "• Problems", - "• Recent Advances", - "• More Problems", - "• Road Ahead", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Meet the Stack", - "• Pango", - "• HarfBuzz", - "• FriBidi", - "• Fontconfig", - "• FreeType", - ], data={'align': pango.ALIGN_LEFT}) - -slide("OpenType") -slide("HarfBuzz") - -list_slide ([ - "Other Free Shapers", - "• ICU", - "• m17n", - "• SIL Graphite", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Consumers", - "• GUI Toolkits", - "• Web Browsers", - "• Word Processors", - "• Designer Tools", - "• Font Design Tools", - "• Terminal Emulators", - "• Batch Doc Processors", - "• TeX Engines", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Excellence", - "• Supported Font Formats", - "• Configuration Mechanism", - "• Transparent Font Fallback", - "• Standard Compliance", - "• Minority Scripts", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Problems", - "• Good Enough", - "• Segregated Efforts", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Segregated Efforts", - "• Font packager's fault", - "• Font configuration GUI", - "• Vertical text", - "• Text Layout Summit", - "• unifont.org", - "• Graphite and m17n", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Recent Advances", - "• Streamlining font packaging", - "• Online font add/remove", - "• Automatic font installation", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone ("Demo\nTime!") - -list_slide ([ - "Online font add/remove", - "1. gnome-settings-daemon monitors", - "2. g-s-d rebuilds cache ", - "3. g-s-d signals via XSETTINGS ", - "4. GTK+ catches, drops Pango caches ", - "5. GTK+ sends \"theme-changed\" ", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Automatic font installation", - "1. RPM detects font at pkg build time", - "2. RPM tags package using fc-query", - "3. PackgeKit installs GTK+ module", - "4. GTK+ overrides Pango default fontmap", - "5. PK receives font install request", - "6. Installed fonts are picked up", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Major Problems", - "• CJK Problem", - "• Indic Problem", - "• Latin Problem", - ], data={'align': pango.ALIGN_LEFT}) - -list_slide ([ - "Road Ahead", - "• HarfBuzz: layout, API, merge", - "• Subpixel rendering and positioning", - "• Font chooser dialog", - "• Font configurator", - "• Font websites", - "• Font viewer", - "• Application fonts", - ], data={'align': pango.ALIGN_LEFT}) - -""" -list_slide ([ - "", - "• ", - "• ", - "• ", - "• ", - "• ", - "• ", - ], data={'align': pango.ALIGN_LEFT}) -""" - -@slide -def where_is_my_vote (r): - r.set_source_rgb (0, .9, 0) - r.paint () - r.set_source_rgb (1, 1, 1) - return "Where\nis\nMy Vote?" - -slide_noone("Q?") - -if __name__ == "__main__": - import slippy - import stateoftext_theme - import sys - #slippy.main (slides, stateoftext_theme) - #slippy.main ("stateoftext_slides.py", "stateoftext_theme.py") - slippy.main (slides, "stateoftext_theme.py") - sys.exit (0) - diff --git a/stateoftext_theme.py b/stateoftext_theme.py deleted file mode 100644 index 2c9f4a7..0000000 --- a/stateoftext_theme.py +++ /dev/null @@ -1,130 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007,2009 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .08 -top_margin = .02 -bottom_margin = .14 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = top_margin * height - f = bottom_margin * height - p = padding * min (width, height) - p2 = 2 * p - - cr.set_source_rgb (128/255., 255/255., 148/255.) - cr.paint () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgba (0,.2,0) - renderer.put_text ("July 5th, 2009", height=(f-p2)*.5, valign=-1) - - cr.move_to (width-p, height-p) - renderer.put_image ("grancanariadesktopsummit.png", height = f-p2, valign=-1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - a = .5 - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (64/255.*a, 128/255.*a, 64/255.*a) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - cr.set_source_rgba (.92, .98, 1, 1) - cr.paint () - - cr.set_source_rgb (96/255.*a, 128/255.*a, 96/255.*a) diff --git a/street.jpg b/street.jpg deleted file mode 100644 index 6467f16..0000000 Binary files a/street.jpg and /dev/null differ diff --git a/textextraction/Fi_garamond_sort_001.png b/textextraction/Fi_garamond_sort_001.png new file mode 100644 index 0000000..f7b944d Binary files /dev/null and b/textextraction/Fi_garamond_sort_001.png differ diff --git a/textextraction/Metal_movable_type.jpg b/textextraction/Metal_movable_type.jpg new file mode 100644 index 0000000..75b6c97 Binary files /dev/null and b/textextraction/Metal_movable_type.jpg differ diff --git a/textextraction/behdad.svg b/textextraction/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/textextraction/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/textextraction/cairo.svg b/textextraction/cairo.svg new file mode 100644 index 0000000..49a049e --- /dev/null +++ b/textextraction/cairo.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/textextraction/redhat.svg b/textextraction/redhat.svg new file mode 100644 index 0000000..89315b6 --- /dev/null +++ b/textextraction/redhat.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/textextraction/slippy.py b/textextraction/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/textextraction/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/textextraction/textextraction_slides.py b/textextraction/textextraction_slides.py new file mode 100755 index 0000000..fca6e54 --- /dev/null +++ b/textextraction/textextraction_slides.py @@ -0,0 +1,183 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +# Copyright 2007 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_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 ( +"""Generating perfectly\ntext-extractable\nPDFs""", width=800, valign=1) + + r.move_to (0, 450) + r.put_text ("""Behdad Esfahbod\nbesfahbo@redhat.com""", + desc="20", halign=1, valign=-1) + +who (behdad) + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +slide_noone("Terminology 101") + +list_slide ([ + "• Character", + "• Glyph", + "• Codepoint", + ], data={'align': pango.ALIGN_LEFT}) +list_slide ([ + "• Input text", + "• Output glyph", + "• Encoded codepoints", + ], data={'align': pango.ALIGN_LEFT}) +list_slide ([ + '• "Hello"', + "• 〈1,2,3,3,4〉", + "• 〈0102030304〉", + ], data={'align': pango.ALIGN_LEFT}) + +slide_noone('Overview of\nPDF Fonts\n(subsetted,\ncustom encoding)') + +list_slide ([ + '• Simple', + '• Composite', + ], data={'align': pango.ALIGN_LEFT}) + +slide ('Simple Fonts\neach byte of\nencoded codepoints\nrepresents one codepoint') +list_slide ([ + 'Simple Fonts', + '• Type1', + '• TrueType', + '• Type3', + ], data={'align': pango.ALIGN_LEFT}) + +slide ('Composite Fonts\ncomplex mapping of\nencoded codepoints\nto codepoints') +list_slide ([ + 'Composite Fonts', + '(CID-keyed Fonts)', + '• Type0 (CFF)', + '• Type2 (TrueType)', + ], data={'align': pango.ALIGN_LEFT}) + +slide ('A CID is exactly\nwhat we called\na codepoint') + +slide ('Observation\nAll PDF fonts can\nhave arbitrary\ncodepoint-to-glyph\nmapping') +slide ('ToUnicode\nAll PDF fonts can\nhave a codepoint-to-\nsequence-of-characters\nmapping') +slide ('ToUnicode mapping\nis the only\nstandard way for\ntext extraction') + +slide ("Broken Practice\nUse original font's\ncharacter-to-glyph\nmapping to generate\nToUnicode mapping") +slide ('Assumes\nreversible\nchar-to-glyph\nmapping') + +slide_noone('What\nTo Do?') +slide('Admit that\nchar-to-glyph\nmapping is\n not 1-to-1') +slide('Corollary\noutput glyphs\nare not enough\nto produce\ngood PDF text') + + +slide_noone("Terminology 201") + +list_slide ([ + "• Cluster", + ], data={'align': pango.ALIGN_LEFT}) +@slide_noone +def cluster_image (r): + r.move_to (400, 300) + r.put_image ("Fi_garamond_sort_001.png", height=650) + r.set_allocation (200, 0, 400, 600) + yield "" +list_slide ([ + "Cluster", + "• Grapheme cluster: ö", + "• Ligature cluster:", + ' - Typographical: 〈f,i〉 → 〈fi〉', + ' - Orthographical: 〈‎,‎〉 → 〈〉', + ], data={'align': pango.ALIGN_LEFT}) +list_slide ([ + "Cluster", + "• M input character", + "• N output glyphs", + "• M→N cluster" + ], data={'align': pango.ALIGN_LEFT}) +list_slide ([ + "• Cluster mapping", + ], data={'align': pango.ALIGN_LEFT}) +slide ('Any good\nPDF generator\nshould take\ninput text,\noutput glyphs,\nand\ncluster mapping') + +slide_noone("What To Do\nWith Them?") +slide ("M→1") +slide ("M→0") +slide ("M→N") + +slide_noone("Issues") +slide ("0→1") +slide ("How to\nbreak?") +slide ("Cursor\npositions") +slide ("Run\norder") +slide ("Bidi") + +slide_noone ('~fin~') + +if __name__ == "__main__": + import slippy + import textextraction_theme + slippy.main (slides, textextraction_theme) diff --git a/textextraction/textextraction_theme.py b/textextraction/textextraction_theme.py new file mode 100644 index 0000000..e96ba69 --- /dev/null +++ b/textextraction/textextraction_theme.py @@ -0,0 +1,136 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .07 +logo_margin = .06 +footer_margin = .05 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = logo_margin * height + f = footer_margin * height + p = padding * min (width, height) + p2 = 2 * p + + cr.set_source_rgb (0xeb/255., 0xd7/255., 0xbb/255.) + cr.paint () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) + renderer.put_text ("OpenPrinting Summit, Montréal, September 24, 2007", height=f-p2, valign=-1) + + # Background image + cr.move_to (width / 2., height / 2.) + renderer.put_image ("Metal_movable_type.jpg", height = height, width = width) + + # Red Hat/cairo logos at the top + cr.move_to (p, p) + renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) + + cr.move_to (width-p, p) + renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (0, 0, 0) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + cr.set_source_rgba (1, 1, 1, .9) + cr.paint () + + cr.set_source_rgb (0, 0, 0) diff --git a/textextraction_slides.py b/textextraction_slides.py deleted file mode 100755 index fca6e54..0000000 --- a/textextraction_slides.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -# Copyright 2007 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_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 ( -"""Generating perfectly\ntext-extractable\nPDFs""", width=800, valign=1) - - r.move_to (0, 450) - r.put_text ("""Behdad Esfahbod\nbesfahbo@redhat.com""", - desc="20", halign=1, valign=-1) - -who (behdad) - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) - -slide_noone("Terminology 101") - -list_slide ([ - "• Character", - "• Glyph", - "• Codepoint", - ], data={'align': pango.ALIGN_LEFT}) -list_slide ([ - "• Input text", - "• Output glyph", - "• Encoded codepoints", - ], data={'align': pango.ALIGN_LEFT}) -list_slide ([ - '• "Hello"', - "• 〈1,2,3,3,4〉", - "• 〈0102030304〉", - ], data={'align': pango.ALIGN_LEFT}) - -slide_noone('Overview of\nPDF Fonts\n(subsetted,\ncustom encoding)') - -list_slide ([ - '• Simple', - '• Composite', - ], data={'align': pango.ALIGN_LEFT}) - -slide ('Simple Fonts\neach byte of\nencoded codepoints\nrepresents one codepoint') -list_slide ([ - 'Simple Fonts', - '• Type1', - '• TrueType', - '• Type3', - ], data={'align': pango.ALIGN_LEFT}) - -slide ('Composite Fonts\ncomplex mapping of\nencoded codepoints\nto codepoints') -list_slide ([ - 'Composite Fonts', - '(CID-keyed Fonts)', - '• Type0 (CFF)', - '• Type2 (TrueType)', - ], data={'align': pango.ALIGN_LEFT}) - -slide ('A CID is exactly\nwhat we called\na codepoint') - -slide ('Observation\nAll PDF fonts can\nhave arbitrary\ncodepoint-to-glyph\nmapping') -slide ('ToUnicode\nAll PDF fonts can\nhave a codepoint-to-\nsequence-of-characters\nmapping') -slide ('ToUnicode mapping\nis the only\nstandard way for\ntext extraction') - -slide ("Broken Practice\nUse original font's\ncharacter-to-glyph\nmapping to generate\nToUnicode mapping") -slide ('Assumes\nreversible\nchar-to-glyph\nmapping') - -slide_noone('What\nTo Do?') -slide('Admit that\nchar-to-glyph\nmapping is\n not 1-to-1') -slide('Corollary\noutput glyphs\nare not enough\nto produce\ngood PDF text') - - -slide_noone("Terminology 201") - -list_slide ([ - "• Cluster", - ], data={'align': pango.ALIGN_LEFT}) -@slide_noone -def cluster_image (r): - r.move_to (400, 300) - r.put_image ("Fi_garamond_sort_001.png", height=650) - r.set_allocation (200, 0, 400, 600) - yield "" -list_slide ([ - "Cluster", - "• Grapheme cluster: ö", - "• Ligature cluster:", - ' - Typographical: 〈f,i〉 → 〈fi〉', - ' - Orthographical: 〈‎,‎〉 → 〈〉', - ], data={'align': pango.ALIGN_LEFT}) -list_slide ([ - "Cluster", - "• M input character", - "• N output glyphs", - "• M→N cluster" - ], data={'align': pango.ALIGN_LEFT}) -list_slide ([ - "• Cluster mapping", - ], data={'align': pango.ALIGN_LEFT}) -slide ('Any good\nPDF generator\nshould take\ninput text,\noutput glyphs,\nand\ncluster mapping') - -slide_noone("What To Do\nWith Them?") -slide ("M→1") -slide ("M→0") -slide ("M→N") - -slide_noone("Issues") -slide ("0→1") -slide ("How to\nbreak?") -slide ("Cursor\npositions") -slide ("Run\norder") -slide ("Bidi") - -slide_noone ('~fin~') - -if __name__ == "__main__": - import slippy - import textextraction_theme - slippy.main (slides, textextraction_theme) diff --git a/textextraction_theme.py b/textextraction_theme.py deleted file mode 100644 index e96ba69..0000000 --- a/textextraction_theme.py +++ /dev/null @@ -1,136 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .07 -logo_margin = .06 -footer_margin = .05 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = logo_margin * height - f = footer_margin * height - p = padding * min (width, height) - p2 = 2 * p - - cr.set_source_rgb (0xeb/255., 0xd7/255., 0xbb/255.) - cr.paint () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgb (0x03/255., 0x40/255., 0x79/255.) - renderer.put_text ("OpenPrinting Summit, Montréal, September 24, 2007", height=f-p2, valign=-1) - - # Background image - cr.move_to (width / 2., height / 2.) - renderer.put_image ("Metal_movable_type.jpg", height = height, width = width) - - # Red Hat/cairo logos at the top - cr.move_to (p, p) - renderer.put_image ("redhat.svg", height = l-p2, valign=+1, halign=+1) - - cr.move_to (width-p, p) - renderer.put_image ("cairo.svg", height = l-p2, valign=+1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (0, 0, 0) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - cr.set_source_rgba (1, 1, 1, .9) - cr.paint () - - cr.set_source_rgb (0, 0, 0) diff --git a/turkey-flag.svg b/turkey-flag.svg deleted file mode 100644 index b6f303e..0000000 --- a/turkey-flag.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/turkey/behdad.svg b/turkey/behdad.svg new file mode 100644 index 0000000..8000f9f --- /dev/null +++ b/turkey/behdad.svg @@ -0,0 +1,114 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/turkey/berlin.jpg b/turkey/berlin.jpg new file mode 100644 index 0000000..25d1fd2 Binary files /dev/null and b/turkey/berlin.jpg differ diff --git a/turkey/gnome-ar.png b/turkey/gnome-ar.png new file mode 100644 index 0000000..588afac Binary files /dev/null and b/turkey/gnome-ar.png differ diff --git a/turkey/gnome-is-people.png b/turkey/gnome-is-people.png new file mode 100644 index 0000000..342b4f5 Binary files /dev/null and b/turkey/gnome-is-people.png differ diff --git a/turkey/gnome-white.svg b/turkey/gnome-white.svg new file mode 100644 index 0000000..0895f53 --- /dev/null +++ b/turkey/gnome-white.svg @@ -0,0 +1,93 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + TM + diff --git a/turkey/n810.jpg b/turkey/n810.jpg new file mode 100644 index 0000000..8547d8a Binary files /dev/null and b/turkey/n810.jpg differ diff --git a/turkey/olpc.jpg b/turkey/olpc.jpg new file mode 100644 index 0000000..88dd948 Binary files /dev/null and b/turkey/olpc.jpg differ diff --git a/turkey/openmoko.jpg b/turkey/openmoko.jpg new file mode 100644 index 0000000..19383ee Binary files /dev/null and b/turkey/openmoko.jpg differ diff --git a/turkey/screenshot-gnome-desktop.png b/turkey/screenshot-gnome-desktop.png new file mode 100644 index 0000000..d406151 Binary files /dev/null and b/turkey/screenshot-gnome-desktop.png differ diff --git a/turkey/slippy.py b/turkey/slippy.py new file mode 120000 index 0000000..8eb5363 --- /dev/null +++ b/turkey/slippy.py @@ -0,0 +1 @@ +../slippy.py \ No newline at end of file diff --git a/turkey/turkey-flag.svg b/turkey/turkey-flag.svg new file mode 100644 index 0000000..b6f303e --- /dev/null +++ b/turkey/turkey-flag.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/turkey/turkey_slides.py b/turkey/turkey_slides.py new file mode 100755 index 0000000..d853bfb --- /dev/null +++ b/turkey/turkey_slides.py @@ -0,0 +1,220 @@ +#!/usr/bin/python +# -*- coding:utf8 -*- + +# Copyright 2007,2009 Behdad Esfahbod + +# 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[:0] = [(f, data, width, height)] + 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 +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_behdad(f, data=None): + return slide_who (f, behdad, data=data) +def slide_image (f, height=650, data=None): + @slide_noone + def image_func (r): + r.move_to (400, 300) + r.put_image (f, height=height) + #r.set_allocation (000, 0, 800, 600) + yield "" + +# +# Slides start here +# + +@slide_noone +def title_slide (r): + r.move_to (800, 100) + r.put_text ( +"""GNOME\nand\nLiving a Happy Life""", +width=800, valign=1, halign=-1) + + r.move_to (0, 450) + r.put_text ("""Behdad Esfahbod\nbehdad@behdad.org""", + desc="20", halign=1, valign=-1) + +who (behdad) + +def list_slide (l, data=None): + def s (r): + return '\n'.join (l) + #yield l[0] + #for i in l[1:]: + # yield '\n'+i + s.__name__ = l[0] + slide (s, data) + +list_slide ([ + "Organization", + "• Who am I?", + "• What is GNOME?", + "• What can GNOME do for you?", + "• What can you do for GNOME?", + "• Why should you join GNOME?", + ], data={'align': pango.ALIGN_LEFT}) + + + +slide_noone("Who am I?") + +slide("Born in 1982\nin Sari, Iran") +slide("Math?\nPhysics?\nComputers?") +slide ("IOI'99, Antalya\nIOI'2000, Beijing") +slide("Sharif\nUniversity of\nTechnology") +slide("FarsiWeb") +slide("Free\nas in\nFreedom") +slide("KDE\nor\nGNOME") +slide("University\nof\nToronto") +slide("First\nLaptop") +slide("P=NP?") +slide("Performance\nPatches") +slide("System\nSoftware") +slide("Summer\nof Code") +slide("PhD?") +slide("Red Hat") +slide("Board of\nDirectors") +slide("MBA!") + + + +slide_noone("What is\nGNOME?") + +slide("GNOME\nis\nPeople") +slide_image("gnome-is-people.png") +slide("GNOME\nis the\nFree Desktop") +slide_image("screenshot-gnome-desktop.png", height=500) +slide("GNOME is\nInternationalized\nand Localized") +slide_image("gnome-ar.png") +slide("GNOME\nis a\nPlatform") +slide("GNOME\nMobile") +@slide_noone +def mobile_image_func (r): + r.set_source_rgb (1, 1, 1) + r.paint () + r.move_to (200, 400) + r.put_image ("olpc.jpg", height=300) + r.move_to (600, 400) + r.put_image ("n810.jpg", height=300) + r.move_to (380, 150) + r.put_image ("openmoko.jpg", height=300) + #r.set_allocation (000, 0, 800, 600) + yield "" + + + +slide_noone("What can GNOME\ndo for you?") + +slide("Learning\nopportunities") +list_slide ([ + "• Reading Code", + "• Code Review", + "• Mentorship", + "• ...", + ], data={'align': pango.ALIGN_LEFT}) + +slide("Internship\nopportunities") +list_slide ([ + "• Google Summer of Code", + "• GNOME Outreach Program", + "• Individual Companies", + "• ...", + ], data={'align': pango.ALIGN_LEFT}) + +slide("Employment\nopportunities") +list_slide ([ + "• Red Hat", + "• Novell", + "• Canonical", + "• Sun", + "• Nokia", + "• Google", + "• ...", + ], data={'align': pango.ALIGN_LEFT}) + +slide("Entrepreneurship\nopportunities") +list_slide ([ + "• CodeThink", + "• Collabora", + "• Fluendo", + "• Igalia", + "• Imendio", + "• Opened Hand *", + "• Openismus", + "• ...", + ], data={'align': pango.ALIGN_LEFT}) + + + +slide_noone("What can you\ndo for GNOME?") +slide("Testing") +slide("Translation") +slide("Usability") +slide("Bug Fixing") +slide("Development") +slide("Web\nDevelopment") +slide("Artistic\nContent") +slide("Marketing") +slide("Journalism") + + + +slide_noone("Why should you\njoin GNOME?") +slide("Cool\nPeople") +slide_image("berlin.jpg") +slide("Helping\nPeople") +slide("Recognition") +slide("Satisfaction") +slide("Living\nHappily") +slide_noone("http://live.gnome.org/JoinGnome") + +if __name__ == "__main__": + import slippy + import turkey_theme + import sys + slippy.main (slides, turkey_theme) + #slippy.main ("turkey_slides.py", "turkey_theme.py") + sys.exit (0) + diff --git a/turkey/turkey_theme.py b/turkey/turkey_theme.py new file mode 100644 index 0000000..33028d9 --- /dev/null +++ b/turkey/turkey_theme.py @@ -0,0 +1,133 @@ +# vim: set fileencoding=utf-8 : +# Written by Behdad Esfahbod, 2007,2009 +# Not copyrighted, in public domain. + +# A theme file should define two functions: +# +# - prepare_page(renderer): should draw any background and return a tuple of +# x,y,w,h that is the area to use for slide canvas. +# +# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the +# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the +# actual extents that the slide will consume. Data will be the user-data +# dictionary from the slide. +# +# 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 and +# put_image. See their pydocs. + +import cairo + +side_margin = .07 +logo_margin = .06 +footer_margin = .05 +padding = .005 +bubble_rad = .25 + +def bubble (cr, x0, y0, x, y, w, h): + + r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) + + p = r / 7. + x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p + + x1, y1, x2, y2 = x, y, x + w, y + h + + cr.move_to (x1+r, y1) + cr.line_to (x2-r, y1) + cr.curve_to (x2, y1, x2, y1, x2, y1+r) + cr.line_to (x2, y2-r) + cr.curve_to (x2, y2, x2, y2, x2-r, y2) + cr.line_to (x1+r, y2) + cr.curve_to (x1, y2, x1, y2, x1, y2-r) + cr.line_to (x1, y1+r) + cr.curve_to (x1, y1, x1, y1, x1+r, y1) + cr.close_path () + + xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) + cr.move_to (xc+r, yc) + cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) + cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) + + +def prepare_page (renderer): + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + l = logo_margin * height + f = footer_margin * height + p = padding * min (width, height) + p2 = 2 * p + + cr.set_source_rgb (227/255., 10/255., 23/255.) + cr.paint () + + cr.move_to (.5 * width, height-p2) + cr.set_source_rgba (1, 1, 1) + renderer.put_text ("Turkey, Feb 2009", height=f-p2, valign=-1) + + cr.move_to (p, p) + renderer.put_image ("gnome-white.svg", height = l-p2, valign=+1, halign=+1) + + cr.move_to (width-p, p) + renderer.put_image ("turkey-flag.svg", height = l-p2, valign=+1, halign=-1) + + # Cartoon icons for speakers + cr.move_to (p, height-p) + renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) + + # Compute rectangle available for slide content + w = width - s - s - p * 2 + x = s + p + h = height - l - f - p * 2 + y = l + p + + # Adjust for bubble padding. the 8 comes from bezier calculations + d = min (w, h) * bubble_rad / 8. + x, y, w, h = x + d, y + d, w - d*2, h - d*2 + + return x, y, w, h + +def draw_bubble (renderer, x, y, w, h, data=None): + # Fancy speech bubble! + cr = renderer.cr + width = renderer.width + height = renderer.height + + s = side_margin * width + p = padding * min (width, height) + + cr.save() + x, y = cr.user_to_device (x, y) + w, h = cr.user_to_device_distance (w, h) + cr.identity_matrix () + + who = data.get ('who', None) + if not who: + xc, yc = x + w*.5, y + h*.5 + elif who < 0: + xc, yc = s * .9, height - .7 * s + else: + xc, yc = width - s * .9, height - .7 * s + + bubble (cr, xc, yc, x, y, w, h) + cr.rectangle (width, 0, -width, height) + cr.clip () + + a = .3 + + bubble (cr, xc, yc, x, y, w, h) + cr.set_source_rgb (227/255.*a, 10/255.*a, 23/255.*a) + cr.set_line_width (p) + cr.set_miter_limit (20) + cr.stroke_preserve () + + cr.restore () + + cr.clip () + cr.set_source_rgba (1, 1, 1, .9) + cr.paint () + + cr.set_source_rgb (227/255.*a, 10/255.*a, 23/255.*a) diff --git a/turkey_slides.py b/turkey_slides.py deleted file mode 100755 index d853bfb..0000000 --- a/turkey_slides.py +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf8 -*- - -# Copyright 2007,2009 Behdad Esfahbod - -# 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[:0] = [(f, data, width, height)] - 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 -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_behdad(f, data=None): - return slide_who (f, behdad, data=data) -def slide_image (f, height=650, data=None): - @slide_noone - def image_func (r): - r.move_to (400, 300) - r.put_image (f, height=height) - #r.set_allocation (000, 0, 800, 600) - yield "" - -# -# Slides start here -# - -@slide_noone -def title_slide (r): - r.move_to (800, 100) - r.put_text ( -"""GNOME\nand\nLiving a Happy Life""", -width=800, valign=1, halign=-1) - - r.move_to (0, 450) - r.put_text ("""Behdad Esfahbod\nbehdad@behdad.org""", - desc="20", halign=1, valign=-1) - -who (behdad) - -def list_slide (l, data=None): - def s (r): - return '\n'.join (l) - #yield l[0] - #for i in l[1:]: - # yield '\n'+i - s.__name__ = l[0] - slide (s, data) - -list_slide ([ - "Organization", - "• Who am I?", - "• What is GNOME?", - "• What can GNOME do for you?", - "• What can you do for GNOME?", - "• Why should you join GNOME?", - ], data={'align': pango.ALIGN_LEFT}) - - - -slide_noone("Who am I?") - -slide("Born in 1982\nin Sari, Iran") -slide("Math?\nPhysics?\nComputers?") -slide ("IOI'99, Antalya\nIOI'2000, Beijing") -slide("Sharif\nUniversity of\nTechnology") -slide("FarsiWeb") -slide("Free\nas in\nFreedom") -slide("KDE\nor\nGNOME") -slide("University\nof\nToronto") -slide("First\nLaptop") -slide("P=NP?") -slide("Performance\nPatches") -slide("System\nSoftware") -slide("Summer\nof Code") -slide("PhD?") -slide("Red Hat") -slide("Board of\nDirectors") -slide("MBA!") - - - -slide_noone("What is\nGNOME?") - -slide("GNOME\nis\nPeople") -slide_image("gnome-is-people.png") -slide("GNOME\nis the\nFree Desktop") -slide_image("screenshot-gnome-desktop.png", height=500) -slide("GNOME is\nInternationalized\nand Localized") -slide_image("gnome-ar.png") -slide("GNOME\nis a\nPlatform") -slide("GNOME\nMobile") -@slide_noone -def mobile_image_func (r): - r.set_source_rgb (1, 1, 1) - r.paint () - r.move_to (200, 400) - r.put_image ("olpc.jpg", height=300) - r.move_to (600, 400) - r.put_image ("n810.jpg", height=300) - r.move_to (380, 150) - r.put_image ("openmoko.jpg", height=300) - #r.set_allocation (000, 0, 800, 600) - yield "" - - - -slide_noone("What can GNOME\ndo for you?") - -slide("Learning\nopportunities") -list_slide ([ - "• Reading Code", - "• Code Review", - "• Mentorship", - "• ...", - ], data={'align': pango.ALIGN_LEFT}) - -slide("Internship\nopportunities") -list_slide ([ - "• Google Summer of Code", - "• GNOME Outreach Program", - "• Individual Companies", - "• ...", - ], data={'align': pango.ALIGN_LEFT}) - -slide("Employment\nopportunities") -list_slide ([ - "• Red Hat", - "• Novell", - "• Canonical", - "• Sun", - "• Nokia", - "• Google", - "• ...", - ], data={'align': pango.ALIGN_LEFT}) - -slide("Entrepreneurship\nopportunities") -list_slide ([ - "• CodeThink", - "• Collabora", - "• Fluendo", - "• Igalia", - "• Imendio", - "• Opened Hand *", - "• Openismus", - "• ...", - ], data={'align': pango.ALIGN_LEFT}) - - - -slide_noone("What can you\ndo for GNOME?") -slide("Testing") -slide("Translation") -slide("Usability") -slide("Bug Fixing") -slide("Development") -slide("Web\nDevelopment") -slide("Artistic\nContent") -slide("Marketing") -slide("Journalism") - - - -slide_noone("Why should you\njoin GNOME?") -slide("Cool\nPeople") -slide_image("berlin.jpg") -slide("Helping\nPeople") -slide("Recognition") -slide("Satisfaction") -slide("Living\nHappily") -slide_noone("http://live.gnome.org/JoinGnome") - -if __name__ == "__main__": - import slippy - import turkey_theme - import sys - slippy.main (slides, turkey_theme) - #slippy.main ("turkey_slides.py", "turkey_theme.py") - sys.exit (0) - diff --git a/turkey_theme.py b/turkey_theme.py deleted file mode 100644 index 33028d9..0000000 --- a/turkey_theme.py +++ /dev/null @@ -1,133 +0,0 @@ -# vim: set fileencoding=utf-8 : -# Written by Behdad Esfahbod, 2007,2009 -# Not copyrighted, in public domain. - -# A theme file should define two functions: -# -# - prepare_page(renderer): should draw any background and return a tuple of -# x,y,w,h that is the area to use for slide canvas. -# -# - draw_bubble(renderer, x, y, w, h, data=None): should setup canvas for the -# slide to run. Can draw a speaking-bubble for example. x,y,w,h is the -# actual extents that the slide will consume. Data will be the user-data -# dictionary from the slide. -# -# 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 and -# put_image. See their pydocs. - -import cairo - -side_margin = .07 -logo_margin = .06 -footer_margin = .05 -padding = .005 -bubble_rad = .25 - -def bubble (cr, x0, y0, x, y, w, h): - - r = min (w, h) * (bubble_rad / (1 - 2./8*bubble_rad)) - - p = r / 7. - x, y, w, h, r = x - p, y - p, w + 2*p, h + 2*p, r + p - - x1, y1, x2, y2 = x, y, x + w, y + h - - cr.move_to (x1+r, y1) - cr.line_to (x2-r, y1) - cr.curve_to (x2, y1, x2, y1, x2, y1+r) - cr.line_to (x2, y2-r) - cr.curve_to (x2, y2, x2, y2, x2-r, y2) - cr.line_to (x1+r, y2) - cr.curve_to (x1, y2, x1, y2, x1, y2-r) - cr.line_to (x1, y1+r) - cr.curve_to (x1, y1, x1, y1, x1+r, y1) - cr.close_path () - - xc, yc = .5 * (x1 + x2), .5 * (y1 + y2) - cr.move_to (xc+r, yc) - cr.curve_to (xc+r, y0, .5 * (xc+r+x0), (yc+y0*2)/3, x0, y0) - cr.curve_to (.5 * (xc-r+x0), (yc+y0*2)/3, xc-r, y0, xc-r, yc) - - -def prepare_page (renderer): - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - l = logo_margin * height - f = footer_margin * height - p = padding * min (width, height) - p2 = 2 * p - - cr.set_source_rgb (227/255., 10/255., 23/255.) - cr.paint () - - cr.move_to (.5 * width, height-p2) - cr.set_source_rgba (1, 1, 1) - renderer.put_text ("Turkey, Feb 2009", height=f-p2, valign=-1) - - cr.move_to (p, p) - renderer.put_image ("gnome-white.svg", height = l-p2, valign=+1, halign=+1) - - cr.move_to (width-p, p) - renderer.put_image ("turkey-flag.svg", height = l-p2, valign=+1, halign=-1) - - # Cartoon icons for speakers - cr.move_to (p, height-p) - renderer.put_image ("behdad.svg", width = s-p2, valign=-1, halign=+1) - - # Compute rectangle available for slide content - w = width - s - s - p * 2 - x = s + p - h = height - l - f - p * 2 - y = l + p - - # Adjust for bubble padding. the 8 comes from bezier calculations - d = min (w, h) * bubble_rad / 8. - x, y, w, h = x + d, y + d, w - d*2, h - d*2 - - return x, y, w, h - -def draw_bubble (renderer, x, y, w, h, data=None): - # Fancy speech bubble! - cr = renderer.cr - width = renderer.width - height = renderer.height - - s = side_margin * width - p = padding * min (width, height) - - cr.save() - x, y = cr.user_to_device (x, y) - w, h = cr.user_to_device_distance (w, h) - cr.identity_matrix () - - who = data.get ('who', None) - if not who: - xc, yc = x + w*.5, y + h*.5 - elif who < 0: - xc, yc = s * .9, height - .7 * s - else: - xc, yc = width - s * .9, height - .7 * s - - bubble (cr, xc, yc, x, y, w, h) - cr.rectangle (width, 0, -width, height) - cr.clip () - - a = .3 - - bubble (cr, xc, yc, x, y, w, h) - cr.set_source_rgb (227/255.*a, 10/255.*a, 23/255.*a) - cr.set_line_width (p) - cr.set_miter_limit (20) - cr.stroke_preserve () - - cr.restore () - - cr.clip () - cr.set_source_rgba (1, 1, 1, .9) - cr.paint () - - cr.set_source_rgb (227/255.*a, 10/255.*a, 23/255.*a) -- cgit v1.2.3