summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorSteve Chaplin <stevech1097@yahoo.com.au>2009-08-06 21:01:59 +0800
committerSteve Chaplin <stevech1097@yahoo.com.au>2009-08-06 21:01:59 +0800
commitca09d078984c5310f5052477da1ae0f65d017a92 (patch)
tree5deefac73e729e373809bdd8f462752dc7747da1 /examples
downloadpy2cairo-ca09d078984c5310f5052477da1ae0f65d017a92.tar.gz
Initial commit
Diffstat (limited to 'examples')
-rw-r--r--examples/.gitignore7
-rw-r--r--examples/Makefile.am40
-rwxr-xr-xexamples/cairo_snippets/c_to_python.py35
-rw-r--r--examples/cairo_snippets/snippets/.gitignore5
-rwxr-xr-xexamples/cairo_snippets/snippets/__init__.py12
-rwxr-xr-xexamples/cairo_snippets/snippets/arc.py21
-rwxr-xr-xexamples/cairo_snippets/snippets/arc_negative.py22
-rwxr-xr-xexamples/cairo_snippets/snippets/clip.py13
-rwxr-xr-xexamples/cairo_snippets/snippets/clip_image.py13
-rwxr-xr-xexamples/cairo_snippets/snippets/curve_rectangle.py53
-rwxr-xr-xexamples/cairo_snippets/snippets/curve_to.py17
-rwxr-xr-xexamples/cairo_snippets/snippets/ellipse.py33
-rwxr-xr-xexamples/cairo_snippets/snippets/fill_and_stroke.py12
-rwxr-xr-xexamples/cairo_snippets/snippets/fill_and_stroke2.py18
-rwxr-xr-xexamples/cairo_snippets/snippets/glyph_path.py21
-rwxr-xr-xexamples/cairo_snippets/snippets/gradient.py16
-rwxr-xr-xexamples/cairo_snippets/snippets/gradient_mask.py12
-rwxr-xr-xexamples/cairo_snippets/snippets/group.py16
-rwxr-xr-xexamples/cairo_snippets/snippets/image.py14
-rwxr-xr-xexamples/cairo_snippets/snippets/imagepattern.py23
-rwxr-xr-xexamples/cairo_snippets/snippets/path.py7
-rwxr-xr-xexamples/cairo_snippets/snippets/set_line_cap.py19
-rwxr-xr-xexamples/cairo_snippets/snippets/set_line_join.py21
-rwxr-xr-xexamples/cairo_snippets/snippets/show_glyphs.py15
-rwxr-xr-xexamples/cairo_snippets/snippets/text.py22
-rwxr-xr-xexamples/cairo_snippets/snippets/text_align_center.py26
-rwxr-xr-xexamples/cairo_snippets/snippets/text_extents.py27
-rwxr-xr-xexamples/cairo_snippets/snippets_gtk.py140
-rwxr-xr-xexamples/cairo_snippets/snippets_pdf.py56
-rwxr-xr-xexamples/cairo_snippets/snippets_png.py52
-rwxr-xr-xexamples/cairo_snippets/snippets_ps.py56
-rwxr-xr-xexamples/cairo_snippets/snippets_svg.py53
-rwxr-xr-xexamples/gradient.py33
-rwxr-xr-xexamples/gtk/cairo-demo.py121
-rwxr-xr-xexamples/gtk/cairo-knockout.py128
-rwxr-xr-xexamples/gtk/hangman.py257
-rwxr-xr-xexamples/gtk/lsystem.py123
-rwxr-xr-xexamples/gtk/png_view.py35
-rwxr-xr-xexamples/gtk/text.py41
-rwxr-xr-xexamples/hering.py55
-rwxr-xr-xexamples/spiral.py36
-rwxr-xr-xexamples/warpedtext.py85
42 files changed, 1811 insertions, 0 deletions
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..f54b062
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+*.pdf
+*.pyc
+*.pyo
+*.png
+*.ps
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..a15a963
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,40 @@
+EXTRA_DIST = \
+ gradient.py \
+ hering.py \
+ spiral.py \
+ warpedtext.py \
+ cairo_snippets/snippets_gtk.py \
+ cairo_snippets/snippets_pdf.py \
+ cairo_snippets/snippets_png.py \
+ cairo_snippets/snippets_ps.py \
+ cairo_snippets/snippets_svg.py \
+ cairo_snippets/data/romedalen.png \
+ cairo_snippets/snippets/arc_negative.py \
+ cairo_snippets/snippets/arc.py \
+ cairo_snippets/snippets/clip_image.py \
+ cairo_snippets/snippets/clip.py \
+ cairo_snippets/snippets/curve_rectangle.py \
+ cairo_snippets/snippets/curve_to.py \
+ cairo_snippets/snippets/ellipse.py \
+ cairo_snippets/snippets/fill_and_stroke2.py \
+ cairo_snippets/snippets/fill_and_stroke.py \
+ cairo_snippets/snippets/glyph_path.py \
+ cairo_snippets/snippets/gradient.py \
+ cairo_snippets/snippets/gradient_mask.py \
+ cairo_snippets/snippets/group.py \
+ cairo_snippets/snippets/imagepattern.py \
+ cairo_snippets/snippets/image.py \
+ cairo_snippets/snippets/__init__.py \
+ cairo_snippets/snippets/path.py \
+ cairo_snippets/snippets/set_line_cap.py \
+ cairo_snippets/snippets/set_line_join.py \
+ cairo_snippets/snippets/show_glyphs.py \
+ cairo_snippets/snippets/text_align_center.py \
+ cairo_snippets/snippets/text_extents.py \
+ cairo_snippets/snippets/text.py \
+ gtk/cairo-demo.py \
+ gtk/cairo-knockout.py \
+ gtk/hangman.py \
+ gtk/lsystem.py \
+ gtk/png_view.py \
+ gtk/text.py
diff --git a/examples/cairo_snippets/c_to_python.py b/examples/cairo_snippets/c_to_python.py
new file mode 100755
index 0000000..c01ebe5
--- /dev/null
+++ b/examples/cairo_snippets/c_to_python.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+"""
+translate C <snippet>.cairo to Python <snippet>.py
+
+; -> ''
+cairo_ -> cr.
+'(cr, ' -> ( but not snippet_normalize (cr, width, height)
+(cr) -> ()
+/* -> #/*
+CAIRO_ -> cairo.
+"""
+
+import sys
+
+
+if len(sys.argv) != 2 or not sys.argv[1].endswith('.cairo'):
+ raise SystemExit('usage: c_to_python.py <file>.cairo')
+
+filename_in = sys.argv[1]
+filename_out = filename_in.replace('.cairo', '.py')
+
+file_in = file(filename_in)
+file_out = file(filename_out, 'w')
+
+for line in file_in:
+ line = line.replace(';', '') # should be ';' and whitespace to EOL only -> \n
+ if not line.startswith('snippet_'):
+ line = line.replace('cairo_', 'cr.')
+ line = line.replace('(cr, ', '(')
+ line = line.replace('(cr)', '()')
+ line = line.replace('/*', '#/*')
+ line = line.replace(' ', '')
+ line = line.replace('CAIRO_', 'cairo.')
+
+ file_out.write (line)
diff --git a/examples/cairo_snippets/snippets/.gitignore b/examples/cairo_snippets/snippets/.gitignore
new file mode 100644
index 0000000..6be9629
--- /dev/null
+++ b/examples/cairo_snippets/snippets/.gitignore
@@ -0,0 +1,5 @@
+*.pdf
+*.png
+*.ps
+*.pyc
+*.svg
diff --git a/examples/cairo_snippets/snippets/__init__.py b/examples/cairo_snippets/snippets/__init__.py
new file mode 100755
index 0000000..70b4813
--- /dev/null
+++ b/examples/cairo_snippets/snippets/__init__.py
@@ -0,0 +1,12 @@
+# snippet list generation
+import os
+
+# list of snippet files
+snip_list = [x[:-3] for x in os.listdir (os.path.dirname (__file__))
+ if not x.startswith('_') and x.endswith('.py')]
+snip_list.sort()
+
+# function used by some or all snippets
+def snippet_normalize (ctx, width, height):
+ ctx.scale (width, height)
+ ctx.set_line_width (0.04)
diff --git a/examples/cairo_snippets/snippets/arc.py b/examples/cairo_snippets/snippets/arc.py
new file mode 100755
index 0000000..b4e6e5d
--- /dev/null
+++ b/examples/cairo_snippets/snippets/arc.py
@@ -0,0 +1,21 @@
+xc = 0.5
+yc = 0.5
+radius = 0.4
+angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */
+angle2 = 180.0 * (M_PI/180.0) #/* in radians */
+
+snippet_normalize (cr, width, height)
+
+cr.arc (xc, yc, radius, angle1, angle2)
+cr.stroke ()
+
+#/* draw helping lines */
+cr.set_source_rgba (1,0.2,0.2,0.6)
+cr.arc (xc, yc, 0.05, 0, 2*M_PI)
+cr.fill ()
+cr.set_line_width (0.03)
+cr.arc (xc, yc, radius, angle1, angle1)
+cr.line_to (xc, yc)
+cr.arc (xc, yc, radius, angle2, angle2)
+cr.line_to (xc, yc)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/arc_negative.py b/examples/cairo_snippets/snippets/arc_negative.py
new file mode 100755
index 0000000..ca6a85d
--- /dev/null
+++ b/examples/cairo_snippets/snippets/arc_negative.py
@@ -0,0 +1,22 @@
+xc = 0.5
+yc = 0.5
+radius = 0.4
+angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */
+angle2 = 180.0 * (M_PI/180.0) #/* in radians */
+
+snippet_normalize (cr, width, height)
+
+cr.arc_negative (xc, yc, radius, angle1, angle2)
+cr.stroke ()
+
+#/* draw helping lines */
+cr.set_source_rgba (1,0.2,0.2,0.6)
+cr.arc (xc, yc, 0.05, 0, 2*M_PI)
+cr.fill ()
+cr.set_line_width (0.03)
+cr.arc (xc, yc, radius, angle1, angle1)
+cr.line_to (xc, yc)
+cr.arc (xc, yc, radius, angle2, angle2)
+cr.line_to (xc, yc)
+cr.stroke ()
+#cr.stroke (10)
diff --git a/examples/cairo_snippets/snippets/clip.py b/examples/cairo_snippets/snippets/clip.py
new file mode 100755
index 0000000..8456235
--- /dev/null
+++ b/examples/cairo_snippets/snippets/clip.py
@@ -0,0 +1,13 @@
+snippet_normalize (cr, width, height)
+
+cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI)
+cr.clip ()
+
+cr.rectangle (0, 0, 1, 1)
+cr.fill ()
+cr.set_source_rgb (0, 1, 0)
+cr.move_to (0, 0)
+cr.line_to (1, 1)
+cr.move_to (1, 0)
+cr.line_to (0, 1)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/clip_image.py b/examples/cairo_snippets/snippets/clip_image.py
new file mode 100755
index 0000000..39a84ab
--- /dev/null
+++ b/examples/cairo_snippets/snippets/clip_image.py
@@ -0,0 +1,13 @@
+snippet_normalize (cr, width, height)
+
+cr.arc (0.5, 0.5, 0.3, 0, 2*M_PI)
+cr.clip ()
+
+image = cairo.ImageSurface.create_from_png ("data/romedalen.png")
+w = image.get_width()
+h = image.get_height()
+
+cr.scale (1.0/w, 1.0/h)
+
+cr.set_source_surface (image, 0, 0)
+cr.paint ()
diff --git a/examples/cairo_snippets/snippets/curve_rectangle.py b/examples/cairo_snippets/snippets/curve_rectangle.py
new file mode 100755
index 0000000..3fb3c4a
--- /dev/null
+++ b/examples/cairo_snippets/snippets/curve_rectangle.py
@@ -0,0 +1,53 @@
+#/* a custom shape, that could be wrapped in a function */
+x0 = 0.1 #/*< parameters like cairo_rectangle */
+y0 = 0.1
+rect_width = 0.8
+rect_height = 0.8
+radius = 0.4 #/*< and an approximate curvature radius */
+
+snippet_normalize (cr, width, height)
+
+x1=x0+rect_width
+y1=y0+rect_height
+#if (!rect_width || !rect_height)
+# return
+if rect_width/2<radius:
+ if rect_height/2<radius:
+ cr.move_to (x0, (y0 + y1)/2)
+ cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
+ cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
+ cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
+ cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
+ else:
+ cr.move_to (x0, y0 + radius)
+ cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
+ cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
+ cr.line_to (x1 , y1 - radius)
+ cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
+ cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+
+else:
+ if rect_height/2<radius:
+ cr.move_to (x0, (y0 + y1)/2)
+ cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
+ cr.line_to (x1 - radius, y0)
+ cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
+ cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
+ cr.line_to (x0 + radius, y1)
+ cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
+ else:
+ cr.move_to (x0, y0 + radius)
+ cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
+ cr.line_to (x1 - radius, y0)
+ cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
+ cr.line_to (x1 , y1 - radius)
+ cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
+ cr.line_to (x0 + radius, y1)
+ cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+
+cr.close_path ()
+
+cr.set_source_rgb (0.5,0.5,1)
+cr.fill_preserve ()
+cr.set_source_rgba (0.5,0,0,0.5)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/curve_to.py b/examples/cairo_snippets/snippets/curve_to.py
new file mode 100755
index 0000000..59e3b00
--- /dev/null
+++ b/examples/cairo_snippets/snippets/curve_to.py
@@ -0,0 +1,17 @@
+x, y = 0.1, 0.5
+x1, y1 = 0.4, 0.9
+x2, y2 = 0.6, 0.1
+x3, y3 = 0.9, 0.5
+
+snippet_normalize (cr, width, height)
+
+cr.move_to (x, y)
+cr.curve_to (x1, y1, x2, y2, x3, y3)
+
+cr.stroke ()
+
+cr.set_source_rgba (1,0.2,0.2,0.6)
+cr.set_line_width (0.03)
+cr.move_to (x,y); cr.line_to (x1,y1)
+cr.move_to (x2,y2); cr.line_to (x3,y3)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/ellipse.py b/examples/cairo_snippets/snippets/ellipse.py
new file mode 100755
index 0000000..9afd4f2
--- /dev/null
+++ b/examples/cairo_snippets/snippets/ellipse.py
@@ -0,0 +1,33 @@
+snippet_normalize(cr, width, height)
+
+def path_ellipse(cr, x, y, width, height, angle=0):
+ """
+ x - center x
+ y - center y
+ width - width of ellipse (in x direction when angle=0)
+ height - height of ellipse (in y direction when angle=0)
+ angle - angle in radians to rotate, clockwise
+ """
+ cr.save()
+ cr.translate(x, y)
+ cr.rotate(angle)
+ cr.scale(width / 2.0, height / 2.0)
+ cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * M_PI)
+ cr.restore()
+
+
+path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, M_PI/4.0)
+
+# fill
+cr.set_source_rgba(1,0,0,1)
+cr.fill_preserve()
+
+# stroke
+# reset identity matrix so line_width is a constant
+# width in device-space, not user-space
+cr.save()
+cr.identity_matrix()
+cr.set_source_rgba(0,0,0,1)
+cr.set_line_width(3)
+cr.stroke()
+cr.restore()
diff --git a/examples/cairo_snippets/snippets/fill_and_stroke.py b/examples/cairo_snippets/snippets/fill_and_stroke.py
new file mode 100755
index 0000000..6d66192
--- /dev/null
+++ b/examples/cairo_snippets/snippets/fill_and_stroke.py
@@ -0,0 +1,12 @@
+snippet_normalize (cr, width, height)
+
+cr.move_to (0.5, 0.1)
+cr.line_to (0.9, 0.9)
+cr.rel_line_to (-0.4, 0.0)
+cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+cr.close_path()
+
+cr.set_source_rgb (0, 0, 1)
+cr.fill_preserve ()
+cr.set_source_rgb (0, 0, 0)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/fill_and_stroke2.py b/examples/cairo_snippets/snippets/fill_and_stroke2.py
new file mode 100755
index 0000000..c520630
--- /dev/null
+++ b/examples/cairo_snippets/snippets/fill_and_stroke2.py
@@ -0,0 +1,18 @@
+snippet_normalize (cr, width, height)
+
+cr.move_to (0.5, 0.1)
+cr.line_to (0.9, 0.9)
+cr.rel_line_to (-0.4, 0.0)
+cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+cr.close_path ()
+
+cr.move_to (0.25, 0.1)
+cr.rel_line_to (0.2, 0.2)
+cr.rel_line_to (-0.2, 0.2)
+cr.rel_line_to (-0.2, -0.2)
+cr.close_path ()
+
+cr.set_source_rgb (0, 0, 1)
+cr.fill_preserve ()
+cr.set_source_rgb (0, 0, 0)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/glyph_path.py b/examples/cairo_snippets/snippets/glyph_path.py
new file mode 100755
index 0000000..2b73193
--- /dev/null
+++ b/examples/cairo_snippets/snippets/glyph_path.py
@@ -0,0 +1,21 @@
+snippet_normalize (cr, width, height)
+
+cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+# draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner
+cr.set_font_size (0.16)
+
+glyphs = []
+index = 20
+for y in range(5):
+ for x in range(5):
+ glyphs.append ((index, x/5.0 + 0.02, y/5.0 + 0.16))
+ index += 1
+
+cr.glyph_path (glyphs)
+cr.set_source_rgb (0.5,0.5,1.0)
+cr.fill_preserve ()
+cr.set_source_rgb (0,0,0)
+cr.set_line_width (0.005)
+cr.stroke ()
+
diff --git a/examples/cairo_snippets/snippets/gradient.py b/examples/cairo_snippets/snippets/gradient.py
new file mode 100755
index 0000000..22f0658
--- /dev/null
+++ b/examples/cairo_snippets/snippets/gradient.py
@@ -0,0 +1,16 @@
+snippet_normalize (cr, width, height)
+
+pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
+pat.add_color_stop_rgba (1, 0, 0, 0, 1)
+pat.add_color_stop_rgba (0, 1, 1, 1, 1)
+cr.rectangle (0,0,1,1)
+cr.set_source (pat)
+cr.fill ()
+
+pat = cairo.RadialGradient (0.45, 0.4, 0.1,
+ 0.4, 0.4, 0.5)
+pat.add_color_stop_rgba (0, 1, 1, 1, 1)
+pat.add_color_stop_rgba (1, 0, 0, 0, 1)
+cr.set_source (pat)
+cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI)
+cr.fill ()
diff --git a/examples/cairo_snippets/snippets/gradient_mask.py b/examples/cairo_snippets/snippets/gradient_mask.py
new file mode 100755
index 0000000..4a0eba4
--- /dev/null
+++ b/examples/cairo_snippets/snippets/gradient_mask.py
@@ -0,0 +1,12 @@
+snippet_normalize (cr, width, height)
+
+pattern = cairo.LinearGradient (0, 0, 1, 1)
+pattern.add_color_stop_rgb (0, 0, 0.3, 0.8)
+pattern.add_color_stop_rgb (1, 0, 0.8, 0.3)
+
+mask = cairo.RadialGradient (0.5, 0.5, 0.25, 0.5, 0.5, 0.5)
+mask.add_color_stop_rgba (0, 0, 0, 0, 1)
+mask.add_color_stop_rgba (0.5, 0, 0, 0, 0)
+
+cr.set_source (pattern)
+cr.mask (mask)
diff --git a/examples/cairo_snippets/snippets/group.py b/examples/cairo_snippets/snippets/group.py
new file mode 100755
index 0000000..a787f4d
--- /dev/null
+++ b/examples/cairo_snippets/snippets/group.py
@@ -0,0 +1,16 @@
+# demo/test for group functions
+snippet_normalize (cr, width, height)
+
+cr.rectangle (0.1, 0.1, 0.6, 0.6)
+cr.set_line_width (0.03)
+cr.set_source_rgb (0.8, 0.8, 0.8)
+cr.fill()
+
+cr.push_group()
+cr.rectangle (0.3, 0.3, 0.6, 0.6)
+cr.set_source (cairo.SolidPattern (1, 0, 0))
+cr.fill_preserve()
+cr.set_source (cairo.SolidPattern (0, 0, 0))
+cr.stroke ()
+cr.pop_group_to_source()
+cr.paint_with_alpha (0.5)
diff --git a/examples/cairo_snippets/snippets/image.py b/examples/cairo_snippets/snippets/image.py
new file mode 100755
index 0000000..ccadc4f
--- /dev/null
+++ b/examples/cairo_snippets/snippets/image.py
@@ -0,0 +1,14 @@
+snippet_normalize (cr, width, height)
+
+image = cairo.ImageSurface.create_from_png ("data/romedalen.png")
+w = image.get_width()
+h = image.get_height()
+
+cr.translate (0.5, 0.5)
+cr.rotate (45* M_PI/180)
+cr.scale (1.0/w, 1.0/h)
+cr.translate (-0.5*w, -0.5*h)
+
+cr.set_source_surface (image, 0, 0)
+cr.paint ()
+
diff --git a/examples/cairo_snippets/snippets/imagepattern.py b/examples/cairo_snippets/snippets/imagepattern.py
new file mode 100755
index 0000000..5d07c07
--- /dev/null
+++ b/examples/cairo_snippets/snippets/imagepattern.py
@@ -0,0 +1,23 @@
+import math
+
+snippet_normalize (cr, width, height)
+
+image = cairo.ImageSurface.create_from_png ("data/romedalen.png")
+w = image.get_width()
+h = image.get_height()
+
+pattern = cairo.SurfacePattern (image)
+pattern.set_extend (cairo.EXTEND_REPEAT)
+
+cr.translate (0.5, 0.5)
+cr.rotate (M_PI / 4)
+cr.scale (1 / math.sqrt (2), 1 / math.sqrt (2))
+cr.translate (- 0.5, - 0.5)
+
+matrix = cairo.Matrix(xx=w * 5, yy=h * 5)
+pattern.set_matrix (matrix)
+
+cr.set_source (pattern)
+
+cr.rectangle (0, 0, 1.0, 1.0)
+cr.fill ()
diff --git a/examples/cairo_snippets/snippets/path.py b/examples/cairo_snippets/snippets/path.py
new file mode 100755
index 0000000..cce8aec
--- /dev/null
+++ b/examples/cairo_snippets/snippets/path.py
@@ -0,0 +1,7 @@
+snippet_normalize (cr, width, height)
+cr.move_to (0.5, 0.1)
+cr.line_to (0.9, 0.9)
+cr.rel_line_to (-0.4, 0.0)
+cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/set_line_cap.py b/examples/cairo_snippets/snippets/set_line_cap.py
new file mode 100755
index 0000000..6de1fae
--- /dev/null
+++ b/examples/cairo_snippets/snippets/set_line_cap.py
@@ -0,0 +1,19 @@
+snippet_normalize (cr, width, height)
+cr.set_line_width (0.12)
+cr.set_line_cap (cairo.LINE_CAP_BUTT) #/* default */
+cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8)
+cr.stroke ()
+cr.set_line_cap (cairo.LINE_CAP_ROUND)
+cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8)
+cr.stroke ()
+cr.set_line_cap (cairo.LINE_CAP_SQUARE)
+cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8)
+cr.stroke ()
+
+#/* draw helping lines */
+cr.set_source_rgb (1,0.2,0.2)
+cr.set_line_width (0.01)
+cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8)
+cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8)
+cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8)
+cr.stroke ()
diff --git a/examples/cairo_snippets/snippets/set_line_join.py b/examples/cairo_snippets/snippets/set_line_join.py
new file mode 100755
index 0000000..b2e1919
--- /dev/null
+++ b/examples/cairo_snippets/snippets/set_line_join.py
@@ -0,0 +1,21 @@
+snippet_normalize (cr, width, height)
+cr.set_line_width (0.16)
+cr.move_to (0.3, 0.33)
+cr.rel_line_to (0.2, -0.2)
+cr.rel_line_to (0.2, 0.2)
+cr.set_line_join (cairo.LINE_JOIN_MITER) #/* default */
+cr.stroke ()
+
+cr.move_to (0.3, 0.63)
+cr.rel_line_to (0.2, -0.2)
+cr.rel_line_to (0.2, 0.2)
+cr.set_line_join (cairo.LINE_JOIN_BEVEL)
+cr.stroke ()
+
+cr.move_to (0.3, 0.93)
+cr.rel_line_to (0.2, -0.2)
+cr.rel_line_to (0.2, 0.2)
+cr.set_line_join (cairo.LINE_JOIN_ROUND)
+cr.stroke ()
+
+
diff --git a/examples/cairo_snippets/snippets/show_glyphs.py b/examples/cairo_snippets/snippets/show_glyphs.py
new file mode 100755
index 0000000..a41cf61
--- /dev/null
+++ b/examples/cairo_snippets/snippets/show_glyphs.py
@@ -0,0 +1,15 @@
+snippet_normalize (cr, width, height)
+
+cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+# draw 0.08 glyphs in 0.10 squares, at (0.01, 0.02) from left corner
+cr.set_font_size (0.08)
+
+glyphs = []
+index = 0
+for y in range(10):
+ for x in range(10):
+ glyphs.append ((index, x/10.0 + 0.01, y/10.0 + 0.08))
+ index += 1
+
+cr.show_glyphs (glyphs)
diff --git a/examples/cairo_snippets/snippets/text.py b/examples/cairo_snippets/snippets/text.py
new file mode 100755
index 0000000..1ba80e6
--- /dev/null
+++ b/examples/cairo_snippets/snippets/text.py
@@ -0,0 +1,22 @@
+snippet_normalize (cr, width, height)
+cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_BOLD)
+cr.set_font_size (0.35)
+
+cr.move_to (0.04, 0.53)
+cr.show_text ("Hello")
+
+cr.move_to (0.27, 0.65)
+cr.text_path ("void")
+cr.set_source_rgb (0.5,0.5,1)
+cr.fill_preserve ()
+cr.set_source_rgb (0,0,0)
+cr.set_line_width (0.01)
+cr.stroke ()
+
+#/* draw helping lines */
+cr.set_source_rgba (1,0.2,0.2, 0.6)
+cr.arc (0.04, 0.53, 0.02, 0, 2*M_PI)
+cr.arc (0.27, 0.65, 0.02, 0, 2*M_PI)
+cr.fill ()
+
diff --git a/examples/cairo_snippets/snippets/text_align_center.py b/examples/cairo_snippets/snippets/text_align_center.py
new file mode 100755
index 0000000..4bc3124
--- /dev/null
+++ b/examples/cairo_snippets/snippets/text_align_center.py
@@ -0,0 +1,26 @@
+utf8 = "cairo"
+
+snippet_normalize (cr, width, height)
+
+cr.select_font_face ("Sans",
+ cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+
+cr.set_font_size (0.2)
+x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8)
+x = 0.5-(width/2 + x_bearing)
+y = 0.5-(height/2 + y_bearing)
+
+cr.move_to (x, y)
+cr.show_text (utf8)
+
+#/* draw helping lines */
+cr.set_source_rgba (1,0.2,0.2,0.6)
+cr.arc (x, y, 0.05, 0, 2*M_PI)
+cr.fill ()
+cr.move_to (0.5, 0)
+cr.rel_line_to (0, 1)
+cr.move_to (0, 0.5)
+cr.rel_line_to (1, 0)
+cr.stroke ()
+
diff --git a/examples/cairo_snippets/snippets/text_extents.py b/examples/cairo_snippets/snippets/text_extents.py
new file mode 100755
index 0000000..890fb88
--- /dev/null
+++ b/examples/cairo_snippets/snippets/text_extents.py
@@ -0,0 +1,27 @@
+utf8 = "cairo"
+
+snippet_normalize (cr, width, height)
+
+cr.select_font_face ("Sans",
+ cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+
+cr.set_font_size (0.4)
+x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8)
+
+x=0.1
+y=0.6
+
+cr.move_to (x,y)
+cr.show_text (utf8)
+
+#/* draw helping lines */
+cr.set_source_rgba (1,0.2,0.2,0.6)
+cr.arc (x, y, 0.05, 0, 2*M_PI)
+cr.fill ()
+cr.move_to (x,y)
+cr.rel_line_to (0, -height)
+cr.rel_line_to (width, 0)
+cr.rel_line_to (x_bearing, -y_bearing)
+cr.stroke ()
+
diff --git a/examples/cairo_snippets/snippets_gtk.py b/examples/cairo_snippets/snippets_gtk.py
new file mode 100755
index 0000000..c7796ea
--- /dev/null
+++ b/examples/cairo_snippets/snippets_gtk.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+"""Python version of cairo-demo/cairo_snippets/cairo_snippets_gtk.c
+"""
+from __future__ import division
+from math import pi as M_PI # used by many snippets
+import os.path
+import sys
+
+import cairo
+import gtk
+import pango
+
+from snippets import snip_list, snippet_normalize
+
+
+Width, Height = 400, 400
+
+snippets_path = os.path.join(os.path.dirname(__file__), 'snippets')
+
+
+def gdkcolor_to_rgb (gdkcolor):
+ return gdkcolor.red/65535, gdkcolor.green/65535, gdkcolor.blue/65535
+
+
+class Window (gtk.Window):
+ """Composite widget"""
+ def __init__ (self, title=None, type=gtk.WINDOW_TOPLEVEL):
+ gtk.Window.__init__ (self, type)
+ self.set_default_size (Width, Height)
+
+ self.da = gtk.DrawingArea()
+ self.da.connect('expose-event', self.da_expose_event)
+
+ def put_in_frame (widget):
+ frame = gtk.Frame (label=None)
+ frame.set_property ('shadow_type', gtk.SHADOW_IN)
+ frame.add (widget)
+ return frame
+
+ vpaned = gtk.VPaned()
+ self.add (vpaned)
+
+ sv = self.create_text_view()
+ vpaned.pack1 (put_in_frame (sv), True, True)
+ sv.set_size_request (Width, int(Height/2))
+
+ hpaned = gtk.HPaned()
+ vpaned.pack2 (hpaned, True, False)
+
+ sl = self.create_snippet_list()
+ hpaned.pack1 (put_in_frame (sl), True, True)
+
+ hpaned.pack2 (put_in_frame (self.da), True, True)
+ self.da.set_size_request (int(Width/2), int(Height/2))
+
+ # set focus to snippet list
+ sl.get_child().grab_focus()
+
+
+ def da_expose_event (self, da, event, data=None):
+ x, y, width, height = da.allocation
+
+ cr = da.window.cairo_create()
+
+ try:
+ exec (self.snippet_str, globals(), locals())
+ except:
+ exc_type, exc_value = sys.exc_info()[:2]
+ print >> sys.stderr, exc_type, exc_value
+
+ return True
+
+
+ def create_text_view (self):
+ sw = gtk.ScrolledWindow()
+ sw.set_property ('shadow-type', gtk.SHADOW_IN)
+ sw.set_policy (hscrollbar_policy=gtk.POLICY_AUTOMATIC,
+ vscrollbar_policy=gtk.POLICY_AUTOMATIC)
+
+ text_view = gtk.TextView()
+ sw.add (text_view)
+ # set a fixed width font, so any tabs line up
+ text_view.modify_font(pango.FontDescription ("Fixed"))
+
+ self.text_buffer = text_view.get_buffer()
+
+ return sw
+
+
+ def cb_selection_changed (self, tselection, data=None):
+ model, iter = tselection.get_selected()
+ if iter:
+ filename = model[iter][0] + '.py'
+ try:
+ path = os.path.join(snippets_path, filename)
+ file_obj = open(path, 'r')
+ self.snippet_str = file_obj.read()
+ file_obj.close()
+ self.text_buffer.set_text(self.snippet_str)
+ except IOError, exc:
+ print "%s: %s" % (exc.filename, exc.strerror)
+
+ self._draw_pixmap = True
+ self.da.queue_draw()
+
+
+ def create_snippet_list (self):
+ sw = gtk.ScrolledWindow()
+ sw.set_property ('shadow-type', gtk.SHADOW_IN)
+ sw.set_policy (hscrollbar_policy=gtk.POLICY_NEVER,
+ vscrollbar_policy=gtk.POLICY_AUTOMATIC)
+
+ model = gtk.ListStore (str,)
+ for row in snip_list:
+ model.append (row=(row,))
+
+ tree_view = gtk.TreeView (model)
+ sw.add (tree_view)
+ tree_view.set_property ('headers-visible', False)
+ tree_view.set_property ('search-column', 0)
+ tree_view.set_property ('rules-hint', False)
+
+ tselection = tree_view.get_selection()
+ tselection.connect ("changed", self.cb_selection_changed)
+ tselection.set_mode (gtk.SELECTION_BROWSE)
+
+ cr = gtk.CellRendererText()
+ tvc = gtk.TreeViewColumn (None, cr, text=0)
+ tree_view.append_column (tvc)
+
+ tselection.select_path(0,) # select first item
+
+ return sw
+
+
+if __name__ == '__main__':
+ app = Window ()
+ app.connect('destroy', gtk.main_quit)
+ app.show_all()
+ gtk.main()
diff --git a/examples/cairo_snippets/snippets_pdf.py b/examples/cairo_snippets/snippets_pdf.py
new file mode 100755
index 0000000..0606804
--- /dev/null
+++ b/examples/cairo_snippets/snippets_pdf.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+"""Python version of cairo-demo/cairo_snippets/cairo_snippets_pdf.c
+create a file for each example rather than one large file for all examples
+"""
+
+from __future__ import division
+from math import pi as M_PI # used by many snippets
+import sys
+
+import cairo
+if not cairo.HAS_PDF_SURFACE:
+ raise SystemExit ('cairo was not compiled with PDF support')
+
+from snippets import snip_list, snippet_normalize
+
+
+width_in_inches, height_in_inches = 2, 2
+width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
+width, height = width_in_points, height_in_points # used by snippet_normalize()
+
+
+def do_snippet (snippet):
+ if verbose_mode:
+ print 'processing %s' % snippet,
+
+ filename = 'snippets/%s.pdf' % snippet
+ surface = cairo.PDFSurface (filename, width_in_points, height_in_points)
+ cr = cairo.Context (surface)
+
+ cr.save()
+ try:
+ execfile ('snippets/%s.py' % snippet, globals(), locals())
+ except:
+ exc_type, exc_value = sys.exc_info()[:2]
+ print >> sys.stderr, exc_type, exc_value
+ else:
+ cr.restore()
+ cr.show_page()
+ surface.finish()
+
+ if verbose_mode:
+ print
+
+if __name__ == '__main__':
+ verbose_mode = True
+ if len(sys.argv) > 1 and sys.argv[1] == '-s':
+ verbose_mode = False
+ del sys.argv[1]
+
+ if len(sys.argv) > 1: # do specified snippets
+ snippet_list = sys.argv[1:]
+ else: # do all snippets
+ snippet_list = snip_list
+
+ for s in snippet_list:
+ do_snippet (s)
diff --git a/examples/cairo_snippets/snippets_png.py b/examples/cairo_snippets/snippets_png.py
new file mode 100755
index 0000000..b499c6c
--- /dev/null
+++ b/examples/cairo_snippets/snippets_png.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+"""Python version of cairo-demo/cairo_snippets/cairo_snippets_png.c
+"""
+
+from __future__ import division
+from math import pi as M_PI # used by many snippets
+import sys
+
+import cairo
+if not cairo.HAS_PNG_FUNCTIONS:
+ raise SystemExit ('cairo was not compiled with PNG support')
+
+from snippets import snip_list, snippet_normalize
+
+
+width, height = 256, 256 # used by snippet_normalize()
+
+
+def do_snippet (snippet):
+ if verbose_mode:
+ print 'processing %s' % snippet,
+
+ surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height)
+ cr = cairo.Context (surface)
+
+ cr.save()
+ try:
+ execfile ('snippets/%s.py' % snippet, globals(), locals())
+ except:
+# exc_type, exc_value = sys.exc_info()[:2]
+# print >> sys.stderr, exc_type, exc_value
+ raise
+ else:
+ cr.restore()
+ surface.write_to_png ('snippets/%s.png' % snippet)
+
+ if verbose_mode:
+ print
+
+if __name__ == '__main__':
+ verbose_mode = True
+ if len(sys.argv) > 1 and sys.argv[1] == '-s':
+ verbose_mode = False
+ del sys.argv[1]
+
+ if len(sys.argv) > 1: # do specified snippets
+ snippet_list = sys.argv[1:]
+ else: # do all snippets
+ snippet_list = snip_list
+
+ for s in snippet_list:
+ do_snippet (s)
diff --git a/examples/cairo_snippets/snippets_ps.py b/examples/cairo_snippets/snippets_ps.py
new file mode 100755
index 0000000..364402a
--- /dev/null
+++ b/examples/cairo_snippets/snippets_ps.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+"""Python version of cairo-demo/cairo_snippets/cairo_snippets_ps.c
+create a file for each example rather than one large file for all examples
+"""
+
+from __future__ import division
+from math import pi as M_PI # used by many snippets
+import sys
+
+import cairo
+if not cairo.HAS_PS_SURFACE:
+ raise SystemExit ('cairo was not compiled with PS support')
+
+from snippets import snip_list, snippet_normalize
+
+
+width_in_inches, height_in_inches = 2, 2
+width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
+width, height = width_in_points, height_in_points # used by snippet_normalize()
+
+
+def do_snippet (snippet):
+ if verbose_mode:
+ print 'processing %s' % snippet,
+
+ filename = 'snippets/%s.ps' % snippet
+ surface = cairo.PSSurface (filename, width_in_points, height_in_points)
+ cr = cairo.Context (surface)
+
+ cr.save()
+ try:
+ execfile ('snippets/%s.py' % snippet, globals(), locals())
+ except:
+ exc_type, exc_value = sys.exc_info()[:2]
+ print >> sys.stderr, exc_type, exc_value
+ else:
+ cr.restore()
+ cr.show_page()
+ surface.finish()
+
+ if verbose_mode:
+ print
+
+if __name__ == '__main__':
+ verbose_mode = True
+ if len(sys.argv) > 1 and sys.argv[1] == '-s':
+ verbose_mode = False
+ del sys.argv[1]
+
+ if len(sys.argv) > 1: # do specified snippets
+ snippet_list = sys.argv[1:]
+ else: # do all snippets
+ snippet_list = snip_list
+
+ for s in snippet_list:
+ do_snippet (s)
diff --git a/examples/cairo_snippets/snippets_svg.py b/examples/cairo_snippets/snippets_svg.py
new file mode 100755
index 0000000..3620ee7
--- /dev/null
+++ b/examples/cairo_snippets/snippets_svg.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+from __future__ import division
+from math import pi as M_PI # used by many snippets
+import sys
+
+import cairo
+if not cairo.HAS_SVG_SURFACE:
+ raise SystemExit ('cairo was not compiled with SVG support')
+
+from snippets import snip_list, snippet_normalize
+
+
+width_in_inches, height_in_inches = 2, 2
+width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
+width, height = width_in_points, height_in_points # used by snippet_normalize()
+
+
+def do_snippet (snippet):
+ if verbose_mode:
+ print 'processing %s' % snippet,
+
+ filename = 'snippets/%s.svg' % snippet
+ surface = cairo.SVGSurface (filename, width_in_points, height_in_points)
+ cr = cairo.Context (surface)
+
+ cr.save()
+ try:
+ execfile ('snippets/%s.py' % snippet, globals(), locals())
+ except:
+ exc_type, exc_value = sys.exc_info()[:2]
+ print >> sys.stderr, exc_type, exc_value
+ else:
+ cr.restore()
+ cr.show_page()
+ surface.finish()
+
+ if verbose_mode:
+ print
+
+if __name__ == '__main__':
+ verbose_mode = True
+ if len(sys.argv) > 1 and sys.argv[1] == '-s':
+ verbose_mode = False
+ del sys.argv[1]
+
+ if len(sys.argv) > 1: # do specified snippets
+ snippet_list = sys.argv[1:]
+ else: # do all snippets
+ snippet_list = snip_list
+
+ for s in snippet_list:
+ do_snippet (s)
diff --git a/examples/gradient.py b/examples/gradient.py
new file mode 100755
index 0000000..9ebbf76
--- /dev/null
+++ b/examples/gradient.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+"""/cairo-demo/cairo_snippets/gradient.cairo translated to Python
+"""
+
+import math
+import cairo
+
+WIDTH, HEIGHT = 256, 256
+
+surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
+ctx = cairo.Context(surface)
+
+ctx.scale (WIDTH/1.0, HEIGHT/1.0)
+
+pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
+pat.add_color_stop_rgba (1, 0, 0, 0, 1)
+pat.add_color_stop_rgba (0, 1, 1, 1, 1)
+
+ctx.rectangle (0,0,1,1)
+ctx.set_source (pat)
+ctx.fill ()
+
+pat = cairo.RadialGradient (0.45, 0.4, 0.1,
+ 0.4, 0.4, 0.5)
+pat.add_color_stop_rgba (0, 1, 1, 1, 1)
+pat.add_color_stop_rgba (1, 0, 0, 0, 1)
+
+ctx.set_source (pat)
+ctx.arc (0.5, 0.5, 0.3, 0, 2 * math.pi)
+ctx.fill ()
+
+surface.write_to_png('gradient.png')
+#surface.write_to_png(10)
diff --git a/examples/gtk/cairo-demo.py b/examples/gtk/cairo-demo.py
new file mode 100755
index 0000000..76795ce
--- /dev/null
+++ b/examples/gtk/cairo-demo.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+"""Based on cairo-demo/X11/cairo-demo.c
+"""
+import cairo
+import gtk
+
+SIZE = 30
+
+def triangle(ctx):
+ ctx.move_to(SIZE, 0)
+ ctx.rel_line_to(SIZE, 2*SIZE)
+ ctx.rel_line_to(-2*SIZE, 0)
+ ctx.close_path()
+
+def square(ctx):
+ ctx.move_to(0, 0)
+ ctx.rel_line_to(2*SIZE, 0)
+ ctx.rel_line_to(0, 2*SIZE)
+ ctx.rel_line_to(-2*SIZE, 0)
+ ctx.close_path()
+
+def bowtie(ctx):
+ ctx.move_to(0, 0)
+ ctx.rel_line_to(2*SIZE, 2*SIZE)
+ ctx.rel_line_to(-2*SIZE, 0)
+ ctx.rel_line_to(2*SIZE, -2*SIZE)
+ ctx.close_path()
+
+def inf(ctx):
+ ctx.move_to(0, SIZE)
+ ctx.rel_curve_to(0,SIZE, SIZE,SIZE, 2*SIZE,0)
+ ctx.rel_curve_to(SIZE,-SIZE, 2*SIZE,-SIZE, 2*SIZE,0)
+ ctx.rel_curve_to(0,SIZE, -SIZE,SIZE, -2*SIZE,0)
+ ctx.rel_curve_to(-SIZE,-SIZE, -2*SIZE,-SIZE, -2*SIZE,0)
+ ctx.close_path()
+
+def draw_shapes(ctx, x, y, fill):
+ ctx.save()
+
+ ctx.new_path()
+ ctx.translate(x+SIZE, y+SIZE)
+ bowtie(ctx)
+ if fill:
+ ctx.fill()
+ else:
+ ctx.stroke()
+
+ ctx.new_path()
+ ctx.translate(3*SIZE, 0)
+ square(ctx)
+ if fill:
+ ctx.fill()
+ else:
+ ctx.stroke()
+
+ ctx.new_path()
+ ctx.translate(3*SIZE, 0)
+ triangle(ctx)
+ if fill:
+ ctx.fill()
+ else:
+ ctx.stroke()
+
+ ctx.new_path()
+ ctx.translate(3*SIZE, 0)
+ inf(ctx)
+ if fill:
+ ctx.fill()
+ else:
+ ctx.stroke()
+
+ ctx.restore()
+
+def fill_shapes(ctx, x, y):
+ draw_shapes(ctx, x, y, True)
+
+def stroke_shapes(ctx, x, y):
+ draw_shapes(ctx, x, y, False)
+
+def expose (da, event):
+ ctx = da.window.cairo_create()
+
+ ctx.set_source_rgb(0, 0, 0)
+
+ ctx.set_line_width(SIZE / 4)
+ ctx.set_tolerance(0.1)
+
+ ctx.set_line_join(cairo.LINE_JOIN_ROUND)
+ ctx.set_dash([SIZE/4.0, SIZE/4.0], 0)
+ stroke_shapes(ctx, 0, 0)
+
+ ctx.set_dash([], 0)
+ stroke_shapes(ctx, 0, 3*SIZE)
+
+ ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
+ stroke_shapes(ctx, 0, 6*SIZE)
+
+ ctx.set_line_join(cairo.LINE_JOIN_MITER)
+ stroke_shapes(ctx, 0, 9*SIZE)
+
+ fill_shapes(ctx, 0, 12*SIZE)
+
+ ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
+ fill_shapes(ctx, 0, 15*SIZE)
+ ctx.set_source_rgb(1,0,0)
+ stroke_shapes(ctx, 0, 15*SIZE)
+
+def main():
+ win = gtk.Window()
+ win.connect('destroy', gtk.main_quit)
+ win.set_default_size(450, 550)
+
+ drawingarea = gtk.DrawingArea()
+ win.add(drawingarea)
+ drawingarea.connect('expose_event', expose)
+
+ win.show_all()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/gtk/cairo-knockout.py b/examples/gtk/cairo-knockout.py
new file mode 100755
index 0000000..e8c2c90
--- /dev/null
+++ b/examples/gtk/cairo-knockout.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+"""Based on gtk+/test/testcairo.c
+"""
+
+from __future__ import division
+import math
+import sys
+
+import cairo
+import gtk
+
+
+def oval_path(ctx, xc, yc, xr, yr):
+ ctx.save()
+
+ ctx.translate (xc, yc)
+ ctx.scale (1.0, yr / xr)
+ ctx.move_to (xr, 0.0)
+ ctx.arc (0, 0, xr, 0, 2 * math.pi)
+ ctx.close_path ()
+
+ ctx.restore()
+
+def fill_checks(ctx, x, y, width, height):
+ CHECK_SIZE = 32
+
+ ctx.rectangle (x, y, width, height)
+ ctx.set_source_rgb (0.4, 0.4, 0.4)
+ ctx.fill ()
+
+ # Only works for CHECK_SIZE a power of 2
+ for j in range (x & -CHECK_SIZE, height, CHECK_SIZE):
+ for i in range (y & -CHECK_SIZE, width, CHECK_SIZE):
+ if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0):
+ ctx.rectangle (i, j, CHECK_SIZE, CHECK_SIZE)
+
+ ctx.set_source_rgb (0.7, 0.7, 0.7)
+ ctx.fill ()
+
+def draw_3circles(ctx, xc, yc, radius, alpha):
+ subradius = radius * (2 / 3. - 0.1)
+
+ ctx.set_source_rgba(1, 0, 0, alpha)
+ oval_path(ctx,
+ xc + radius / 3. * math.cos(math.pi * 0.5),
+ yc - radius / 3. * math.sin(math.pi * 0.5),
+ subradius, subradius)
+ ctx.fill()
+
+ ctx.set_source_rgba(0, 1, 0, alpha)
+ oval_path(ctx,
+ xc + radius / 3. * math.cos(math.pi * (0.5 + 2/.3)),
+ yc - radius / 3. * math.sin(math.pi * (0.5 + 2/.3)),
+ subradius, subradius)
+ ctx.fill()
+
+ ctx.set_source_rgba(0, 0, 1, alpha)
+ oval_path(ctx,
+ xc + radius / 3. * math.cos(math.pi * (0.5 + 4/.3)),
+ yc - radius / 3. * math.sin(math.pi * (0.5 + 4/.3)),
+ subradius, subradius)
+ ctx.fill()
+
+def draw (ctx, width, height):
+ radius = 0.5 * min(width, height) - 10
+ xc = width / 2.
+ yc = height / 2.
+
+ target = ctx.get_target()
+ overlay = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height)
+ punch = target.create_similar(cairo.CONTENT_ALPHA, width, height)
+ circles = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height)
+
+ fill_checks(ctx, 0, 0, width, height)
+
+ # Draw a black circle on the overlay
+ overlay_cr = cairo.Context (overlay)
+ overlay_cr.set_source_rgb (0, 0, 0)
+ oval_path (overlay_cr, xc, yc, radius, radius)
+ overlay_cr.fill()
+
+ # Draw 3 circles to the punch surface, then cut
+ # that out of the main circle in the overlay
+ punch_cr = cairo.Context (punch)
+ draw_3circles (punch_cr, xc, yc, radius, 1.0)
+
+ overlay_cr.set_operator (cairo.OPERATOR_DEST_OUT)
+ overlay_cr.set_source_surface (punch, 0, 0)
+ overlay_cr.paint()
+
+ # Now draw the 3 circles in a subgroup again
+ # at half intensity, and use OperatorAdd to join up
+ # without seams.
+ circles_cr = cairo.Context (circles)
+
+ circles_cr.set_operator (cairo.OPERATOR_OVER)
+ draw_3circles (circles_cr, xc, yc, radius, 0.5)
+
+ overlay_cr.set_operator (cairo.OPERATOR_ADD)
+ overlay_cr.set_source_surface (circles, 0, 0)
+ overlay_cr.paint()
+
+ ctx.set_source_surface (overlay, 0, 0)
+ ctx.paint()
+
+def expose(drawingarea, event):
+ ctx = drawingarea.window.cairo_create()
+
+ _, _, width, height = drawingarea.allocation
+ draw (ctx, width, height)
+
+ return False
+
+def main():
+ win = gtk.Window()
+ win.connect('destroy', gtk.main_quit)
+ win.set_title('Knockout Groups')
+ win.set_default_size(400, 400)
+
+ drawingarea = gtk.DrawingArea()
+ win.add(drawingarea)
+ drawingarea.connect('expose_event', expose)
+
+ win.show_all()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/gtk/hangman.py b/examples/gtk/hangman.py
new file mode 100755
index 0000000..8aa16ce
--- /dev/null
+++ b/examples/gtk/hangman.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+# -*- coding: iso8859-1 -*-
+#
+# Copyright © 2004 Kevin Worth
+#
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of the Kevin Worth not
+# be used in advertising or publicity pertaining to distribution of
+# the software without specific, written prior permission. Kevin Worth
+# California makes no representations about the suitability of this
+# software for any purpose. It is provided "as is" without express or
+# implied warranty.
+#
+# KEVIN WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+# NO EVENT SHALL KEVIN WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Author: Kevin Worth <kevin@theworths.org>
+
+from math import pi
+from random import randint
+
+import cairo
+import gtk
+
+letters_guessed = ""
+letters_guessed_right = ""
+letters_guessed_wrong = ""
+
+body_parts = 6
+words = ['cairo', 'graphics', 'pencil', 'keyboard', 'science', 'ricochet', 'flood', 'president', 'sanity']
+
+idxRandom = randint(0, len(words) -1)
+word_chosen = words[idxRandom]
+
+#print "The secret word is " + word_chosen
+
+def guess_letter(widget, event):
+ global letters_guessed, letters_guessed_right, letters_guessed_wrong
+ if event.string in letters_guessed:
+ print "What?!?! You already guessed '" + event.string + "'!"
+ else:
+ letters_guessed += event.string
+ if word_chosen.lower().find(event.string) != -1:
+ letters_guessed_right += event.string
+ else:
+ letters_guessed_wrong += event.string
+ widget.queue_draw()
+
+def expose_event(widget, event):
+ _, _, width, height = widget.allocation
+
+ if width < height:
+ size = width
+ else:
+ size = height
+
+ pixmap = gtk.gdk.Pixmap (widget.window, width, height)
+ ctx = pixmap.cairo_create()
+
+ # set the background
+ ctx.set_source_rgb(0.7,0.7,0.7)
+ ctx.set_operator (cairo.OPERATOR_SOURCE)
+ ctx.paint()
+
+ ctx.translate ((width - size) / 2, (height - size) / 2)
+ ctx.scale(size / 150.0, size / 160.0)
+
+ def man_hung():
+ return len(letters_guessed_wrong) == body_parts
+
+ ctx.set_font_size(10)
+ ctx.set_source_rgb(0,0,0)
+ for idxLetter in range(len(word_chosen)):
+ #print "Examining letter: " + word_chosen[idxLetter]
+ if word_chosen[idxLetter].lower() in letters_guessed_right or man_hung():
+ if idxLetter == 0:
+ ctx.move_to(0, 150)
+ ctx.show_text(word_chosen[idxLetter].upper())
+ else:
+ ctx.move_to(idxLetter * 15, 150)
+ ctx.show_text(word_chosen[idxLetter].lower())
+ else:
+ ctx.move_to(idxLetter * 15, 150)
+ ctx.show_text('_')
+
+ # Draw Letters Guessed
+
+ ctx.move_to(0, 160)
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.show_text(letters_guessed)
+
+ # Draw noose
+
+ ctx.move_to(100, 12.5)
+ ctx.line_to(100, 5)
+ ctx.line_to(130, 5)
+ ctx.line_to(130, 100)
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.stroke()
+
+ # Draw base fill color
+
+ ctx.move_to(130, 100)
+ ctx.line_to(130, 140)
+ ctx.line_to(40, 140)
+ ctx.line_to(40, 130)
+ ctx.line_to(50, 130)
+ ctx.line_to(50, 122)
+ ctx.line_to(60, 122)
+ ctx.line_to(60, 114)
+ ctx.line_to(70, 114)
+ ctx.line_to(70, 106)
+ ctx.line_to(130, 106)
+ ctx.set_source_rgb(.4, .2, .1)
+ ctx.fill()
+
+ # Draw base outline color
+
+ ctx.move_to(130, 100)
+ ctx.line_to(130, 140)
+ ctx.line_to(40, 140)
+
+ # Draw 1st(lowest) stair
+
+ ctx.line_to(40, 130)
+ ctx.line_to(50, 130)
+ ctx.line_to(130, 130)
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.stroke()
+
+ # Draw 2nd stair
+
+ ctx.move_to(50, 130)
+ ctx.line_to(50, 121)
+ ctx.line_to(60, 121)
+ ctx.line_to(130, 121)
+ ctx.stroke()
+
+ # Draw 3rd stair
+
+ ctx.move_to(60, 121)
+ ctx.line_to(60, 113)
+ ctx.line_to(70, 113)
+ ctx.line_to(130, 113)
+ ctx.stroke()
+
+ # Draw 4th(top) stair
+
+ ctx.move_to(70, 113)
+ ctx.line_to(70, 105)
+ ctx.line_to(130, 105)
+ ctx.stroke()
+
+ # Draw Head
+
+ if len(letters_guessed_wrong) > 0:
+ ctx.move_to(107.5, 20)
+ ctx.arc(100, 20, 7.5, 0, 2*pi)
+ ctx.set_line_width(1)
+ ctx.stroke()
+
+ # Draw Eye 1
+
+ ctx.move_to(104, 17)
+ ctx.arc(103, 17, 1, 0, 2*pi)
+ ctx.move_to(103.1, 17)
+ ctx.arc(103, 17, .1, 0, 2*pi)
+
+ # Draw Eye 2
+
+ ctx.move_to(98, 17)
+ ctx.arc(97, 17, 1, 0, 2*pi)
+ ctx.move_to(97.1, 17)
+ ctx.arc(97, 17, .1, 0, 2*pi)
+
+ # Draw Nose
+
+ ctx.move_to(100.5, 19)
+ ctx.line_to(99.5, 21)
+ ctx.line_to(100.5, 21)
+
+ # Draw Mouth
+
+ if len(letters_guessed_wrong) < 6:
+ ctx.move_to(97, 23)
+ ctx.curve_to(97, 23, 100, 27.5, 103, 23)
+ ctx.set_line_width(.5)
+ ctx.stroke()
+ else:
+ ctx.move_to(100.5, 24)
+ ctx.arc(100, 24, .5, 0, 2*pi)
+ ctx.set_line_width(.5)
+ ctx.stroke()
+
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.set_line_width(1)
+
+ # Draw Body
+
+ if len(letters_guessed_wrong) > 1:
+ ctx.move_to(100, 27.5)
+ ctx.line_to(100, 70)
+ ctx.stroke()
+
+ # Draw Arm 1
+
+ if len(letters_guessed_wrong) > 2:
+ ctx.move_to(100, 35)
+ ctx.line_to(110, 50)
+ ctx.stroke()
+
+ # Draw Arm 2
+
+ if len(letters_guessed_wrong) > 3:
+ ctx.move_to(100, 35)
+ ctx.line_to(90, 50)
+ ctx.stroke()
+
+ # Draw Leg 1
+
+ if len(letters_guessed_wrong) > 4:
+ ctx.move_to(100, 70)
+ ctx.line_to(112, 95)
+ ctx.stroke()
+
+ # Draw Leg 2
+
+ if len(letters_guessed_wrong) > 5:
+ ctx.move_to(100, 70)
+ ctx.line_to(88, 95)
+ ctx.stroke()
+
+ # draw pixmap to gdk.window
+ gc = gtk.gdk.GC(widget.window)
+ widget.window.draw_drawable(gc, pixmap, 0,0, 0,0, -1,-1)
+
+
+win = gtk.Window()
+win.connect('destroy', gtk.main_quit)
+win.connect('key_press_event', guess_letter)
+win.set_title('Kevin\'s cairo demo')
+
+drawingarea = gtk.DrawingArea()
+win.add(drawingarea)
+drawingarea.connect('expose_event', expose_event)
+drawingarea.set_size_request(300,320)
+
+win.show_all()
+gtk.main()
diff --git a/examples/gtk/lsystem.py b/examples/gtk/lsystem.py
new file mode 100755
index 0000000..e08c8dc
--- /dev/null
+++ b/examples/gtk/lsystem.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+import cairo
+import gtk
+
+# Copyright 2003 Jesse Andrews (jdandr2@uky.edu) under GPL
+
+
+class lindenmayer:
+ def __init__( self ):
+ self.str = ''
+ self.prod = {'[':'[','f':'f',']':']','+':'+','-':'-'}
+ self.SIZE = 10
+ self.THETA = 90
+
+ def addProd( self, let, pro ):
+ self.prod[let]=pro
+
+ def iterate( self, qty=1 ):
+ for i in xrange(qty):
+ self.str = ''.join([ self.prod[l] for l in self.str])
+ print 'Done iterating'
+
+ def expose( self, drawingarea, event ):
+ drawable = drawingarea.window
+ x, y, width, height = drawingarea.allocation
+
+ ctx = drawable.cairo_create()
+ ctx.set_source_rgb(0, 0, 0)
+
+ ctx.set_line_width(self.SIZE / 4)
+ ctx.set_tolerance(0.1)
+ ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
+
+ ctx.new_path()
+ ctx.move_to(100,100)
+
+ for c in self.str:
+ if c == 'f': line(ctx, self.SIZE )
+ if c == '+': rotate( ctx, +self.THETA )
+ if c == '-': rotate( ctx, -self.THETA )
+ if c == '[': ctx.save()
+ if c == ']': ctx.restore()
+
+ ctx.stroke()
+
+def line(ctx, len):
+ ctx.rel_line_to( 0, len )
+
+def rotate(ctx, deg):
+ ctx.rotate( 2*3.141592653589793*deg/360.0 )
+
+def lin_setup():
+ cls = lindenmayer()
+ ################# SETUP LSYSTEM HERE ################
+
+ ### Generic stuff ###
+
+ cls.str = 'f' # the starting string
+
+ cls.SIZE = 5 # length of a line
+
+ ##############################################
+ ##############################################
+ #### Uncomment the one you want to use... ####
+ #### only one at a time right now! ####
+ ##############################################
+ ##############################################
+
+ ###### Kock Square Curve #######
+ cls.addProd('f','f-f+f+f-f')
+ cls.THETA = 90
+
+ ###### Kock Snowflake ######
+
+# cls.addProd('f','f-f++f-f')
+# cls.THETA = 60
+
+ ######## Peano Curve ########
+# cls.addProd('x', 'xfyfx+f+yfxfy-f-xfyfx')
+# cls.addProd('y', 'yfxfy-f-xfyfx+f+yfxfy')
+# cls.addProd('f', 'f')
+# cls.THETA = 90
+# cls.str = 'y'
+
+ ###### the plant ######
+ ## doesn't seem to work ... .save & .restore messed up ##
+
+# cls.addProd( 'f','f[+f]f[-f]f' )
+# cls.THETA = 25
+
+ ####### the tree #########
+ ## doesn't seem to work ... .save & .restore messed up ##
+
+# cls.addProd( 'f', 'ff+[+f-f-f]-[-f+f+f]' )
+# cls.THETA = 22
+
+
+ ### times to iterate string rewriting ###
+ #this grows QUICKLY, so start only inc by 1 each run!
+ cls.iterate(4)
+
+ ################ DONE SETUP ###############
+ return cls
+
+def main():
+ win = gtk.Window()
+ win.connect('destroy', lambda x: gtk.main_quit())
+ win.set_title('cairo Lindenmayer System')
+ win.set_default_size(600, 600)
+
+ cls = lin_setup()
+
+ drawingarea = gtk.DrawingArea()
+ win.add(drawingarea)
+ drawingarea.connect('expose_event', cls.expose)
+
+ win.show_all()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/gtk/png_view.py b/examples/gtk/png_view.py
new file mode 100755
index 0000000..1100c75
--- /dev/null
+++ b/examples/gtk/png_view.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+"""Display a png file
+"""
+
+import sys
+
+import cairo
+import gtk
+
+
+def expose_event(widget, event, surface):
+ ctx = widget.window.cairo_create()
+ ctx.set_source_surface(surface, 0,0)
+ ctx.paint()
+
+
+if len(sys.argv) != 2:
+ raise SystemExit('usage: png_view.py png_file')
+
+filename = sys.argv[1]
+
+surface = cairo.ImageSurface.create_from_png(filename)
+Width = surface.get_width()
+Height = surface.get_height()
+
+win = gtk.Window()
+win.connect('destroy', gtk.main_quit)
+
+drawingarea = gtk.DrawingArea()
+win.add(drawingarea)
+drawingarea.connect('expose_event', expose_event, surface)
+drawingarea.set_size_request(Width,Height)
+
+win.show_all()
+gtk.main()
diff --git a/examples/gtk/text.py b/examples/gtk/text.py
new file mode 100755
index 0000000..2bef98b
--- /dev/null
+++ b/examples/gtk/text.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+import cairo
+import gtk
+
+
+def expose_event(widget, event):
+ ctx = widget.window.cairo_create()
+
+ ctx.set_line_width(6)
+ ctx.set_tolerance(.1)
+
+ ctx.select_font_face('sans-serif')
+ ctx.set_font_size(48)
+ (x, y, width, height, dx, dy) = ctx.text_extents('Hello World')
+
+ ctx.translate (100, 100)
+
+ ctx.new_path()
+ ctx.move_to(x-10,y-10)
+ ctx.rel_line_to(width + 20, 0)
+ ctx.rel_line_to(0, height + 20)
+ ctx.rel_line_to(-(width + 20), 0)
+ ctx.close_path()
+ ctx.set_source_rgb(0,0,1)
+ ctx.stroke()
+
+ ctx.move_to(0, 0)
+ ctx.set_source_rgb(0,0,0)
+ ctx.show_text('Hello World')
+
+win = gtk.Window()
+win.connect('destroy', gtk.main_quit)
+
+drawingarea = gtk.DrawingArea()
+win.add(drawingarea)
+drawingarea.connect('expose_event', expose_event)
+drawingarea.set_size_request(400,150)
+
+win.show_all()
+gtk.main()
diff --git a/examples/hering.py b/examples/hering.py
new file mode 100755
index 0000000..e400e15
--- /dev/null
+++ b/examples/hering.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+"""cairo/cairo-demo/png/hering.c translated into Python
+"""
+
+import math
+
+import cairo
+
+WIDTH = 300
+HEIGHT = 600
+
+def draw_hering (ctx, width, height):
+ LINES= 32
+ MAX_THETA = .80 * math.pi * 2
+ THETA_INC = 2.0 * MAX_THETA / (LINES-1)
+
+ ctx.set_source_rgb (0, 0, 0)
+ ctx.set_line_width (2.0)
+
+ ctx.save()
+
+ ctx.translate (width / 2, height / 2)
+ ctx.rotate (MAX_THETA)
+
+ for i in range (LINES):
+ ctx.move_to (-2 * width, 0)
+ ctx.line_to (2 * width, 0)
+ ctx.stroke()
+
+ ctx.rotate (- THETA_INC)
+
+ ctx.restore()
+
+ ctx.set_line_width (6)
+ ctx.set_source_rgb (1, 0, 0)
+
+ ctx.move_to (width / 4.0, 0)
+ ctx.rel_line_to (0, height)
+ ctx.stroke()
+
+ ctx.move_to (3 * width / 4.0, 0)
+ ctx.rel_line_to (0, height)
+ ctx.stroke()
+
+
+surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
+ctx = cairo.Context(surface)
+
+ctx.set_source_rgb (1, 1, 1)
+ctx.set_operator (cairo.OPERATOR_SOURCE)
+ctx.paint()
+
+draw_hering (ctx, WIDTH, HEIGHT)
+
+surface.write_to_png('hering.png')
diff --git a/examples/spiral.py b/examples/spiral.py
new file mode 100755
index 0000000..7be9af2
--- /dev/null
+++ b/examples/spiral.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+"""cairo/cairo-demo/png/spiral.c translated into Python
+"""
+
+import cairo
+
+WIDTH, HEIGHT = 600, 600
+
+def draw_spiral (ctx, width, height):
+ wd = .02 * width
+ hd = .02 * height
+
+ width -= 2
+ height -= 2
+
+ ctx.move_to (width + 1, 1-hd)
+ for i in range(9):
+ ctx.rel_line_to (0, height - hd * (2 * i - 1))
+ ctx.rel_line_to (- (width - wd * (2 *i)), 0)
+ ctx.rel_line_to (0, - (height - hd * (2*i)))
+ ctx.rel_line_to (width - wd * (2 * i + 1), 0)
+
+ ctx.set_source_rgb (0, 0, 1)
+ ctx.stroke()
+
+
+surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
+ctx = cairo.Context(surface)
+
+ctx.set_source_rgb (1, 1, 1)
+ctx.set_operator (cairo.OPERATOR_SOURCE)
+ctx.paint()
+
+draw_spiral (ctx, WIDTH, HEIGHT)
+
+surface.write_to_png('spiral.png')
diff --git a/examples/warpedtext.py b/examples/warpedtext.py
new file mode 100755
index 0000000..cd83ee7
--- /dev/null
+++ b/examples/warpedtext.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+
+import cairo
+import math
+
+def warpPath(ctx, function):
+ first = True
+
+ for type, points in ctx.copy_path():
+ if type == cairo.PATH_MOVE_TO:
+ if first:
+ ctx.new_path()
+ first = False
+ x, y = function(*points)
+ ctx.move_to(x, y)
+
+ elif type == cairo.PATH_LINE_TO:
+ x, y = function(*points)
+ ctx.line_to(x, y)
+
+ elif type == cairo.PATH_CURVE_TO:
+ x1, y1, x2, y2, x3, y3 = points
+ x1, y1 = function(x1, y1)
+ x2, y2 = function(x2, y2)
+ x3, y3 = function(x3, y3)
+ ctx.curve_to(x1, y1, x2, y2, x3, y3)
+
+ elif type == cairo.PATH_CLOSE_PATH:
+ ctx.close_path()
+
+def spiral(x, y):
+ theta0 = -math.pi * 3 / 4
+ theta = x / Width * math.pi * 2 + theta0
+ radius = y + 200 - x/7
+ xnew = radius*math.cos(theta)
+ ynew = radius*math.sin(-theta)
+ return xnew + Width/2, ynew + Height/2
+
+def curl(x, y):
+ xn = x - Textwidth/2
+ #yn = y - Textheight/2
+ xnew = xn
+ ynew = y + xn ** 3 / ((Textwidth/2)**3) * 70
+ return xnew + Width/2, ynew + Height*2/5
+
+
+Width, Height = 512, 512
+surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height)
+ctx = cairo.Context(surface)
+solidpattern = ctx.get_source()
+
+# background
+pat = cairo.LinearGradient (0.0, 0.0, 0, Height)
+pat.add_color_stop_rgba (1, 0, 0, 0, 1)
+pat.add_color_stop_rgba (0, 1, 1, 1, 1)
+
+ctx.rectangle (0,0,Width,Height)
+ctx.set_source (pat)
+ctx.fill ()
+
+# foreground
+ctx.set_source (solidpattern)
+ctx.set_source_rgb (1,1,1)
+
+ctx.select_font_face("Sans")
+ctx.set_font_size(80)
+
+# spiral text
+ctx.new_path()
+ctx.move_to(0, 0)
+ctx.text_path("pycairo - " + "spam " * 5)
+warpPath(ctx, spiral)
+ctx.fill()
+
+# curly text
+ctx.new_path()
+ctx.move_to(0, 0)
+ctx.set_source_rgb(0.3, 0.3, 0.3)
+text = "I am curly :)"
+ctx.text_path(text)
+Textwidth, Textheight = ctx.text_extents(text)[2:4]
+warpPath(ctx, curl)
+ctx.fill()
+
+surface.write_to_png("warpedtext.png")