summaryrefslogtreecommitdiff
path: root/doc/tutorial/src
diff options
context:
space:
mode:
authormh0310.choi <mh0310.choi@samsung.com>2015-07-28 10:46:57 +0900
committermh0310.choi <mh0310.choi@samsung.com>2015-07-28 13:08:12 +0900
commit5e67a6f721eaedda61300baf0799199c7771ebd0 (patch)
tree6cd50b52498aab50e79b966cdccc2a137db316d9 /doc/tutorial/src
parentd3aeffba37161d2b76b29c4ea13369bd67a47a8e (diff)
downloadcairo-5e67a6f721eaedda61300baf0799199c7771ebd0.tar.gz
cairo-5e67a6f721eaedda61300baf0799199c7771ebd0.tar.bz2
cairo-5e67a6f721eaedda61300baf0799199c7771ebd0.zip
- from 1.12.14 to 1.14.2 Change-Id: I3b62d212041b337bbb926d579f9ce74f42a45c3b
Diffstat (limited to 'doc/tutorial/src')
-rw-r--r--doc/tutorial/src/.gitignore8
-rw-r--r--doc/tutorial/src/README66
-rw-r--r--doc/tutorial/src/circle.c22
-rw-r--r--doc/tutorial/src/include/cairo-tutorial-gtk.h133
-rw-r--r--doc/tutorial/src/include/cairo-tutorial-pdf.h74
-rw-r--r--doc/tutorial/src/include/cairo-tutorial-png.h74
-rw-r--r--doc/tutorial/src/include/cairo-tutorial-xlib.h251
-rw-r--r--doc/tutorial/src/include/cairo-tutorial.h40
-rw-r--r--doc/tutorial/src/lca.c32
-rw-r--r--doc/tutorial/src/singular.c162
-rw-r--r--doc/tutorial/src/twin.c39
11 files changed, 901 insertions, 0 deletions
diff --git a/doc/tutorial/src/.gitignore b/doc/tutorial/src/.gitignore
new file mode 100644
index 000000000..68af59e73
--- /dev/null
+++ b/doc/tutorial/src/.gitignore
@@ -0,0 +1,8 @@
+*-gtk
+*-pdf
+*-png
+*-xlib
+*.pdf
+*.png
+*.o
+*~
diff --git a/doc/tutorial/src/README b/doc/tutorial/src/README
new file mode 100644
index 000000000..a2738da4e
--- /dev/null
+++ b/doc/tutorial/src/README
@@ -0,0 +1,66 @@
+Welcome to the cairo tutorial:
+
++--------------------------------+
+| How to Recognize Ugly Graphics |
+|(and what you can do about them)|
++--------------------------------+
+
+This directory is your personal playground for following along with
+the examples. In order for you to make use of these files you will
+need to have cairo and its header files installed. You can find
+instructions for doing this at:
+
+ http://cairographics.org/tutorial
+
+Notice that there are a few .c files in this directory.
+
+You should start out by just typing "make" which will turn each .c
+file into several different programs. Go ahead and run each of the
+programs and see what they do. Some of them will open up new X windows
+while others will simply write their output to files (such .png or
+.pdf).
+
+After you play with those a bit, go ahead and take a look at the
+contents of the .c files. You'll see that each file contains a draw()
+function that does all of the drawing.
+
+You might be surprised to notice that there is no main() function in
+any of the files. Instead, main is hidden away by means of
+cairo-tutorial.h. This rather non-conventional style is used to allow
+you to focus on the actual drawing code involved in using cairo, while
+not having to worry about the setup semantics. We don't recommend that
+you follow this style for real projects.
+
+As you follow along during the tutorial and get some ideas for things
+to draw, you'll want to start making your own .c files. You can copy
+an existing file or make your own by following this simple minimal
+template:
+
+ #include "cairo-tutorial.h"
+
+ static void
+ draw (cairo_t *cr, int width, int height)
+ {
+ /* Put your drawing code here. */
+ }
+
+Any new file you create will automatically get picked up by the
+Makefile so that "make" will compile your file into several different
+programs, just like the existing examples.
+
+If you'd like to control the initial size of the output, you may
+define WIDTH and HEIGHT before including cairo-tutorial.h like so:
+
+ #define WIDTH 100
+ #define HEIGHT 100
+
+ #include "cairo-tutorial.h"
+
+If you would like to change the set of cairo-backend target programs
+that are compiled, you may edit the "all" target in the Makefile.
+
+Have fun!
+
+-Carl Worth
+
+cworth@redhat.com
diff --git a/doc/tutorial/src/circle.c b/doc/tutorial/src/circle.c
new file mode 100644
index 000000000..6bd02e8ba
--- /dev/null
+++ b/doc/tutorial/src/circle.c
@@ -0,0 +1,22 @@
+#include "cairo-tutorial.h"
+
+static void
+draw (cairo_t *cr, int width, int height)
+{
+ int radius;
+
+ if (width < height)
+ radius = width/2 - 4;
+ else
+ radius = height/2 - 4;
+
+ cairo_move_to (cr, width/2 + radius, height/2);
+ cairo_arc (cr, width/2, height/2, radius,
+ 0.0, 2 * M_PI);
+
+ cairo_set_source_rgb (cr, 0.6, 0.8, 1.0);
+ cairo_fill_preserve (cr);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_stroke (cr);
+}
diff --git a/doc/tutorial/src/include/cairo-tutorial-gtk.h b/doc/tutorial/src/include/cairo-tutorial-gtk.h
new file mode 100644
index 000000000..60516a356
--- /dev/null
+++ b/doc/tutorial/src/include/cairo-tutorial-gtk.h
@@ -0,0 +1,133 @@
+/* cairo-tutorial-gtk.h - a tutorial framework for cairo with gtk+
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <cairo.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr, int width, int height);
+
+#if ! GTK_CHECK_VERSION(2,7,0)
+/* copied from gtk+/gdk/gdkcairo.c and gtk+/gdk/x11/gdkdrawable-x11.c
+ * gdk_cairo_create() which is available in 2.7.0 and later.
+ */
+static cairo_t *
+gdk_cairo_create (GdkDrawable *drawable)
+{
+ int width, height;
+ cairo_t *cr = NULL;
+ cairo_surface_t *surface = NULL;
+ GdkVisual *visual = gdk_drawable_get_visual (drawable);
+
+ gdk_drawable_get_size (drawable, &width, &height);
+ if (visual)
+ surface = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable),
+ GDK_DRAWABLE_XID (drawable),
+ GDK_VISUAL_XVISUAL (visual),
+ width, height);
+ else if (gdk_drawable_get_depth (drawable) == 1)
+ surface = cairo_xlib_surface_create_for_bitmap
+ (GDK_PIXMAP_XDISPLAY (drawable),
+ GDK_PIXMAP_XID (drawable),
+ GDK_SCREEN_XSCREEN (gdk_drawable_get_screen (drawable)),
+ width, height);
+ else {
+ g_warning ("Using Cairo rendering requires the drawable argument to\n"
+ "have a specified colormap. All windows have a colormap,\n"
+ "however, pixmaps only have colormap by default if they\n"
+ "were created with a non-NULL window argument. Otherwise\n"
+ "a colormap must be set on them with "
+ "gdk_drawable_set_colormap");
+ return NULL;
+ }
+ if (surface) {
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ }
+ return cr;
+}
+#endif
+
+static gboolean
+handle_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer data)
+{
+ cairo_t *cr;
+
+ cr = gdk_cairo_create (widget->window);
+
+ draw (cr, widget->allocation.width, widget->allocation.height);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+static gboolean
+handle_key_press (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
+{
+ if ((event->keyval == GDK_Q ||
+ event->keyval == GDK_q) && (event->state & GDK_CONTROL_MASK))
+ gtk_main_quit ();
+
+ return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window, *drawing_area;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT);
+ gtk_window_set_title (GTK_WINDOW (window), "cairo demo");
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_container_add (GTK_CONTAINER (window), drawing_area);
+
+ g_signal_connect (drawing_area, "expose-event",
+ G_CALLBACK (handle_expose), NULL);
+
+ g_signal_connect (window, "key-press-event",
+ G_CALLBACK (handle_key_press), NULL);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/doc/tutorial/src/include/cairo-tutorial-pdf.h b/doc/tutorial/src/include/cairo-tutorial-pdf.h
new file mode 100644
index 000000000..00d0f188e
--- /dev/null
+++ b/doc/tutorial/src/include/cairo-tutorial-pdf.h
@@ -0,0 +1,74 @@
+/* cairo-tutorial-png.h - a tutorial framework for cairo to write a PNG image
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <cairo.h>
+#include <cairo-pdf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr, int width, int height);
+
+int
+main (int argc, char **argv)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *filename, *dash;
+
+ filename = strdup (argv[0]);
+ assert (filename != NULL);
+
+ dash = strrchr (filename, '-');
+
+ if (strcmp (dash, "-pdf") == 0) {
+ *dash = '.';
+ } else {
+ char *new_filename;
+ new_filename = malloc (strlen (filename) + 5);
+ sprintf (new_filename, "%s.pdf", filename);
+ free (filename);
+ filename = new_filename;
+ }
+
+ surface = cairo_pdf_surface_create (filename, WIDTH, HEIGHT);
+
+ cr = cairo_create (surface);
+
+ draw (cr, WIDTH, HEIGHT);
+
+ cairo_show_page (cr);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ free (filename);
+
+ return 0;
+}
diff --git a/doc/tutorial/src/include/cairo-tutorial-png.h b/doc/tutorial/src/include/cairo-tutorial-png.h
new file mode 100644
index 000000000..428baf294
--- /dev/null
+++ b/doc/tutorial/src/include/cairo-tutorial-png.h
@@ -0,0 +1,74 @@
+/* cairo-tutorial-png.h - a tutorial framework for cairo to write a PNG image
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <cairo.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr, int width, int height);
+
+int
+main (int argc, char **argv)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *filename, *dash;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ WIDTH, HEIGHT);
+
+ cr = cairo_create (surface);
+
+ draw (cr, WIDTH, HEIGHT);
+
+ filename = strdup (argv[0]);
+ assert (filename != NULL);
+
+ dash = strrchr (filename, '-');
+
+ if (strcmp (dash, "-png") == 0) {
+ *dash = '.';
+ } else {
+ char *new_filename;
+ new_filename = malloc (strlen (filename) + 5);
+ sprintf (new_filename, "%s.png", filename);
+ free (filename);
+ filename = new_filename;
+ }
+
+ cairo_surface_write_to_png (surface, filename);
+
+ free (filename);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ return 0;
+}
diff --git a/doc/tutorial/src/include/cairo-tutorial-xlib.h b/doc/tutorial/src/include/cairo-tutorial-xlib.h
new file mode 100644
index 000000000..5e78d0354
--- /dev/null
+++ b/doc/tutorial/src/include/cairo-tutorial-xlib.h
@@ -0,0 +1,251 @@
+/* cairo-tutorial-xlib.h - a tutorial framework for cairo with xlib
+ *
+ * Copyright © 2005, Keith Packard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <strings.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+#ifndef DEFAULT_VISUAL
+#define DEFAULT_VISUAL 0
+#endif
+
+static void
+Usage (char *program)
+{
+ fprintf (stderr, "Usage: %s\n", program);
+ fprintf (stderr, "\t-display <display-name>\n");
+ fprintf (stderr, "\t-geometry <geometry>\n");
+ exit (1);
+}
+
+char *dpy_name;
+VisualID vid = DEFAULT_VISUAL;
+Colormap colormap;
+Visual *visual;
+int depth;
+unsigned int width = WIDTH, height = HEIGHT;
+Window win;
+Pixmap pix;
+GC gc;
+
+static void
+draw (cairo_t *cr, int width, int height);
+
+static void
+draw_to_pixmap (Display *dpy, Pixmap pix)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_xlib_surface_create (dpy, pix, visual,
+ width, height);
+ cr = cairo_create (surface);
+
+ draw (cr, width, height);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+}
+
+static void
+handle_configure (Display *dpy, XConfigureEvent *cev)
+{
+ width = cev->width;
+ height = cev->height;
+
+ XFreePixmap(dpy, pix);
+ pix = XCreatePixmap(dpy, win, width, height, depth);
+ XFillRectangle(dpy, pix, gc, 0, 0, width, height);
+ draw_to_pixmap (dpy, pix);
+}
+
+static void
+handle_expose (Display *dpy, XExposeEvent *eev)
+{
+ XCopyArea (dpy, pix, win, gc,
+ eev->x, eev->y,
+ eev->width, eev->height,
+ eev->x, eev->y);
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ Display *dpy;
+ Window root = 0;
+ char **init_argv = argv;
+ XSetWindowAttributes attr;
+ int scr;
+ int x = 0, y = 0;
+ int geometryMask;
+ int border_width = 1;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ XClassHint classHints;
+ XEvent ev;
+ XEvent eev;
+ int HasExpose = 0;
+ int sync = 0;
+ XTextProperty wm_name, icon_name;
+ Atom wm_delete_window;
+ unsigned long gc_mask;
+ XGCValues gcv;
+ char quit_string[10];
+ unsigned long window_mask;
+ int has_colormap = 0;
+
+ wm_name.value = (unsigned char *) argv[0];
+ wm_name.encoding = XA_STRING;
+ wm_name.format = 8;
+ wm_name.nitems = strlen (argv[0]) + 1;
+ icon_name = wm_name;
+ gc_mask = 0;
+ while (*++argv) {
+ if (!strcmp (*argv, "-display"))
+ dpy_name = *++argv;
+ else if (!strcmp (*argv, "-visual"))
+ vid = strtol(*++argv, NULL, 0);
+ else if (!strcmp (*argv, "-geometry"))
+ geometryMask = XParseGeometry (*++argv, &x, &y, &width, &height);
+ else if (!strcmp (*argv, "-sync"))
+ sync = 1;
+ else if (!strcmp (*argv, "-bw"))
+ border_width = strtol(*++argv, NULL, 0);
+ else if (!strcmp (*argv, "-root"))
+ root = strtol (*++argv, NULL, 0);
+ else
+ Usage (*init_argv);
+ }
+ sizeHints.flags = 0;
+ wmHints.flags = InputHint;
+ wmHints.input = True;
+ classHints.res_name = init_argv[0];
+ classHints.res_class = init_argv[0];
+ dpy = XOpenDisplay (dpy_name);
+ if (!dpy) {
+ fprintf (stderr, "Error: failed to open display: %s\n",
+ XDisplayName (dpy_name));
+ exit (1);
+ }
+ if (sync)
+ XSynchronize (dpy, sync);
+ scr = DefaultScreen (dpy);
+ if (!root)
+ root = RootWindow (dpy, scr);
+ window_mask = CWBackPixel|CWBorderPixel|CWEventMask;
+ if (!has_colormap)
+ colormap = DefaultColormap (dpy, scr);
+ else
+ {
+ window_mask |= CWColormap;
+ attr.colormap = colormap;
+ }
+ visual = DefaultVisual (dpy, scr);
+ depth = DefaultDepth (dpy, scr);
+ if (vid)
+ {
+ XVisualInfo vi, *vi_ret;
+ int n;
+
+ vi.visualid = vid;
+ vi.screen = scr;
+ vi_ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask,
+ &vi, &n);
+ if (vi_ret)
+ {
+ visual = vi_ret->visual;
+ if (!has_colormap)
+ {
+ colormap = XCreateColormap (dpy, root, visual, AllocNone);
+ window_mask |= CWColormap;
+ attr.colormap = colormap;
+ }
+ depth = vi_ret->depth;
+ }
+ }
+ attr.background_pixel = WhitePixel (dpy, scr);
+ attr.border_pixel = 0;
+ attr.event_mask = ExposureMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask;
+ wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ win = XCreateWindow (dpy, root, x, y, width, height, border_width,
+ depth, InputOutput,
+ visual,
+ window_mask,
+ &attr);
+ pix = XCreatePixmap (dpy, win, width, height, depth);
+ gcv.foreground = WhitePixel (dpy, scr);
+ gc = XCreateGC (dpy, pix, GCForeground, &gcv);
+ XFillRectangle(dpy, pix, gc, 0, 0, width, height);
+ draw_to_pixmap (dpy, pix);
+ XSetWMProperties (dpy, win,
+ &wm_name, &icon_name,
+ init_argv, argc,
+ &sizeHints, &wmHints, 0);
+ XSetWMProtocols (dpy, win, &wm_delete_window, 1);
+ XMapWindow (dpy, win);
+ for (;;) {
+ XNextEvent (dpy, &ev);
+ if (HasExpose && ev.type != Expose) {
+ HasExpose = 0;
+ handle_expose (dpy, &eev.xexpose);
+ }
+ switch (ev.type) {
+ case ConfigureNotify:
+ handle_configure (dpy, &ev.xconfigure);
+ break;
+ case Expose:
+ if (QLength(dpy)) {
+ eev = ev;
+ HasExpose = 1;
+ } else if (ev.xexpose.count == 0) {
+ handle_expose (dpy, &ev.xexpose);
+ }
+ break;
+ case KeyPress:
+ if (XLookupString ((XKeyEvent *) &ev, quit_string, sizeof (quit_string), 0, 0) == 1) {
+ switch (quit_string[0]) {
+ case 'q':
+ exit (0);
+ case 'c':
+ XClearArea (dpy, ev.xkey.window, 0, 0, 0, 0, True);
+ break;
+ }
+ }
+ break;
+ case ClientMessage:
+ exit (0);
+ }
+ }
+}
diff --git a/doc/tutorial/src/include/cairo-tutorial.h b/doc/tutorial/src/include/cairo-tutorial.h
new file mode 100644
index 000000000..ec738e915
--- /dev/null
+++ b/doc/tutorial/src/include/cairo-tutorial.h
@@ -0,0 +1,40 @@
+/* cairo-tutorial-gtk.h - a tutorial framework for cairo
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <cairo.h>
+#include <math.h>
+
+/* The application program may override these before including
+ * cairo-tutorial.h in order to get a window of a different size. */
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+#ifdef CAIRO_TUTORIAL_GTK
+#include "cairo-tutorial-gtk.h"
+#elif CAIRO_TUTORIAL_XLIB
+#include "cairo-tutorial-xlib.h"
+#elif CAIRO_TUTORIAL_PDF
+#include "cairo-tutorial-pdf.h"
+#elif CAIRO_TUTORIAL_PNG
+#include "cairo-tutorial-png.h"
+#endif
diff --git a/doc/tutorial/src/lca.c b/doc/tutorial/src/lca.c
new file mode 100644
index 000000000..0b131afaf
--- /dev/null
+++ b/doc/tutorial/src/lca.c
@@ -0,0 +1,32 @@
+#define WIDTH 750
+#define HEIGHT 360
+
+#include "cairo-tutorial.h"
+
+static void
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_save (cr);
+
+ cairo_translate (cr, 60, 60);
+ cairo_scale (cr, 3, 3);
+
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_width (cr, 20);
+
+ /* L */
+ cairo_move_to (cr, 0, 0);
+ cairo_line_to (cr, 0, 80);
+ cairo_line_to (cr, 50, 80);
+
+ /* C */
+ cairo_move_to (cr, 110 + 40 * cos (M_PI / 3), 40 + 40 * sin(M_PI / 3));
+ cairo_arc (cr, 110, 40, 40, M_PI / 3, -M_PI / 3);
+
+ /* A */
+ cairo_move_to (cr, 160, 80);
+ cairo_curve_to (cr, 160, -30, 210, -30, 210, 80);
+
+ cairo_stroke (cr);
+}
diff --git a/doc/tutorial/src/singular.c b/doc/tutorial/src/singular.c
new file mode 100644
index 000000000..958b2b047
--- /dev/null
+++ b/doc/tutorial/src/singular.c
@@ -0,0 +1,162 @@
+/**
+ * Uses Singular values of transformation matrix to find the length of the
+ * major and minor axes of the scaled pen.
+ *
+ * Put this file in cairo/doc/tutorial/src and type "make"
+ */
+
+#define WIDTH 300
+#define HEIGHT 300
+
+#include "cairo-tutorial.h"
+
+#include <math.h>
+
+/*
+ * Finds the singular values of the non-translation part of matrix.
+ *
+ * Let M be the cairo transformation matrix in question:
+ *
+ * ⌈xx xy⌉
+ * M = |yx yy|
+ * ⌊x0 y0⌋
+ *
+ * The non-translation part is:
+ *
+ * A = ⌈xx xy⌉
+ * ⌊yx yy⌋
+ *
+ * The non-zero singular values of A are the square roots of the non-zero
+ * eigenvalues of A⁺ A, where A⁺ is A-transpose.
+ *
+ * A⁺ A = ⌈xx yx⌉⌈xx xy⌉ = ⌈xx²+yx² xx*xy+yx*yy⌉
+ * ⌊xy yy⌋⌊yx yy⌋ ⌊xx*xy+yx*yy xy²+yy²⌋
+ *
+ * Name those:
+ *
+ * B = A⁺ A = ⌈a k⌉
+ * ⌊k b⌋
+ *
+ * The eigenvalues of B satisfy:
+ *
+ * λ² - (a+b).λ + a.b - k² = 0
+ *
+ * The eigenvalues are:
+ * __________________
+ * (a+b) ± √(a+b)² - 4(a.b-k²)
+ * λ = ---------------------------
+ * 2
+ * that simplifies to:
+ * _______________
+ * λ = (a+b)/2 ± √((a-b)/2)² + k²
+ *
+ * And the Singular values are the root of λs.
+ *
+ */
+static void
+get_singular_values (const cairo_matrix_t *matrix,
+ double *major,
+ double *minor)
+{
+ double xx = matrix->xx, xy = matrix->xy;
+ double yx = matrix->yx, yy = matrix->yy;
+
+ double a = xx*xx+yx*yx;
+ double b = xy*xy+yy*yy;
+ double k = xx*xy+yx*yy;
+
+ double f = (a+b) * .5;
+ double g = (a-b) * .5;
+ double delta = sqrt (g*g + k*k);
+
+ if (major)
+ *major = sqrt (f + delta);
+ if (minor)
+ *minor = sqrt (f - delta);
+}
+
+/*
+ * Finds the length of the major and minor axes of the pen for a cairo_t,
+ * identified by the current transformation matrix and line width.
+ *
+ * Returned values are in device units.
+ */
+static void
+get_pen_axes (cairo_t *cr,
+ double *major,
+ double *minor)
+{
+ double width;
+ cairo_matrix_t matrix;
+
+ width = cairo_get_line_width (cr);
+ cairo_get_matrix (cr, &matrix);
+
+ get_singular_values (&matrix, major, minor);
+
+ if (major)
+ *major *= width;
+ if (minor)
+ *minor *= width;
+}
+
+static void
+draw (cairo_t *cr, int width, int height)
+{
+ double major_width, minor_width;
+
+ /* clear background */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+ cairo_paint (cr);
+
+#define W width
+#define H height
+#define B ((width+height)/16)
+
+ /* the spline we want to stroke */
+ cairo_move_to (cr, W-B, B);
+ cairo_curve_to (cr, -W, B,
+ 2*W, H-B,
+ B, H-B);
+
+ /* the effect is show better with round caps */
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+ /* set the skewed pen */
+ cairo_rotate (cr, +.7);
+ cairo_scale (cr, .5, 2.);
+ cairo_rotate (cr, -.7);
+ cairo_set_line_width (cr, B);
+
+ get_pen_axes (cr, &major_width, &minor_width);
+
+ /* stroke with "major" pen in translucent red */
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+ cairo_set_line_width (cr, major_width);
+ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, .9);
+ cairo_stroke_preserve (cr);
+ cairo_restore (cr);
+
+ /* stroke with skewed pen in translucent black */
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, .9);
+ cairo_stroke_preserve (cr);
+
+ /* stroke with "minor" pen in translucent yellow */
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+ cairo_set_line_width (cr, minor_width);
+ cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, .9);
+ cairo_stroke_preserve (cr);
+ cairo_restore (cr);
+
+ /* stroke with hairline in black */
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_stroke_preserve (cr);
+ cairo_restore (cr);
+
+ cairo_new_path (cr);
+}
diff --git a/doc/tutorial/src/twin.c b/doc/tutorial/src/twin.c
new file mode 100644
index 000000000..14347bac2
--- /dev/null
+++ b/doc/tutorial/src/twin.c
@@ -0,0 +1,39 @@
+/**
+ * Put this file in cairo/doc/tutorial/src and type "make"
+ */
+
+#define WIDTH 1350
+#define HEIGHT 900
+
+#include "cairo-tutorial.h"
+
+
+static void
+draw (cairo_t *cr, int width, int height)
+{
+ int i, j, h;
+ unsigned char s[2] = {0, 0};
+
+ /* clear background */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_select_font_face (cr,
+ "@cairo:",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+
+ h = 2;
+ for (i = 8; i < 48; i >= 24 ? i+=3 : i++) {
+ cairo_set_font_size (cr, i);
+ for (j = 33; j < 128; j++) {
+ if (j == 33 || (j == 80 && i > 24)) {
+ h += i + 2;
+ cairo_move_to (cr, 10, h);
+ }
+ s[0] = j;
+ cairo_show_text (cr, (const char *) s);
+ }
+ }
+}