[cairo-commit] 40 commits - doc/public src/cairo-analysis-surface.c src/cairo-analysis-surface-private.h src/cairo-bentley-ottmann.c src/cairo.c src/cairo-deprecated.h src/cairo-font-face.c src/cairo-ft-font.c src/cairo-ft-private.h src/cairo.h src/cairo-image-surface.c src/cairoint.h src/cairo-lzw.c src/cairo-matrix.c src/cairo-meta-surface.c src/cairo-meta-surface-private.h src/cairo-misc.c src/cairo-mutex-type-private.h src/cairo-output-stream.c src/cairo-paginated-private.h src/cairo-paginated-surface.c src/cairo-path-fixed.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-quartz-font.c src/cairo-quartz-image-surface.c src/cairo-rectangle.c src/cairo-scaled-font.c src/cairo-surface.c src/cairo-svg-surface.c src/cairo-traps.c src/cairo-types-private.h src/cairo-user-font.c src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/check-doc-syntax.sh src/Makefile.am src/test-paginated-surface.c test/cairo-test.c test/cairo-test.h test/.gitignore test/Makefile.am test/user-font.c test/user-font-pdf-ref.png test/user-font-ref.png test/user-font-svg-ref.png

Behdad Esfahbod behdad at kemper.freedesktop.org
Fri May 9 16:28:12 PDT 2008


 doc/public/cairo-docs.xml            |    1 
 doc/public/cairo-sections.txt        |    9 
 doc/public/tmpl/cairo-font-face.sgml |    1 
 doc/public/tmpl/cairo-status.sgml    |    3 
 src/Makefile.am                      |    7 
 src/cairo-analysis-surface-private.h |   12 
 src/cairo-analysis-surface.c         |  141 +++++++---
 src/cairo-bentley-ottmann.c          |    6 
 src/cairo-deprecated.h               |    4 
 src/cairo-font-face.c                |    3 
 src/cairo-ft-font.c                  |   16 -
 src/cairo-ft-private.h               |    3 
 src/cairo-image-surface.c            |    6 
 src/cairo-lzw.c                      |    2 
 src/cairo-matrix.c                   |   12 
 src/cairo-meta-surface-private.h     |    4 
 src/cairo-meta-surface.c             |   74 +++++
 src/cairo-misc.c                     |    6 
 src/cairo-mutex-type-private.h       |   32 +-
 src/cairo-output-stream.c            |    6 
 src/cairo-paginated-private.h        |   12 
 src/cairo-paginated-surface.c        |    2 
 src/cairo-path-fixed.c               |   52 +++
 src/cairo-pattern.c                  |   13 
 src/cairo-pdf-surface.c              |    6 
 src/cairo-ps-surface.c               |    5 
 src/cairo-quartz-font.c              |   12 
 src/cairo-quartz-image-surface.c     |   15 -
 src/cairo-rectangle.c                |   35 ++
 src/cairo-scaled-font.c              |   46 +++
 src/cairo-surface.c                  |   48 ++-
 src/cairo-svg-surface.c              |    5 
 src/cairo-traps.c                    |   56 +++-
 src/cairo-types-private.h            |   11 
 src/cairo-user-font.c                |  486 +++++++++++++++++++++++++++++++++++
 src/cairo-win32-font.c               |   27 +
 src/cairo-win32-printing-surface.c   |   16 -
 src/cairo.c                          |    7 
 src/cairo.h                          |   82 +++++
 src/cairoint.h                       |   91 ++++--
 src/check-doc-syntax.sh              |   45 +--
 src/test-paginated-surface.c         |    5 
 test/.gitignore                      |    1 
 test/Makefile.am                     |    4 
 test/cairo-test.c                    |   31 ++
 test/cairo-test.h                    |    3 
 test/user-font-pdf-ref.png           |binary
 test/user-font-ref.png               |binary
 test/user-font-svg-ref.png           |binary
 test/user-font.c                     |  236 ++++++++++++++++
 50 files changed, 1491 insertions(+), 209 deletions(-)

New commits:
commit 17f21ea3071ef5d7833c615271b18ae35673c349
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 16:01:37 2008 +0200

    [cairo-user-font] Implement user fonts

diff --git a/doc/public/tmpl/cairo-font-face.sgml b/doc/public/tmpl/cairo-font-face.sgml
index 2dc6674..1bb686d 100644
--- a/doc/public/tmpl/cairo-font-face.sgml
+++ b/doc/public/tmpl/cairo-font-face.sgml
@@ -69,6 +69,7 @@ cairo_get_font_face().
 @CAIRO_FONT_TYPE_FT: 
 @CAIRO_FONT_TYPE_WIN32: 
 @CAIRO_FONT_TYPE_QUARTZ: 
+ at CAIRO_FONT_TYPE_USER: 
 
 <!-- ##### FUNCTION cairo_font_face_get_type ##### -->
 <para>
diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml
index 9b2bbe1..143ce81 100644
--- a/doc/public/tmpl/cairo-status.sgml
+++ b/doc/public/tmpl/cairo-status.sgml
@@ -63,6 +63,9 @@ code is required before or after each individual cairo function call.
 @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: 
 @CAIRO_STATUS_TEMP_FILE_ERROR: 
 @CAIRO_STATUS_INVALID_STRIDE: 
+ at CAIRO_STATUS_FONT_TYPE_MISMATCH: 
+ at CAIRO_STATUS_USER_FONT_IMMUTABLE: 
+ at CAIRO_STATUS_USER_FONT_ERROR: 
 
 <!-- ##### FUNCTION cairo_status_to_string ##### -->
 <para>
diff --git a/src/Makefile.am b/src/Makefile.am
index e5382d3..c52a7a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,6 +63,7 @@ cairo_base_sources =				\
 	cairo-surface-fallback-private.h	\
 	cairo-surface-private.h			\
 	cairo-traps.c				\
+	cairo-user-font.c			\
 	cairo-unicode.c				\
 	cairo-output-stream.c			\
 	cairo-output-stream-private.h		\
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index b85d98f..02c8873 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -103,6 +103,10 @@ cairo_status_to_string (cairo_status_t status)
 	return "invalid value for stride";
     case CAIRO_STATUS_FONT_TYPE_MISMATCH:
 	return "the font type is not appropriate for the operation";
+    case CAIRO_STATUS_USER_FONT_IMMUTABLE:
+	return "the user-font is immutable";
+    case CAIRO_STATUS_USER_FONT_ERROR:
+	return "error occurred in a user-font callback function";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
new file mode 100644
index 0000000..6422d1b
--- /dev/null
+++ b/src/cairo-user-font.c
@@ -0,0 +1,486 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2006, 2008 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *      Kristian Høgsberg <krh at redhat.com>
+ *      Behdad Esfahbod <behdad at behdad.org>
+ */
+
+#include "cairoint.h"
+#include "cairo-meta-surface-private.h"
+#include "cairo-analysis-surface-private.h"
+
+typedef struct _cairo_user_scaled_font_methods {
+    cairo_user_scaled_font_init_func_t			init;
+    cairo_user_scaled_font_render_glyph_func_t		render_glyph;
+    cairo_user_scaled_font_unicode_to_glyph_func_t	unicode_to_glyph;
+    cairo_user_scaled_font_text_to_glyphs_func_t	text_to_glyphs;
+} cairo_user_scaled_font_methods_t;
+
+typedef struct _cairo_user_font_face {
+    cairo_font_face_t	             base;
+
+    /* Set to true after first scaled font is created.  At that point,
+     * the scaled_font_methods cannot change anymore. */
+    cairo_bool_t		     immutable;
+
+    cairo_user_scaled_font_methods_t scaled_font_methods;
+} cairo_user_font_face_t;
+
+typedef struct _cairo_user_scaled_font {
+    cairo_scaled_font_t  base;
+
+    cairo_text_extents_t default_glyph_extents;
+} cairo_user_scaled_font_t;
+
+/* TODO test user fonts using other fonts in the render_glyph */
+
+/* #cairo_user_scaled_font_t */
+
+const cairo_scaled_font_backend_t cairo_user_scaled_font_backend;
+
+static cairo_int_status_t
+_cairo_user_scaled_glyph_init (void			 *abstract_font,
+			       cairo_scaled_glyph_t	 *scaled_glyph,
+			       cairo_scaled_glyph_info_t  info)
+{
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_user_scaled_font_t *scaled_font = abstract_font;
+    cairo_surface_t *meta_surface = scaled_glyph->meta_surface;
+
+    if (!scaled_glyph->meta_surface) {
+	cairo_user_font_face_t *face =
+	    (cairo_user_font_face_t *) scaled_font->base.font_face;
+	cairo_text_extents_t extents = scaled_font->default_glyph_extents;
+	cairo_t *cr;
+
+	meta_surface = _cairo_meta_surface_create (CAIRO_CONTENT_COLOR_ALPHA, -1, -1);
+	cr = cairo_create (meta_surface);
+
+	cairo_set_matrix (cr, &scaled_font->base.scale);
+	cairo_set_font_size (cr, 1.0);
+	cairo_set_font_options (cr, &scaled_font->base.options);
+
+	status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
+							 _cairo_scaled_glyph_index(scaled_glyph),
+							 cr, &extents);
+
+	if (status == CAIRO_STATUS_SUCCESS)
+	    status = cairo_status (cr);
+
+	cairo_destroy (cr);
+
+	if (status) {
+	    cairo_surface_destroy (meta_surface);
+	    return status;
+	}
+
+	_cairo_scaled_glyph_set_meta_surface (scaled_glyph,
+					      &scaled_font->base,
+					      meta_surface);
+
+
+	/* set metrics */
+
+	if (extents.width == 0.) {
+	    /* Compute extents.x/y/width/height from meta_surface, in font space */
+
+	    cairo_box_t bbox;
+	    double x1, y1, x2, y2;
+	    cairo_surface_t *null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
+	    cairo_surface_t *analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
+	    cairo_surface_destroy (null_surface);
+
+	    _cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->base.scale_inverse);
+	    status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
+	    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
+	    cairo_surface_destroy (analysis_surface);
+
+	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
+
+	    extents.x_bearing = x1;
+	    extents.y_bearing = y1;
+	    extents.width     = x2 - x1;
+	    extents.height    = y2 - y1;
+	}
+
+	_cairo_scaled_glyph_set_metrics (scaled_glyph,
+					 &scaled_font->base,
+					 &extents);
+    }
+
+    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
+	cairo_surface_t	*surface;
+	cairo_status_t status = CAIRO_STATUS_SUCCESS;
+	int width, height;
+
+	/* TODO: extend the glyph cache to support argb glyphs */
+
+	width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
+	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
+	height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
+	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
+	/* XXX handle / figure out antialias/subpixel font options to choose
+	 * the right format here? */
+	surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+
+	cairo_surface_set_device_offset (surface,
+					 -scaled_glyph->metrics.x_bearing,
+					 -scaled_glyph->metrics.y_bearing);
+	status = _cairo_meta_surface_replay (meta_surface, surface);
+
+	if (status) {
+	    cairo_surface_destroy(surface);
+	    return status;
+	}
+
+	_cairo_scaled_glyph_set_surface (scaled_glyph,
+					 &scaled_font->base,
+					 (cairo_image_surface_t *) surface);
+    }
+
+    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
+	cairo_path_fixed_t *path = _cairo_path_fixed_create ();
+	if (!path)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	status = _cairo_meta_surface_get_path (meta_surface, path);
+
+	if (status) {
+	    _cairo_path_fixed_destroy (path);
+	    return status;
+	}
+
+	_cairo_scaled_glyph_set_path (scaled_glyph,
+				      &scaled_font->base,
+				      path);
+    }
+
+    return status;
+}
+
+static unsigned long
+_cairo_user_ucs4_to_index (void	    *abstract_font,
+			   uint32_t  ucs4)
+{
+    cairo_user_scaled_font_t *scaled_font = abstract_font;
+    cairo_user_font_face_t *face =
+	(cairo_user_font_face_t *) scaled_font->base.font_face;
+    unsigned long glyph = 0;
+
+    if (face->scaled_font_methods.unicode_to_glyph) {
+	cairo_status_t status;
+
+	status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
+							     ucs4, &glyph);
+
+	if (status != CAIRO_STATUS_SUCCESS) {
+	    status = _cairo_scaled_font_set_error (&scaled_font->base, status);
+	    glyph = 0;
+	}
+
+    } else {
+	glyph = ucs4;
+    }
+
+    return glyph;
+}
+
+static cairo_int_status_t
+_cairo_user_text_to_glyphs (void           *abstract_font,
+			    double          x,
+			    double          y,
+			    const char     *utf8,
+			    cairo_glyph_t **glyphs,
+			    int	           *num_glyphs)
+{
+    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    cairo_user_scaled_font_t *scaled_font = abstract_font;
+    cairo_user_font_face_t *face =
+	(cairo_user_font_face_t *) scaled_font->base.font_face;
+
+    if (face->scaled_font_methods.text_to_glyphs) {
+	int i;
+
+	*glyphs = NULL;
+
+	status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
+							   utf8, glyphs, num_glyphs);
+
+	if (status != CAIRO_STATUS_SUCCESS) {
+	    status = _cairo_scaled_font_set_error (&scaled_font->base, status);
+	    if (*glyphs) {
+		free (*glyphs);
+		*glyphs = NULL;
+	    }
+	    return status;
+	}
+
+	/* Convert from font space to user space and add x,y */
+	for (i = 0; i < *num_glyphs; i++) {
+	    double gx = (*glyphs)[i].x;
+	    double gy = (*glyphs)[i].y;
+
+	    cairo_matrix_transform_point (&scaled_font->base.font_matrix,
+					  &gx, &gy);
+
+	    (*glyphs)[i].x = gx + x;
+	    (*glyphs)[i].y = gy + y;
+	}
+    }
+
+    return status;
+}
+
+const cairo_scaled_font_backend_t cairo_user_scaled_font_backend = {
+    CAIRO_FONT_TYPE_USER,
+    NULL,	/* create_toy */
+    NULL,	/* scaled_font_fini */
+    _cairo_user_scaled_glyph_init,
+    _cairo_user_text_to_glyphs,
+    _cairo_user_ucs4_to_index,
+    NULL,	/* show_glyphs */
+    NULL,	/* load_truetype_table */
+    NULL,	/* map_glyphs_to_unicode */
+};
+
+/* #cairo_user_font_face_t */
+
+static cairo_status_t
+_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
+					  const cairo_matrix_t        *font_matrix,
+					  const cairo_matrix_t        *ctm,
+					  const cairo_font_options_t  *options,
+					  cairo_scaled_font_t        **scaled_font)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_user_font_face_t *font_face = abstract_face;
+    cairo_user_scaled_font_t *user_scaled_font = NULL;
+    cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
+
+    font_face->immutable = TRUE;
+
+    user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
+    if (user_scaled_font == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    status = _cairo_scaled_font_init (&user_scaled_font->base,
+				      &font_face->base,
+				      font_matrix, ctm, options,
+				      &cairo_user_scaled_font_backend);
+
+    if (status) {
+	free (user_scaled_font);
+	return status;
+    }
+
+    if (font_face->scaled_font_methods.init != NULL)
+	status = font_face->scaled_font_methods.init (&user_scaled_font->base,
+						      &font_extents);
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
+
+
+    if (status != CAIRO_STATUS_SUCCESS) {
+        _cairo_scaled_font_fini (&user_scaled_font->base);
+	free (user_scaled_font);
+    } else {
+        user_scaled_font->default_glyph_extents.x_bearing = 0.;
+        user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
+        user_scaled_font->default_glyph_extents.width = 0.;
+        user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
+        user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
+        user_scaled_font->default_glyph_extents.y_advance = 0.; /* XXX */
+
+	*scaled_font = &user_scaled_font->base;
+    }
+
+    return status;
+}
+
+static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
+    CAIRO_FONT_TYPE_USER,
+    NULL,	/* destroy */
+    _cairo_user_font_face_scaled_font_create
+};
+
+
+/* Implement the public interface */
+
+/**
+ * cairo_user_font_face_create:
+ *
+ * TODO: document this
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ *
+ * Since: 1.8
+ **/
+cairo_font_face_t *
+cairo_user_font_face_create (void)
+{
+    cairo_user_font_face_t *font_face;
+
+    font_face = malloc (sizeof (cairo_user_font_face_t));
+    if (!font_face) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_font_face_t *)&_cairo_font_face_nil;
+    }
+
+    _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
+
+    font_face->immutable = FALSE;
+    memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
+
+    return &font_face->base;
+}
+
+/* User-font method setters */
+
+static cairo_bool_t
+_cairo_font_face_is_user (cairo_font_face_t *font_face)
+{
+    return font_face->backend == &_cairo_user_font_face_backend;
+}
+
+
+void
+cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
+				    cairo_user_scaled_font_init_func_t  init_func)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return;
+    }
+    if (user_font_face->immutable) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
+	    return;
+    }
+    user_font_face->scaled_font_methods.init = init_func;
+}
+
+void
+cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
+					    cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return;
+    }
+    if (user_font_face->immutable) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
+	    return;
+    }
+    user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
+}
+
+void
+cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
+						cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return;
+    }
+    if (user_font_face->immutable) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
+	    return;
+    }
+    user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
+}
+
+void
+cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
+					      cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return;
+    }
+    if (user_font_face->immutable) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
+	    return;
+    }
+    user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
+}
+
+/* User-font method getters */
+
+cairo_user_scaled_font_init_func_t
+cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return NULL;
+    }
+    return user_font_face->scaled_font_methods.init;
+}
+
+cairo_user_scaled_font_render_glyph_func_t
+cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return NULL;
+    }
+    return user_font_face->scaled_font_methods.render_glyph;
+}
+
+cairo_user_scaled_font_unicode_to_glyph_func_t
+cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return NULL;
+    }
+    return user_font_face->scaled_font_methods.unicode_to_glyph;
+}
+
+cairo_user_scaled_font_text_to_glyphs_func_t
+cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
+{
+    cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
+    if (! _cairo_font_face_is_user (font_face)) {
+	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
+	    return NULL;
+    }
+    return user_font_face->scaled_font_methods.text_to_glyphs;
+}
diff --git a/src/cairo.h b/src/cairo.h
index 4ac8f32..2116f00 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -204,6 +204,8 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
  * @CAIRO_STATUS_INVALID_STRIDE: invalid value for stride (Since 1.6)
  * @CAIRO_STATUS_FONT_TYPE_MISMATCH: the font type is not appropriate for the operation (Since 1.8)
+ * @CAIRO_STATUS_USER_FONT_IMMUTABLE: the user-font is immutable (Since 1.8)
+ * @CAIRO_STATUS_USER_FONT_ERROR: error occurred in a user-font callback function (Since 1.8)
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -239,7 +241,9 @@ typedef enum _cairo_status {
     CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
     CAIRO_STATUS_TEMP_FILE_ERROR,
     CAIRO_STATUS_INVALID_STRIDE,
-    CAIRO_STATUS_FONT_TYPE_MISMATCH
+    CAIRO_STATUS_FONT_TYPE_MISMATCH,
+    CAIRO_STATUS_USER_FONT_IMMUTABLE,
+    CAIRO_STATUS_USER_FONT_ERROR
     /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairoint.h */
 } cairo_status_t;
 
@@ -1153,12 +1157,14 @@ cairo_font_face_get_reference_count (cairo_font_face_t *font_face);
 cairo_public cairo_status_t
 cairo_font_face_status (cairo_font_face_t *font_face);
 
+
 /**
  * cairo_font_type_t:
  * @CAIRO_FONT_TYPE_TOY: The font was created using cairo's toy font api
  * @CAIRO_FONT_TYPE_FT: The font is of type FreeType
  * @CAIRO_FONT_TYPE_WIN32: The font is of type Win32
  * @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6)
+ * @CAIRO_FONT_TYPE_USER: The font was create using cairo's user font api (Since: 1.8)
  *
  * #cairo_font_type_t is used to describe the type of a given font
  * face or scaled font. The font types are also known as "font
@@ -1193,7 +1199,8 @@ typedef enum _cairo_font_type {
     CAIRO_FONT_TYPE_TOY,
     CAIRO_FONT_TYPE_FT,
     CAIRO_FONT_TYPE_WIN32,
-    CAIRO_FONT_TYPE_QUARTZ
+    CAIRO_FONT_TYPE_QUARTZ,
+    CAIRO_FONT_TYPE_USER
 } cairo_font_type_t;
 
 cairo_public cairo_font_type_t
@@ -1272,6 +1279,63 @@ cairo_public void
 cairo_scaled_font_get_font_options (cairo_scaled_font_t		*scaled_font,
 				    cairo_font_options_t	*options);
 
+/* User fonts */
+
+cairo_public cairo_font_face_t *
+cairo_user_font_face_create (void);
+
+/* User-font method signatures */
+
+typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_t  *scaled_font,
+							      cairo_font_extents_t *extents);
+
+typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scaled_font_t  *scaled_font,
+								      unsigned long         glyph,
+								      cairo_t              *cr,
+								      cairo_text_extents_t *extents);
+
+typedef cairo_status_t (*cairo_user_scaled_font_unicode_to_glyph_func_t) (cairo_scaled_font_t *scaled_font,
+									  unsigned long        unicode,
+									  unsigned long       *glyph_index);
+
+typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t   *scaled_font,
+									const char            *utf8,
+									cairo_glyph_t        **glyphs,
+									int                   *num_glyphs);
+
+/* User-font method setters */
+
+cairo_public void
+cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
+				    cairo_user_scaled_font_init_func_t  init_func);
+
+cairo_public void
+cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
+					    cairo_user_scaled_font_render_glyph_func_t  render_glyph_func);
+
+cairo_public void
+cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
+					        cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func);
+
+cairo_public void
+cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
+					      cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func);
+
+/* User-font method getters */
+
+cairo_public cairo_user_scaled_font_init_func_t
+cairo_user_font_face_get_init_func (cairo_font_face_t *font_face);
+
+cairo_public cairo_user_scaled_font_render_glyph_func_t
+cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face);
+
+cairo_public cairo_user_scaled_font_unicode_to_glyph_func_t
+cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face);
+
+cairo_public cairo_user_scaled_font_text_to_glyphs_func_t
+cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face);
+
+
 /* Query functions */
 
 cairo_public cairo_operator_t
diff --git a/src/cairoint.h b/src/cairoint.h
index 6df8170..b1c0ad7 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -110,7 +110,7 @@ _cairo_win32_tmpfile (void);
  * a bit of a pain, but it should be easy to always catch as long as
  * one adds a new test case to test a trigger of the new status value.
  */
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_FONT_TYPE_MISMATCH
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_USER_FONT_ERROR
 
 
 /* Size in bytes of buffer to use off the stack per functions.
diff --git a/test/.gitignore b/test/.gitignore
index cf61740..65f9a77 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -202,6 +202,7 @@ truetype-tables
 unantialiased-shapes
 unbounded-operator
 user-data
+user-font
 xlib-expose-event
 xlib-surface
 xlib-surface-source
diff --git a/test/Makefile.am b/test/Makefile.am
index 99a7ece..88cc1ed 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -157,6 +157,7 @@ truetype-tables$(EXEEXT)				\
 unantialiased-shapes$(EXEEXT)				\
 unbounded-operator$(EXEEXT)				\
 user-data$(EXEEXT)					\
+user-font$(EXEEXT)					\
 zero-alpha$(EXEEXT)
 
 # XXX: Here are some existing tests that are currently disabled for
@@ -695,6 +696,9 @@ REFERENCE_IMAGES = \
 	unantialiased-shapes-quartz-ref.png \
 	unbounded-operator-ref.png	\
 	unbounded-operator-rgb24-ref.png	\
+	user-font-ref.png	\
+	user-font-pdf-ref.png	\
+	user-font-svg-ref.png	\
 	unbounded-operator-quartz-ref.png	\
 	unbounded-operator-quartz-rgb24-ref.png	\
 	xlib-expose-event-ref.png \
diff --git a/test/user-font-pdf-ref.png b/test/user-font-pdf-ref.png
new file mode 100644
index 0000000..babca10
Binary files /dev/null and b/test/user-font-pdf-ref.png differ
diff --git a/test/user-font-ref.png b/test/user-font-ref.png
new file mode 100644
index 0000000..00c6d43
Binary files /dev/null and b/test/user-font-ref.png differ
diff --git a/test/user-font-svg-ref.png b/test/user-font-svg-ref.png
new file mode 100644
index 0000000..96c53ef
Binary files /dev/null and b/test/user-font-svg-ref.png differ
diff --git a/test/user-font.c b/test/user-font.c
new file mode 100644
index 0000000..3cdf7bc
--- /dev/null
+++ b/test/user-font.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright © 2006, 2008 Red Hat, Inc.
+ *
+ * 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
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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.
+ *
+ * Contributor(s):
+ *	Kristian Høgsberg <krh at redhat.com>
+ *	Behdad Esfahbod <behdad at behdad.org>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cairo-test.h"
+
+/*#define ROTATED 1*/
+
+#define BORDER 10
+#define TEXT_SIZE 64
+#define WIDTH  (TEXT_SIZE * 9.75 + 2*BORDER)
+#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#define TEXT   "cairo user font"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "user-font",
+    "Tests user font feature",
+#ifndef ROTATED
+    WIDTH, HEIGHT,
+#else
+    WIDTH, WIDTH,
+#endif
+    draw
+};
+
+/* Simple glyph definition: 1 - 15 means lineto (or moveto for first
+ * point) for one of the points on this grid:
+ *
+ *      1  2  3
+ *      4  5  6
+ *      7  8  9
+ * ----10 11 12----(baseline)
+ *     13 14 15
+ */
+
+#define END_GLYPH 0
+#define STROKE 13
+#define CLOSE 14
+
+static const struct {
+    unsigned long ucs4;
+    int width;
+    char data[16];
+} glyphs [] = {
+    { -1 ,  0, { END_GLYPH } },
+    { ' ',  1, { END_GLYPH } },
+    { 'c',  3, { 6, 4, 10, 12, STROKE, END_GLYPH } },
+    { 'a',  3, { 4, 6, 12, 10, 7, 8, STROKE, END_GLYPH } },
+    { 'i',  1, { 1, 1, STROKE, 4, 10, STROKE, END_GLYPH } },
+    { 'r',  3, { 4, 10, STROKE, 7, 5, 6, STROKE, END_GLYPH } },
+    { 'o',  3, { 4, 10, 12, 6, CLOSE, END_GLYPH } },
+    { 'u',  3, { 4, 10, 12, 6, STROKE, END_GLYPH } },
+    { 's',  3, { 6, 4, 7, 9, 12, 10, STROKE, END_GLYPH } },
+    { 'e',  3, { 12, 10, 4, 6, 9, 8, STROKE, END_GLYPH } },
+    { 'f',  3, { 3, 2, 11, STROKE, 4, 6, STROKE, END_GLYPH } },
+    { 'n',  3, { 10, 4, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } },
+    { 't',  3, { 2, 11, 12, STROKE, 4, 6, STROKE, END_GLYPH } },
+    { 'h',  3, { 1, 10, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } },
+    { 'l',  1, { 1, 10, STROKE, END_GLYPH } },
+    { '-',  2, { 7, 8, STROKE, END_GLYPH } },
+    { '\0', 0, { END_GLYPH } },
+};
+
+static cairo_status_t
+test_scaled_font_init (cairo_scaled_font_t  *scaled_font,
+		       cairo_font_extents_t *metrics)
+{
+  metrics->ascent  = .75;
+  metrics->descent = .25;
+  return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+test_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
+				   unsigned long        unicode,
+				   unsigned long       *glyph)
+{
+    int i;
+
+    for (i = 0; glyphs[i].ucs4 != '\0'; i++)
+	if (glyphs[i].ucs4 == unicode) {
+	    *glyph = i;
+	    return CAIRO_STATUS_SUCCESS;
+	}
+
+    /* Fall through and default to undefined glyph. */
+    return CAIRO_STATUS_INVALID_INDEX;
+}
+
+static cairo_status_t
+test_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
+			       unsigned long         glyph,
+			       cairo_t              *cr,
+			       cairo_text_extents_t *metrics)
+{
+    int i;
+    const char *data;
+    div_t d;
+    double x, y;
+
+    metrics->x_advance = glyphs[glyph].width / 4.0;
+
+    cairo_set_line_width (cr, 0.1);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+    data = glyphs[glyph].data;
+    for (i = 0; data[i] != END_GLYPH; i++) {
+	switch (data[i]) {
+	case STROKE:
+	    cairo_new_sub_path (cr);
+	    break;
+
+	case CLOSE:
+	    cairo_close_path (cr);
+	    break;
+
+	default:
+	    d = div (data[i] - 1, 3);
+	    x = d.rem / 4.0 + 0.125;
+	    y = d.quot / 5.0 + 0.4 - 1.0;
+	    cairo_line_to (cr, x, y);
+	}
+    }
+    cairo_stroke (cr);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_font_face_t *
+get_user_font_face (void)
+{
+    static cairo_font_face_t *user_font_face = NULL;
+
+    if (!user_font_face) {
+	user_font_face = cairo_user_font_face_create ();
+	cairo_user_font_face_set_init_func             (user_font_face, test_scaled_font_init);
+	cairo_user_font_face_set_render_glyph_func     (user_font_face, test_scaled_font_render_glyph);
+	cairo_user_font_face_set_unicode_to_glyph_func (user_font_face, test_scaled_font_unicode_to_glyph);
+    }
+
+    return user_font_face;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    const char text[] = TEXT;
+    cairo_font_extents_t font_extents;
+    cairo_text_extents_t extents;
+
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+#ifdef ROTATED
+    cairo_translate (cr, TEXT_SIZE, 0);
+    cairo_rotate (cr, .6);
+#endif
+
+    cairo_set_font_face (cr, get_user_font_face ());
+    cairo_set_font_size (cr, TEXT_SIZE);
+
+    cairo_font_extents (cr, &font_extents);
+    cairo_text_extents (cr, text, &extents);
+
+    /* logical boundaries in red */
+    cairo_move_to (cr, 0, BORDER);
+    cairo_rel_line_to (cr, WIDTH, 0);
+    cairo_move_to (cr, 0, BORDER + font_extents.ascent);
+    cairo_rel_line_to (cr, WIDTH, 0);
+    cairo_move_to (cr, 0, BORDER + font_extents.ascent + font_extents.descent);
+    cairo_rel_line_to (cr, WIDTH, 0);
+    cairo_move_to (cr, BORDER, 0);
+    cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
+    cairo_move_to (cr, BORDER + extents.x_advance, 0);
+    cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
+    cairo_set_source_rgba (cr, 1, 0, 0, .8);
+    cairo_set_line_width (cr, 2);
+    cairo_stroke (cr);
+
+    /* ink boundaries in green */
+    cairo_rectangle (cr,
+		     BORDER + extents.x_bearing, BORDER + font_extents.ascent + extents.y_bearing,
+		     extents.width, extents.height);
+    cairo_set_source_rgba (cr, 0, 1, 0, .8);
+    cairo_set_line_width (cr, 2);
+    cairo_stroke (cr);
+
+    /* text in gray */
+    cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+    cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
+    cairo_show_text (cr, text);
+
+
+    /* filled version of text in light blue */
+    cairo_set_source_rgba (cr, 0, 0, 1, 0.5);
+    cairo_move_to (cr, BORDER, BORDER + font_extents.height + 2*BORDER + font_extents.ascent);
+    cairo_text_path (cr, text);
+    cairo_fill (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
commit 9f2971440b59c311d88beeeb31e1d456489b107d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat May 10 01:19:41 2008 +0200

    [doc] Remove cairo-quartz-image-surface from docs
    
    Docs only include stable API.

diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml
index 73eeeda..467a587 100644
--- a/doc/public/cairo-docs.xml
+++ b/doc/public/cairo-docs.xml
@@ -38,6 +38,7 @@
     <!--xi:include href="xml/cairo-beos.xml"/-->
     <xi:include href="xml/cairo-svg.xml"/>
     <xi:include href="xml/cairo-quartz.xml" />
+    <!--xi:include href="xml/cairo-quartz-image.xml"/-->
     <!--xi:include href="xml/cairo-xcb.xml"/-->
     <xi:include href="xml/cairo-xlib.xml"/>
   </chapter>
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 98cc974..1696f15 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -103,12 +103,7 @@ CAIRO_HAS_QUARTZ_SURFACE
 cairo_quartz_surface_create
 cairo_quartz_surface_create_for_cg_context
 cairo_quartz_surface_get_cg_context
-</SECTION>
-
-<SECTION>
-<FILE>cairo-quartz-image</FILE>
-<TITLE>Quartz Image Surfaces</TITLE>
-CAIRO_HAS_QUARTZ_IMAGE_SURFACE
+<SUBSECTION Private>
 cairo_quartz_image_surface_create
 cairo_quartz_image_surface_get_image
 </SECTION>
@@ -528,4 +523,6 @@ cairo_set_target_drawable
 cairo_get_status_string
 cairo_status_string
 CAIRO_FORMAT_RGB16_565
+CAIRO_FONT_TYPE_ATSUI
+cairo_atsui_font_face_create_for_atsu_font_id
 </SECTION>
commit 74eea0f297a62be5aba84b7482832485d11995e1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat May 10 00:58:07 2008 +0200

    [cairo-quartz-image-surface] Remove one abuse of out-of-memory status
    
    Vlad, you need to stop throwing random OOM errors...

diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index e0c69a9..c3f73d1 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -43,6 +43,7 @@
 #include "cairo-quartz-private.h"
 
 #define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
+#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
 #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
 
 CGImageRef
@@ -300,7 +301,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *image_surface)
     unsigned char *data;
 
     if (cairo_surface_get_type(image_surface) != CAIRO_SURFACE_TYPE_IMAGE)
-	return SURFACE_ERROR_NO_MEMORY;
+	return SURFACE_ERROR_TYPE_MISMATCH;
 
     image_surface = (cairo_image_surface_t*) image_surface;
     width = image_surface->width;
commit dca892c83ea7d115fba0ce66a69464c36cadf74c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat May 10 00:57:44 2008 +0200

    Fix gtk-doc warnings

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index ec62281..fac9e43 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -851,7 +851,7 @@ _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
     return FALSE;
 }
 
-/**
+/*
  * Check whether the given path contains a single rectangle
  * that is logically equivalent to:
  *   cairo_move_to (cr, x, y);
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 4a59d67..3203983 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -127,9 +127,9 @@ struct _cairo_quartz_font_face {
     CGFontRef cgFont;
 };
 
-/**
- ** font face backend
- **/
+/*
+ * font face backend
+ */
 
 static void
 _cairo_quartz_font_face_destroy (void *abstract_face)
@@ -255,9 +255,9 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
     return &font_face->base;
 }
 
-/**
- ** scaled font backend
- **/
+/*
+ * scaled font backend
+ */
 
 static cairo_quartz_font_face_t *
 _cairo_quartz_scaled_to_face (void *abstract_font)
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index 124a803..e0c69a9 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -274,7 +274,7 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
 
 /**
  * cairo_quartz_image_surface_create
- * @surface: a cairo image surface to wrap with a quartz image surface
+ * @image_surface: a cairo image surface to wrap with a quartz image surface
  *
  * Creates a Quartz surface backed by a CGImageRef that references the
  * given image surface. The resulting surface can be rendered quickly
@@ -288,7 +288,7 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
  * Since: 1.6
  */
 cairo_surface_t *
-cairo_quartz_image_surface_create (cairo_surface_t *surface)
+cairo_quartz_image_surface_create (cairo_surface_t *image_surface)
 {
     cairo_quartz_image_surface_t *qisurf;
 
@@ -299,10 +299,10 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
     cairo_format_t format;
     unsigned char *data;
 
-    if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE)
+    if (cairo_surface_get_type(image_surface) != CAIRO_SURFACE_TYPE_IMAGE)
 	return SURFACE_ERROR_NO_MEMORY;
 
-    image_surface = (cairo_image_surface_t*) surface;
+    image_surface = (cairo_image_surface_t*) image_surface;
     width = image_surface->width;
     height = image_surface->height;
     stride = image_surface->stride;
@@ -328,7 +328,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
      * be released via the callback (which will be called in
      * case of failure.)
      */
-    cairo_surface_reference (surface);
+    cairo_surface_reference (image_surface);
 
     image = _cairo_quartz_create_cgimage (format,
 					  width, height,
@@ -337,7 +337,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
 					  TRUE,
 					  NULL,
 					  DataProviderReleaseCallback,
-					  surface);
+					  image_surface);
 
     if (!image) {
 	free (qisurf);
commit 1246ff8aec9054d1d550dd1401b67fac4035cce0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 17:14:02 2008 +0200

    [cairo-test] Implement cairo_test_log_path() to dump a cairo_path_t to logs
    
    Dumping paths is so hard in C.  Shouldn't be.  At least not when debugging...

diff --git a/test/cairo-test.c b/test/cairo-test.c
index b1f0191..0c6d823 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -151,6 +151,37 @@ cairo_test_log (const char *fmt, ...)
     va_end (va);
 }
 
+void
+cairo_test_log_path (const cairo_path_t *path)
+{
+  int i;
+
+  for (i = 0; i < path->num_data; i += path->data[i].header.length) {
+    cairo_path_data_t *data = &path->data[i];
+    switch (data->header.type) {
+    case CAIRO_PATH_MOVE_TO:
+	cairo_test_log ("    cairo_move_to (cr, %g, %g);\n",
+			data[1].point.x, data[1].point.y);
+        break;
+    case CAIRO_PATH_LINE_TO:
+	cairo_test_log ("    cairo_line_to (cr, %g, %g);\n",
+			data[1].point.x, data[1].point.y);
+	break;
+    case CAIRO_PATH_CURVE_TO:
+	cairo_test_log ("    cairo_curve_to (cr, %g, %g, %g, %g, %g, %g);\n",
+			data[1].point.x, data[1].point.y,
+			data[2].point.x, data[2].point.y,
+			data[3].point.x, data[3].point.y);
+	break;
+    case CAIRO_PATH_CLOSE_PATH:
+	cairo_test_log ("    cairo_close_path (cr);\n\n");
+	break;
+    default:
+	assert (0);
+    }
+  }
+}
+
 static void
 xunlink (const char *pathname)
 {
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 6b6b373..381fd4c 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -120,6 +120,9 @@ cairo_test_fini (void);
 void
 cairo_test_log (const char *fmt, ...) CAIRO_BOILERPLATE_PRINTF_FORMAT(1, 2);
 
+void
+cairo_test_log_path (const cairo_path_t *path);
+
 /* Helper functions that take care of finding source images even when
  * building in a non-srcdir manner, (ie. the tests will be run in a
  * directory that is different from the one where the source image
commit dc33760fcb67c41358bb073d63810b5a86099f43
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:59:00 2008 +0200

    [cairo-scaled-font] In _cairo_scaled_glyph_lookup, better handle UNSUPPORTED
    
    If we ask for a glyph info piece and the backend doesn't provide it,
    we should return UNSUPPORTED, even if the backend returned SUCCESS
    (perhaps because the backend doesn't know about that particular piece
    of glyph info).

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 29b8e9f..8cfc44a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1863,6 +1863,29 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 		  scaled_glyph_init) (scaled_font, scaled_glyph, need_info);
 	if (status)
 	    goto CLEANUP;
+
+	/* Don't trust the scaled_glyph_init() return value, the font
+	 * backend may not even know about some of the info.  For example,
+	 * no backend other than the user-fonts knows about meta-surface
+	 * glyph info. */
+
+	if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
+	    scaled_glyph->surface == NULL) {
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    goto CLEANUP;
+	}
+
+	if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
+	    scaled_glyph->path == NULL) {
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    goto CLEANUP;
+	}
+
+	if ((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
+	    scaled_glyph->meta_surface == NULL) {
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    goto CLEANUP;
+	}
     }
 
   CLEANUP:
commit a63dc133779de9c623a85c5aefb5e3da01a8b7d6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:56:35 2008 +0200

    [cairo-scaled-font] Add a meta-surface member to scaled glyphs
    
    No one currently uses it.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 259f172..29b8e9f 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -167,6 +167,8 @@ _cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
 	cairo_surface_destroy (&scaled_glyph->surface->base);
     if (scaled_glyph->path != NULL)
 	_cairo_path_fixed_destroy (scaled_glyph->path);
+    if (scaled_glyph->meta_surface != NULL)
+	cairo_surface_destroy (scaled_glyph->meta_surface);
 }
 
 static void
@@ -1751,6 +1753,16 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
     scaled_glyph->path = path;
 }
 
+void
+_cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
+				      cairo_scaled_font_t *scaled_font,
+				      cairo_surface_t *meta_surface)
+{
+    if (scaled_glyph->meta_surface != NULL)
+	cairo_surface_destroy (meta_surface);
+    scaled_glyph->meta_surface = meta_surface;
+}
+
 /**
  * _cairo_scaled_glyph_lookup:
  * @scaled_font: a #cairo_scaled_font_t
@@ -1810,6 +1822,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 	scaled_glyph->scaled_font = scaled_font;
 	scaled_glyph->surface = NULL;
 	scaled_glyph->path = NULL;
+	scaled_glyph->meta_surface = NULL;
 	scaled_glyph->surface_private = NULL;
 
 	/* ask backend to initialize metrics and shape fields */
@@ -1841,6 +1854,10 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 	 scaled_glyph->path == NULL))
 	need_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
 
+    if (((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
+	 scaled_glyph->path == NULL))
+	need_info |= CAIRO_SCALED_GLYPH_INFO_META_SURFACE;
+
     if (need_info) {
 	status = (*scaled_font->backend->
 		  scaled_glyph_init) (scaled_font, scaled_glyph, need_info);
diff --git a/src/cairoint.h b/src/cairoint.h
index e0a733d..6df8170 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -316,6 +316,7 @@ typedef struct _cairo_scaled_glyph {
     int16_t                 y_advance;		/* device-space rounded Y advance */
     cairo_image_surface_t   *surface;		/* device-space image */
     cairo_path_fixed_t	    *path;		/* device-space outline */
+    cairo_surface_t         *meta_surface;	/* device-space meta-surface */
     void		    *surface_private;	/* for the surface backend */
 } cairo_scaled_glyph_t;
 
@@ -358,9 +359,10 @@ typedef struct _cairo_toy_font_face {
 } cairo_toy_font_face_t;
 
 typedef enum _cairo_scaled_glyph_info {
-    CAIRO_SCALED_GLYPH_INFO_METRICS	= (1 << 0),
-    CAIRO_SCALED_GLYPH_INFO_SURFACE	= (1 << 1),
-    CAIRO_SCALED_GLYPH_INFO_PATH	= (1 << 2)
+    CAIRO_SCALED_GLYPH_INFO_METRICS	 = (1 << 0),
+    CAIRO_SCALED_GLYPH_INFO_SURFACE	 = (1 << 1),
+    CAIRO_SCALED_GLYPH_INFO_PATH	 = (1 << 2),
+    CAIRO_SCALED_GLYPH_INFO_META_SURFACE = (1 << 3),
 } cairo_scaled_glyph_info_t;
 
 typedef struct _cairo_scaled_font_subset {
@@ -1535,6 +1537,11 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
 			      cairo_scaled_font_t *scaled_font,
 			      cairo_path_fixed_t *path);
 
+cairo_private void
+_cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
+				      cairo_scaled_font_t *scaled_font,
+				      cairo_surface_t *meta_surface);
+
 cairo_private cairo_int_status_t
 _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 			    unsigned long index,
commit 11a0884168afe341d53e5c86a49aa48a0142e6ef
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:29:10 2008 +0200

    Add CAIRO_INTERNAL_SURFACE_TYPE_NULL and cairo_nul_surface_create()
    
    It creates a surface that does nothing.  This can be used with
    cairo-analysis-surface, to compute bounds of cairo drawings without doing any
    actual drawings.

diff --git a/src/cairo-analysis-surface-private.h b/src/cairo-analysis-surface-private.h
index dff8a87..b756a4b 100644
--- a/src/cairo-analysis-surface-private.h
+++ b/src/cairo-analysis-surface-private.h
@@ -66,4 +66,8 @@ cairo_private void
 _cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
 					  cairo_box_t     *bbox);
 
+
+cairo_private cairo_surface_t *
+_cairo_null_surface_create (cairo_content_t content);
+
 #endif /* CAIRO_ANALYSIS_SURFACE_H */
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 2dc149d..ad1ca3c 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -748,3 +748,58 @@ _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface,
 
     *bbox = surface->page_bbox;
 }
+
+/* null surface type: a surface that does nothing (has no side effects, yay!) */
+
+static cairo_int_status_t
+_return_success (void)
+{
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static const cairo_surface_backend_t cairo_null_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+
+    NULL, /* create_similar */
+    NULL, /* finish */
+    NULL, /* acquire_source_image */
+    NULL, /* release_source_image */
+    NULL, /* acquire_dest_image */
+    NULL, /* release_dest_image */
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    _return_success, /* set_clip_region */
+    NULL, /* intersect_clip_path */
+    NULL, /* get_extents */
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+    _return_success, /* paint */
+    _return_success, /* mask */
+    _return_success, /* stroke */
+    _return_success, /* fill */
+    _return_success, /* show_glyphs */
+    NULL  /* snapshot */
+};
+
+cairo_surface_t *
+_cairo_null_surface_create (cairo_content_t content)
+{
+    cairo_surface_t *surface;
+
+    surface = malloc (sizeof (cairo_surface_t));
+    if (surface == NULL) {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    _cairo_surface_init (surface, &cairo_null_surface_backend, content);
+
+    return surface;
+}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 64f09b9..45c158b 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -148,7 +148,8 @@ typedef enum _cairo_internal_surface_type {
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
-    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+    CAIRO_INTERNAL_SURFACE_TYPE_NULL
 } cairo_internal_surface_type_t;
 
 typedef struct _cairo_region cairo_region_t;
commit 08334be905edf5f557250e5946bd61391823da27
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:32:57 2008 +0200

    [cairo-meta-surface] Add _cairo_meta_surface_get_path()
    
    Which generates the path for each cairo operation.  If there's any paint,
    mask, or intersect-clip-path operations in the meta-surface, UNSUPPORTED
    is returned.
    
    Strokes are currently tesselated to traps, then traps converted to path.
    Should be made to use stroke_to_path() when we implement that.

diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index 80d8b79..35957f7 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -159,6 +159,10 @@ _cairo_meta_surface_create (cairo_content_t	content,
 			    int			width_pixels,
 			    int			height_pixels);
 
+cairo_private cairo_int_status_t
+_cairo_meta_surface_get_path (cairo_surface_t	 *surface,
+			      cairo_path_fixed_t *path);
+
 cairo_private cairo_status_t
 _cairo_meta_surface_replay (cairo_surface_t *surface,
 			    cairo_surface_t *target);
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index f7ce2d7..4cd1676 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -652,6 +652,77 @@ _cairo_command_get_path (cairo_command_t *command)
     return NULL;
 }
 
+cairo_int_status_t
+_cairo_meta_surface_get_path (cairo_surface_t	 *surface,
+			      cairo_path_fixed_t *path)
+{
+    cairo_meta_surface_t *meta;
+    cairo_command_t *command, **elements;
+    int i, num_elements;
+    cairo_int_status_t status;
+
+    if (surface->status)
+	return surface->status;
+
+    meta = (cairo_meta_surface_t *) surface;
+    status = CAIRO_STATUS_SUCCESS;
+
+    num_elements = meta->commands.num_elements;
+    elements = _cairo_array_index (&meta->commands, 0);
+    for (i = meta->replay_start_idx; i < num_elements; i++) {
+	command = elements[i];
+
+	switch (command->header.type) {
+	case CAIRO_COMMAND_PAINT:
+	case CAIRO_COMMAND_MASK:
+	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    break;
+
+	case CAIRO_COMMAND_STROKE:
+	{
+	    cairo_traps_t traps;
+
+	    _cairo_traps_init (&traps);
+
+	    /* XXX call cairo_stroke_to_path() when that is implemented */
+	    status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
+							&command->stroke.style,
+							&command->stroke.ctm,
+							&command->stroke.ctm_inverse,
+							command->stroke.tolerance,
+							&traps);
+
+	    if (status == CAIRO_STATUS_SUCCESS)
+		status = _cairo_traps_path (&traps, path);
+
+	    _cairo_traps_fini (&traps);
+	    break;
+	}
+	case CAIRO_COMMAND_FILL:
+	{
+	    status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD);
+	    break;
+	}
+	case CAIRO_COMMAND_SHOW_GLYPHS:
+	{
+	    status = _cairo_scaled_font_glyph_path (command->show_glyphs.scaled_font,
+						    command->show_glyphs.glyphs,
+						    command->show_glyphs.num_glyphs,
+						    path);
+	    break;
+	}
+	default:
+	    ASSERT_NOT_REACHED;
+	}
+
+	if (status)
+	    break;
+    }
+
+    return _cairo_surface_set_error (surface, status);
+}
+
 static cairo_status_t
 _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 				     cairo_surface_t	     *target,
diff --git a/src/cairo.c b/src/cairo.c
index 6c73e2c..1a0da69 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1827,7 +1827,8 @@ cairo_rectangle (cairo_t *cr,
     cairo_close_path (cr);
 }
 
-/* XXX: NYI
+#if 0
+/* XXX: NYI */
 void
 cairo_stroke_to_path (cairo_t *cr)
 {
@@ -1836,11 +1837,13 @@ cairo_stroke_to_path (cairo_t *cr)
     if (cr->status)
 	return;
 
+    /* The code in _cairo_meta_surface_get_path has a poorman's stroke_to_path */
+
     status = _cairo_gstate_stroke_path (cr->gstate);
     if (status)
 	_cairo_set_error (cr, status);
 }
-*/
+#endif
 
 /**
  * cairo_close_path:
commit 674cba89fe6165d3dc9986c3d5f083867498e6c1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:31:45 2008 +0200

    [cairo-traps] Add _cairo_traps_path()
    
    It appends path for each trap to the path.

diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 257fd0d..91bb926 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -657,3 +657,49 @@ _cairo_traps_extract_region (const cairo_traps_t  *traps,
 
     return status;
 }
+
+/* moves trap points such that they become the actual corners of the trapezoid */
+static void
+_sanitize_trap (cairo_trapezoid_t *trap)
+{
+/* XXX the math here is fragile.  can overflow in extreme cases */
+#define FIX(t, lr, tb, p) \
+    if (t->lr.p.y != t->tb) { \
+        t->lr.p.x = t->lr.p2.x + (t->lr.p1.x - t->lr.p2.x) * (t->tb - t->lr.p2.y) / (t->lr.p1.y - t->lr.p2.y); \
+        t->lr.p.y = t->tb; \
+    }
+    FIX (trap, left,  top,    p1);
+    FIX (trap, left,  bottom, p2);
+    FIX (trap, right, top,    p1);
+    FIX (trap, right, bottom, p2);
+}
+
+cairo_private cairo_status_t
+_cairo_traps_path (const cairo_traps_t *traps,
+		   cairo_path_fixed_t  *path)
+{
+    int i;
+
+    for (i = 0; i < traps->num_traps; i++) {
+	cairo_status_t status;
+	cairo_trapezoid_t trap = traps->traps[i];
+
+	if (trap.top == trap.bottom)
+	    continue;
+
+	_sanitize_trap (&trap);
+
+	status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
+	if (status) return status;
+	status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
+	if (status) return status;
+	status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
+	if (status) return status;
+	status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
+	if (status) return status;
+	status = _cairo_path_fixed_close_path (path);
+	if (status) return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 33b4df5..e0a733d 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2140,6 +2140,10 @@ cairo_private cairo_int_status_t
 _cairo_traps_extract_region (const cairo_traps_t *tr,
 			     cairo_region_t      *region);
 
+cairo_private cairo_status_t
+_cairo_traps_path (const cairo_traps_t *traps,
+		   cairo_path_fixed_t  *path);
+
 cairo_private void
 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
 					    cairo_trapezoid_t *src_traps,
commit af1e168bbbbaddbf564c661111a74064fbbb5334
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:25:40 2008 +0200

    [cairo-meta/analysis-surface] Make width/height of -1,-1 mean unbounded surface

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index c625380..2dc149d 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -673,10 +673,17 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
     _cairo_region_init (&surface->supported_region);
     _cairo_region_init (&surface->fallback_region);
 
-    surface->current_clip.x = 0;
-    surface->current_clip.y = 0;
-    surface->current_clip.width = width;
-    surface->current_clip.height = height;
+    if (width == -1 && height == -1) {
+	surface->current_clip.x      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.y      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+	surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    } else {
+	surface->current_clip.x = 0;
+	surface->current_clip.y = 0;
+	surface->current_clip.width = width;
+	surface->current_clip.height = height;
+    }
 
     return &surface->base;
 }
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 61c9b5d..f7ce2d7 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -570,6 +570,9 @@ _cairo_meta_surface_get_extents (void			 *abstract_surface,
 {
     cairo_meta_surface_t *surface = abstract_surface;
 
+    if (surface->width_pixels == -1 && surface->height_pixels == -1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     rectangle->x = 0;
     rectangle->y = 0;
     rectangle->width = surface->width_pixels;
commit a6eb9be1066559233d51dbd17bcef18dd61e29fc
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 14:46:22 2008 +0200

    [_cairo_surface_get_extents()] return UNSUPPORTED if surface has no bounds
    and set the extents to the infinite bounds.
    
    A surface has no bounds if it does not provide get_extents(), or if its
    get_extents() returns UNSUPPORTED.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index dd70a98..c625380 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -84,7 +84,7 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
     old_height = surface->height;
     old_clip = surface->current_clip;
     status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     surface->width = meta_extents.width;
@@ -306,7 +306,7 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -364,7 +364,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
     }
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -419,7 +419,7 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -498,7 +498,7 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -575,7 +575,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 7f67b56..edb1d75 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2067,18 +2067,31 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
  * This behavior would have to be changed is we ever exported a public
  * variant of this function.
  */
-cairo_status_t
+cairo_int_status_t
 _cairo_surface_get_extents (cairo_surface_t         *surface,
-			    cairo_rectangle_int_t   *rectangle)
+			    cairo_rectangle_int_t   *extents)
 {
+    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+
     if (surface->status)
 	return surface->status;
 
     if (surface->finished)
 	return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
 
-    return _cairo_surface_set_error (surface,
-	    surface->backend->get_extents (surface, rectangle));
+    if (surface->backend->get_extents) {
+	status = _cairo_surface_set_error (surface,
+					   surface->backend->get_extents (surface, extents));
+    }
+
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	extents->x      = CAIRO_RECT_INT_MIN;
+	extents->y      = CAIRO_RECT_INT_MIN;
+	extents->width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+	extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    }
+
+    return status;
 }
 
 /* Note: the backends may modify the contents of the glyph array as long as
diff --git a/src/cairoint.h b/src/cairoint.h
index 3ebf8da..33b4df5 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -619,10 +619,14 @@ struct _cairo_surface_backend {
      * saves those, and the generic get_clip_extents will only call
      * into the specific surface->get_extents if there is no current
      * clip.
+     *
+     * If this function is not implemented, or if it returns
+     * %CAIRO_INT_STATUS_UNSUPPORTED, the surface is considered to be
+     * boundless and inifnite bounds are used for it.
      */
     cairo_warn cairo_int_status_t
     (*get_extents)		(void			 *surface,
-				 cairo_rectangle_int_t   *rectangle);
+				 cairo_rectangle_int_t   *extents);
 
     /*
      * This is an optional entry to let the surface manage its own glyph
@@ -1776,9 +1780,9 @@ _cairo_surface_get_clip (cairo_surface_t *surface);
 cairo_private cairo_status_t
 _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip);
 
-cairo_private cairo_status_t
+cairo_private cairo_int_status_t
 _cairo_surface_get_extents (cairo_surface_t         *surface,
-			    cairo_rectangle_int_t   *rectangle);
+			    cairo_rectangle_int_t   *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_old_show_glyphs (cairo_scaled_font_t	*scaled_font,
commit d37788f9953b296675860cd48a0b3c14be49c1da
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 14:34:22 2008 +0200

    [cairo-analysis-surface] Initialize page bounding box
    
    If there was no operations played to the analysis surface, page_bbox
    was being left uninitialized.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 8f2569a..dd70a98 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -664,6 +664,12 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
+
+    surface->page_bbox.p1.x = 0;
+    surface->page_bbox.p1.y = 0;
+    surface->page_bbox.p2.x = 0;
+    surface->page_bbox.p2.y = 0;
+
     _cairo_region_init (&surface->supported_region);
     _cairo_region_init (&surface->fallback_region);
 
commit ee3672efdbb4d3ebd3e0bd9e2d63273ad1273e64
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 14:05:04 2008 +0200

    [cairo-pattern] Extend infinite pattern extents to negative coordinates too
    
    With things like meta-surface, the assumption that coordinates are always
    non-negative make no sense.  Extend the "infinite" extents accordingly.
    
    Also remove stale comment.  extents->width/height are unsigned these days and
    cover the full range.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 0f2eb3e..aa32b85 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2066,15 +2066,10 @@ _cairo_pattern_get_extents (cairo_pattern_t         *pattern,
      * horizontal/vertical linear gradients).
      */
 
-    /* XXX: because extents are represented as x, y, w, h we can't
-     * actually have a rectangle that covers our entire valid
-     * coordinate space, since we'd need width/height to be 2*INT_MAX.
-     */
-
-    extents->x = 0;
-    extents->y = 0;
-    extents->width = CAIRO_RECT_INT_MAX;
-    extents->height = CAIRO_RECT_INT_MAX;
+    extents->x = CAIRO_RECT_INT_MIN;
+    extents->y = CAIRO_RECT_INT_MIN;
+    extents->width = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
+    extents->height = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
 
     return CAIRO_STATUS_SUCCESS;
 }
commit f81b857e1ffa48559c794e2fb427413e3a88a271
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:25:16 2008 +0200

    [cairo-paginated-surface] Clean up reference counting mess
    
    Previously the paginated constructor didn't reference the target surface, but
    simply assume ownership of the reference, and then unref it when shutting
    down.  The callers to paginated constructor then, where just give away their
    reference to paginated and not unref the reference they were holding.  While
    this works correctly, it's against the usual idioms that everyone is
    responsible for the reference they are holding, and should get their own
    reference if they need to keep an object alive.  Fix it all.

diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index e490b45..4c47749 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -89,7 +89,7 @@ _cairo_paginated_surface_create (cairo_surface_t				*target,
      * evidence of the paginated wrapper out to the user. */
     surface->base.type = cairo_surface_get_type (target);
 
-    surface->target = target;
+    surface->target = cairo_surface_reference (target);
 
     surface->content = content;
     surface->width = width;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index bb39e03..3573b55 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -301,9 +301,13 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					  CAIRO_CONTENT_COLOR_ALPHA,
 					  width, height,
 					  &cairo_pdf_surface_paginated_backend);
+
     status = surface->paginated_surface->status;
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_STATUS_SUCCESS) {
+	/* paginated keeps the only reference to surface now, drop ours */
+	cairo_surface_destroy (&surface->base);
 	return surface->paginated_surface;
+    }
 
 BAIL1:
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 59f07ed..2c07b47 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -747,8 +747,11 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
 					   width, height,
 					   &cairo_ps_surface_paginated_backend);
     status = surface->paginated_surface->status;
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_STATUS_SUCCESS) {
+	/* paginated keeps the only reference to surface now, drop ours */
+	cairo_surface_destroy (&surface->base);
 	return surface->paginated_surface;
+    }
 
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
  CLEANUP_OUTPUT_STREAM:
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index df5253d..6a06783 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -384,8 +384,11 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
 						 surface->height,
 						 &cairo_svg_surface_paginated_backend);
     status = paginated->status;
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_STATUS_SUCCESS) {
+	/* paginated keeps the only reference to surface now, drop ours */
+	cairo_surface_destroy (&surface->base);
 	return paginated;
+    }
 
     /* ignore status as we are on the error path */
 CLEANUP:
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 791eb91..8fe5bc7 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1500,6 +1500,7 @@ cairo_surface_t *
 cairo_win32_printing_surface_create (HDC hdc)
 {
     cairo_win32_surface_t *surface;
+    cairo_surface_t *paginated;
     RECT rect;
 
     surface = malloc (sizeof (cairo_win32_surface_t));
@@ -1535,11 +1536,16 @@ cairo_win32_printing_surface_create (HDC hdc)
     _cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend,
                          CAIRO_CONTENT_COLOR_ALPHA);
 
-    return _cairo_paginated_surface_create (&surface->base,
-                                            CAIRO_CONTENT_COLOR_ALPHA,
-					    surface->extents.width,
-					    surface->extents.height,
-                                            &cairo_win32_surface_paginated_backend);
+    paginated = _cairo_paginated_surface_create (&surface->base,
+						 CAIRO_CONTENT_COLOR_ALPHA,
+						 surface->extents.width,
+						 surface->extents.height,
+						 &cairo_win32_surface_paginated_backend);
+
+    /* paginated keeps the only reference to surface now, drop ours */
+    cairo_surface_destroy (&surface->base);
+
+    return paginated;
 }
 
 cairo_bool_t
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index f640b60..f7cc4db 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -93,9 +93,12 @@ _cairo_test_paginated_surface_create_for_data (unsigned char		*data,
     paginated =  _cairo_paginated_surface_create (&surface->base,
 	                                          content, width, height,
 						  &test_paginated_surface_paginated_backend);
+
+    /* paginated keeps the only reference to surface now, drop ours */
+    cairo_surface_destroy (&surface->base);
+
     if (paginated->status) {
 	cairo_surface_destroy (target);
-	free (surface);
     }
     return paginated;
 }
commit 440b339da793ba2f71f504328417aefc7d44ee7f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:23:02 2008 +0200

    [cairo-analysis-surface] Hold reference to target surface

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index fbe5812..8f2569a 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -238,6 +238,8 @@ _cairo_analysis_surface_finish (void *abstract_surface)
     _cairo_region_fini (&surface->supported_region);
     _cairo_region_fini (&surface->fallback_region);
 
+    cairo_surface_destroy (surface->target);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -658,7 +660,7 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
     cairo_matrix_init_identity (&surface->ctm);
     surface->has_ctm = FALSE;
 
-    surface->target = target;
+    surface->target = cairo_surface_reference (target);
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
commit 25700f5cd052e5353c868ba0311ff53850e3f549
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:32:35 2008 +0200

    [cairo-ft-font.c] Throw error on font type mismatch and remove unused function

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 95da10b..649aad0 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -350,12 +350,6 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
     return CAIRO_STATUS_SUCCESS;
 }
 
-cairo_bool_t
-_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
-{
-    return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
-}
-
 /**
  * _cairo_ft_unscaled_font_fini:
  *
@@ -2615,6 +2609,11 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
     FT_Face face;
     cairo_status_t status;
 
+    if (! _cairo_scaled_font_is_ft (abstract_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return NULL;
+    }
+
     if (scaled_font->base.status)
 	return NULL;
 
@@ -2657,6 +2656,11 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
 
+    if (! _cairo_scaled_font_is_ft (abstract_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return;
+    }
+
     if (scaled_font->base.status)
 	return;
 
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 67154b3..e6436ca 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -47,9 +47,6 @@ CAIRO_BEGIN_DECLS
 typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t;
 
 cairo_private cairo_bool_t
-_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font);
-
-cairo_private cairo_bool_t
 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font);
 
 /* These functions are needed by the PDF backend, which needs to keep track of the
commit 2a1661fba9db1e263079e0ff101c628a443702e8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:31:54 2008 +0200

    [cairo-win32-font.c] Return error on font type mismatch

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 3abfe2d..919b6f8 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1941,6 +1941,12 @@ cairo_win32_font_face_create_for_hfont (HFONT font)
     return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
 }
 
+static cairo_bool_t
+_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
+{
+    return scaled_font->backend == &cairo_win32_scaled_font_backend;
+}
+
 /**
  * cairo_win32_scaled_font_select_font:
  * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an
@@ -1974,6 +1980,10 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
     HFONT old_hfont = NULL;
     int old_mode;
 
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+    }
+
     if (scaled_font->status)
 	return scaled_font->status;
 
@@ -2013,6 +2023,9 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
 void
 cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
 {
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+    }
 }
 
 /**
@@ -2030,6 +2043,10 @@ cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
 double
 cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
 {
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return 1.;
+    }
     return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
 }
 
@@ -2048,6 +2065,11 @@ cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
 					       cairo_matrix_t *logical_to_device)
 {
     cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	cairo_matrix_init_identity (logical_to_device);
+	return;
+    }
     *logical_to_device = win_font->logical_to_device;
 }
 
@@ -2066,5 +2088,10 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
 					       cairo_matrix_t *device_to_logical)
 {
     cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	cairo_matrix_init_identity (device_to_logical);
+	return;
+    }
     *device_to_logical = win_font->device_to_logical;
 }
commit 2a9bb6f78c8a0fa47908da7863979560230a62a2
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:07:45 2008 +0200

    Add CAIRO_STATUS_FONT_TYPE_MISMATCH

diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index a2250ff..b85d98f 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -101,6 +101,8 @@ cairo_status_to_string (cairo_status_t status)
 	return "error creating or writing to a temporary file";
     case CAIRO_STATUS_INVALID_STRIDE:
 	return "invalid value for stride";
+    case CAIRO_STATUS_FONT_TYPE_MISMATCH:
+	return "the font type is not appropriate for the operation";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 42eb027..4ac8f32 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -203,6 +203,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
  * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
  * @CAIRO_STATUS_INVALID_STRIDE: invalid value for stride (Since 1.6)
+ * @CAIRO_STATUS_FONT_TYPE_MISMATCH: the font type is not appropriate for the operation (Since 1.8)
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -237,7 +238,8 @@ typedef enum _cairo_status {
     CAIRO_STATUS_INVALID_INDEX,
     CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
     CAIRO_STATUS_TEMP_FILE_ERROR,
-    CAIRO_STATUS_INVALID_STRIDE
+    CAIRO_STATUS_INVALID_STRIDE,
+    CAIRO_STATUS_FONT_TYPE_MISMATCH
     /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairoint.h */
 } cairo_status_t;
 
diff --git a/src/cairoint.h b/src/cairoint.h
index cb45bdf..3ebf8da 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -110,7 +110,7 @@ _cairo_win32_tmpfile (void);
  * a bit of a pain, but it should be easy to always catch as long as
  * one adds a new test case to test a trigger of the new status value.
  */
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_STRIDE
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_FONT_TYPE_MISMATCH
 
 
 /* Size in bytes of buffer to use off the stack per functions.
commit 4d77dfc78d2ea1925d0035080f57b68b0269a5f0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:27:55 2008 +0200

    [cairo-analysis-surface] Add _cairo_analysis_surface_[gs]et_ctm()
    
    The functionality was there.  Just add getter/setter for the ctm.

diff --git a/src/cairo-analysis-surface-private.h b/src/cairo-analysis-surface-private.h
index 9fcfed0..dff8a87 100644
--- a/src/cairo-analysis-surface-private.h
+++ b/src/cairo-analysis-surface-private.h
@@ -42,6 +42,14 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
 				int			 width,
 				int			 height);
 
+cairo_private void
+_cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
+				 cairo_matrix_t  *ctm);
+
+cairo_private void
+_cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
+				 cairo_matrix_t  *ctm);
+
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *surface);
 
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 978343f..fbe5812 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -673,6 +673,26 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
     return &surface->base;
 }
 
+cairo_private void
+_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
+				 cairo_matrix_t  *ctm)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    surface->ctm = *ctm;
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
+}
+
+cairo_private void
+_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
+				 cairo_matrix_t  *ctm)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    *ctm = surface->ctm;
+}
+
+
 cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
 {
commit ad7cfb4af98e8bf7792dad0ef4fd772cd6f1d270
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:20:02 2008 +0200

    [cairo-analysis-surface] Use _cairo_matrix_transform_bounding_box_fixed()
    and other conversion functions.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 749f3e3..978343f 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -140,22 +140,13 @@ _cairo_analysis_surface_add_operation  (cairo_analysis_surface_t *surface,
 	}
     }
 
+    _cairo_box_from_rectangle (&bbox, rect);
+
     if (surface->has_ctm) {
-	double x1, y1, x2, y2;
-
-	x1 = rect->x;
-	y1 = rect->y;
-	x2 = rect->x + rect->width;
-	y2 = rect->y + rect->height;
-	_cairo_matrix_transform_bounding_box (&surface->ctm,
-					      &x1, &y1, &x2, &y2,
-					      NULL);
-	rect->x = floor (x1);
-	rect->y = floor (y1);
-
-	x2 = ceil (x2) - rect->x;
-	y2 = ceil (y2) - rect->y;
-	if (x2 <= 0 || y2 <= 0) {
+
+	_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
+
+	if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
 	    /* Even though the operation is not visible we must be
 	     * careful to not allow unsupported operations to be
 	     * replayed to the backend during
@@ -171,15 +162,9 @@ _cairo_analysis_surface_add_operation  (cairo_analysis_surface_t *surface,
 	    }
 	}
 
-	rect->width  = x2;
-	rect->height = y2;
+	_cairo_box_round_to_rectangle (&bbox, rect);
     }
 
-    bbox.p1.x = _cairo_fixed_from_int (rect->x);
-    bbox.p1.y = _cairo_fixed_from_int (rect->y);
-    bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
-    bbox.p2.y = _cairo_fixed_from_int (rect->y + rect->height);
-
     if (surface->first_op) {
 	surface->first_op = FALSE;
 	surface->page_bbox = bbox;
commit bdfda97f191fa6ffa64abad5b6f035244d91f44c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:17:30 2008 +0200

    [cairo-matrix] Add _cairo_matrix_transform_bounding_box_fixed()

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 57414b7..b743273 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -423,6 +423,18 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
     }
 }
 
+cairo_private void
+_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
+					    cairo_box_t          *bbox,
+					    cairo_bool_t *is_tight)
+{
+    double x1, y1, x2, y2;
+
+    _cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
+    _cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
+    _cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
+}
+
 static void
 _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
 {
diff --git a/src/cairoint.h b/src/cairoint.h
index 9130765..cb45bdf 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2051,6 +2051,11 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
 				      double *x2, double *y2,
 				      cairo_bool_t *is_tight);
 
+cairo_private void
+_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
+					    cairo_box_t          *bbox,
+					    cairo_bool_t         *is_tight);
+
 cairo_private cairo_bool_t
 _cairo_matrix_is_invertible (const cairo_matrix_t *matrix);
 
commit 6c9902fd746d70d9cc22c938f4ca68640e48bb73
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:16:13 2008 +0200

    Add more consts to function signatures and remove stale prototype

diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index 1da9743..208da7c 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -1415,9 +1415,9 @@ update_minmax(cairo_fixed_t *inout_min,
 }
 
 cairo_status_t
-_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	*traps,
-					   cairo_polygon_t	*polygon,
-					   cairo_fill_rule_t	 fill_rule)
+_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
+					   const cairo_polygon_t *polygon,
+					   cairo_fill_rule_t	  fill_rule)
 {
     int intersections;
     cairo_status_t status;
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 8d71607..257fd0d 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -557,7 +557,8 @@ _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
 }
 
 cairo_bool_t
-_cairo_traps_contain (cairo_traps_t *traps, double x, double y)
+_cairo_traps_contain (const cairo_traps_t *traps,
+		      double x, double y)
 {
     int i;
     cairo_point_t point;
@@ -574,7 +575,8 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y)
 }
 
 void
-_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
+_cairo_traps_extents (const cairo_traps_t *traps,
+		      cairo_box_t         *extents)
 {
     if (traps->num_traps == 0) {
 	extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
@@ -598,8 +600,8 @@ _cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
  * or %CAIRO_STATUS_NO_MEMORY
  **/
 cairo_int_status_t
-_cairo_traps_extract_region (cairo_traps_t  *traps,
-			     cairo_region_t *region)
+_cairo_traps_extract_region (const cairo_traps_t  *traps,
+			     cairo_region_t       *region)
 {
     cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
     cairo_box_int_t *boxes = stack_boxes;
diff --git a/src/cairoint.h b/src/cairoint.h
index 389a1cc..9130765 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2109,30 +2109,27 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
 cairo_private cairo_status_t
 _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
 
-cairo_private cairo_status_t
-_cairo_traps_tessellate_polygon (cairo_traps_t *traps,
-				 cairo_polygon_t *poly,
-				 cairo_fill_rule_t fill_rule);
-
 cairo_private void
 _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
 				   cairo_point_t left_p1, cairo_point_t left_p2,
 				   cairo_point_t right_p1, cairo_point_t right_p2);
 
 cairo_private cairo_status_t
-_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t      *traps,
-					   cairo_polygon_t      *polygon,
-					   cairo_fill_rule_t     fill_rule);
+_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t         *traps,
+					   const cairo_polygon_t *polygon,
+					   cairo_fill_rule_t      fill_rule);
 
 cairo_private int
-_cairo_traps_contain (cairo_traps_t *traps, double x, double y);
+_cairo_traps_contain (const cairo_traps_t *traps,
+		      double x, double y);
 
 cairo_private void
-_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents);
+_cairo_traps_extents (const cairo_traps_t *traps,
+		      cairo_box_t         *extents);
 
 cairo_private cairo_int_status_t
-_cairo_traps_extract_region (cairo_traps_t     *tr,
-			     cairo_region_t *region);
+_cairo_traps_extract_region (const cairo_traps_t *tr,
+			     cairo_region_t      *region);
 
 cairo_private void
 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
commit 0e965c970bd310bd8f06cd59ed0cf631ae88659a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:13:52 2008 +0200

    [cairo-path-fixed] Add _cairo_path_fixed_append()

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 43b8040..ec62281 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -541,6 +541,52 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t		*path,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_append_move_to (void		 *closure,
+	  cairo_point_t  *point)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_move_to (path, point->x, point->y);
+}
+
+static cairo_status_t
+_append_line_to (void		 *closure,
+	  cairo_point_t *point)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_line_to (path, point->x, point->y);
+}
+
+static cairo_status_t
+_append_curve_to (void	  *closure,
+	   cairo_point_t *p0,
+	   cairo_point_t *p1,
+	   cairo_point_t *p2)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y);
+}
+
+static cairo_status_t
+_append_close_path (void *closure)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_close_path (path);
+}
+
+cairo_private cairo_status_t
+_cairo_path_fixed_append (cairo_path_fixed_t		  *path,
+			  const cairo_path_fixed_t	  *other,
+			  cairo_direction_t		   dir)
+{
+    return _cairo_path_fixed_interpret (other, dir,
+					_append_move_to,
+					_append_line_to,
+					_append_curve_to,
+					_append_close_path,
+					path);
+}
+
 static void
 _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
 				    cairo_fixed_t offx,
diff --git a/src/cairoint.h b/src/cairoint.h
index ac52eeb..389a1cc 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1420,6 +1420,11 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
 		       double				  tolerance);
 
 cairo_private cairo_status_t
+_cairo_path_fixed_append (cairo_path_fixed_t		  *path,
+			  const cairo_path_fixed_t	  *other,
+			  cairo_direction_t		   dir);
+
+cairo_private cairo_status_t
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 			  double *x1, double *y1,
 			  double *x2, double *y2,
commit e9b6bb06d60584a867256e52732aad25c9e137c5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:13:15 2008 +0200

    [cairo-path-fixed] Add a couple consts to function signatures

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 75a76d0..43b8040 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -476,7 +476,7 @@ static int const num_args[] =
 };
 
 cairo_status_t
-_cairo_path_fixed_interpret (cairo_path_fixed_t			*path,
+_cairo_path_fixed_interpret (const cairo_path_fixed_t		*path,
 			     cairo_direction_t			 dir,
 			     cairo_path_fixed_move_to_func_t	*move_to,
 			     cairo_path_fixed_line_to_func_t	*line_to,
@@ -701,7 +701,7 @@ _cpf_close_path (void *closure)
 
 
 cairo_status_t
-_cairo_path_fixed_interpret_flat (cairo_path_fixed_t			*path,
+_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t		*path,
 				  cairo_direction_t			dir,
 				  cairo_path_fixed_move_to_func_t	*move_to,
 				  cairo_path_fixed_line_to_func_t	*line_to,
diff --git a/src/cairoint.h b/src/cairoint.h
index 6d5d636..ac52eeb 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1402,7 +1402,7 @@ typedef cairo_status_t
 (cairo_path_fixed_close_path_func_t) (void *closure);
 
 cairo_private cairo_status_t
-_cairo_path_fixed_interpret (cairo_path_fixed_t		  *path,
+_cairo_path_fixed_interpret (const cairo_path_fixed_t	  *path,
 		       cairo_direction_t		   dir,
 		       cairo_path_fixed_move_to_func_t	  *move_to,
 		       cairo_path_fixed_line_to_func_t	  *line_to,
@@ -1411,7 +1411,7 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t		  *path,
 		       void				  *closure);
 
 cairo_private cairo_status_t
-_cairo_path_fixed_interpret_flat (cairo_path_fixed_t	  *path,
+_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
 		       cairo_direction_t		   dir,
 		       cairo_path_fixed_move_to_func_t	  *move_to,
 		       cairo_path_fixed_line_to_func_t	  *line_to,
commit 2a3eec1731d0cfdbc1abc204c08ff14296f297ef
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:10:44 2008 +0200

    [cairo-rectangle] Add new convenience functions for working with cairo_box_t
    
    _cairo_box_from_doubles, _cairo_box_to_doubles, _cairo_box_from_rectangle.

diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 6fb0ef2..3618ba0 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -39,6 +39,38 @@
 
 #include "cairoint.h"
 
+cairo_private void
+_cairo_box_from_doubles (cairo_box_t *box,
+			 double *x1, double *y1,
+			 double *x2, double *y2)
+{
+    box->p1.x = _cairo_fixed_from_double (*x1);
+    box->p1.y = _cairo_fixed_from_double (*y1);
+    box->p2.x = _cairo_fixed_from_double (*x2);
+    box->p2.y = _cairo_fixed_from_double (*y2);
+}
+
+cairo_private void
+_cairo_box_to_doubles (const cairo_box_t *box,
+		       double *x1, double *y1,
+		       double *x2, double *y2)
+{
+    *x1 = _cairo_fixed_to_double (box->p1.x);
+    *y1 = _cairo_fixed_to_double (box->p1.y);
+    *x2 = _cairo_fixed_to_double (box->p2.x);
+    *y2 = _cairo_fixed_to_double (box->p2.y);
+}
+
+void
+_cairo_box_from_rectangle (cairo_box_t                 *box,
+			   const cairo_rectangle_int_t *rect)
+{
+    box->p1.x = _cairo_fixed_from_int (rect->x);
+    box->p1.y = _cairo_fixed_from_int (rect->y);
+    box->p2.x = _cairo_fixed_from_int (rect->x + rect->width);
+    box->p2.y = _cairo_fixed_from_int (rect->y + rect->height);
+}
+
 /* XXX We currently have a confusing mix of boxes and rectangles as
  * exemplified by this function.  A #cairo_box_t is a rectangular area
  * represented by the coordinates of the upper left and lower right
@@ -54,7 +86,8 @@
  */
 
 void
-_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle)
+_cairo_box_round_to_rectangle (const cairo_box_t     *box,
+			       cairo_rectangle_int_t *rectangle)
 {
     rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
     rectangle->y = _cairo_fixed_integer_floor (box->p1.y);
diff --git a/src/cairoint.h b/src/cairoint.h
index 16fc0ed..6d5d636 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -207,7 +207,22 @@ be32_to_cpu(uint32_t v)
 #include "cairo-reference-count-private.h"
 
 cairo_private void
-_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle);
+_cairo_box_from_doubles (cairo_box_t *box,
+			 double *x1, double *y1,
+			 double *x2, double *y2);
+
+cairo_private void
+_cairo_box_to_doubles (const cairo_box_t *box,
+		       double *x1, double *y1,
+		       double *x2, double *y2);
+
+cairo_private void
+_cairo_box_from_rectangle (cairo_box_t                 *box,
+			   const cairo_rectangle_int_t *rectangle);
+
+cairo_private void
+_cairo_box_round_to_rectangle (const cairo_box_t     *box,
+			       cairo_rectangle_int_t *rectangle);
 
 cairo_private void
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src);
commit 6836b2b8bac0a0f5594e0c56629b075387fe1d22
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:14:23 2008 +0200

    [cairoint.h] Fix file name in comments

diff --git a/src/cairoint.h b/src/cairoint.h
index 5ec657d..16fc0ed 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1297,7 +1297,7 @@ cairo_private void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other);
 
-/* cairo_hull.c */
+/* cairo-hull.c */
 cairo_private cairo_status_t
 _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
 
@@ -1305,7 +1305,7 @@ _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
 cairo_private unsigned char *
 _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out);
 
-/* cairo_path.c */
+/* cairo-path-fixed.c */
 cairo_private void
 _cairo_path_fixed_init (cairo_path_fixed_t *path);
 
@@ -1425,14 +1425,14 @@ cairo_private cairo_bool_t
 _cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
 				cairo_box_t        *box);
 
-/* cairo_path_fill.c */
+/* cairo-path-fill.c */
 cairo_private cairo_status_t
 _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
 				 cairo_fill_rule_t   fill_rule,
 				 double              tolerance,
 				 cairo_traps_t      *traps);
 
-/* cairo_path_stroke.c */
+/* cairo-path-stroke.c */
 cairo_private cairo_status_t
 _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t	*path,
 				   cairo_stroke_style_t	*stroke_style,
commit ca8b917102ddfad67300f907732dbd69a2c86957
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:28:31 2008 +0200

    [cairo-surface] Call backend->flush even if backend->finish is null
    
    Trivial bug.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 5a68959..7f67b56 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -500,11 +500,6 @@ cairo_surface_finish (cairo_surface_t *surface)
 	return;
     }
 
-    if (surface->backend->finish == NULL) {
-	surface->finished = TRUE;
-	return;
-    }
-
     if (!surface->status && surface->backend->flush) {
 	status = surface->backend->flush (surface);
 	if (status) {
@@ -513,6 +508,11 @@ cairo_surface_finish (cairo_surface_t *surface)
 	}
     }
 
+    if (surface->backend->finish == NULL) {
+	surface->finished = TRUE;
+	return;
+    }
+
     status = surface->backend->finish (surface);
     if (status)
 	status = _cairo_surface_set_error (surface, status);
commit 07cd614039cf7d3c776413ff26e94aa7dc27ea23
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:27:40 2008 +0200

    [cairo-scaled-font] Tolerate null scaled_font->backend->fini

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 8b250a2..259f172 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -589,7 +589,8 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 	scaled_font->surface_backend->scaled_font_fini != NULL)
 	scaled_font->surface_backend->scaled_font_fini (scaled_font);
 
-    scaled_font->backend->fini (scaled_font);
+    if (scaled_font->backend->fini != NULL)
+	scaled_font->backend->fini (scaled_font);
 
     _cairo_user_data_array_fini (&scaled_font->user_data);
 }
commit 1f05cae0a9aaff23a4d80b309d30ed5047198113
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:03:51 2008 +0200

    [cairo-font-face] Tolerate null font_face->backend->destroy()

diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index 49c8cdf..6fe6dfc 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -132,7 +132,8 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
     if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
 	return;
 
-    font_face->backend->destroy (font_face);
+    if (font_face->backend->destroy)
+	font_face->backend->destroy (font_face);
 
     /* We allow resurrection to deal with some memory management for the
      * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
commit 96599225e2fd1f7d11071a19f1ceb2c33f2a453b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:36:33 2008 +0200

    Define CAIRO_RECT_INT_MIN/MAX such that ints do not overflow when converted to fixed
    
    There's not much point in having integers that will overflow.

diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 30f7476..64f09b9 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -207,13 +207,13 @@ struct _cairo_point_int32 {
 #if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
 typedef struct _cairo_rectangle_int16 cairo_rectangle_int_t;
 typedef struct _cairo_point_int16 cairo_point_int_t;
-#define CAIRO_RECT_INT_MIN INT16_MIN
-#define CAIRO_RECT_INT_MAX INT16_MAX
+#define CAIRO_RECT_INT_MIN (INT16_MIN >> (CAIRO_FIXED_FRAC_BITS - 16))
+#define CAIRO_RECT_INT_MAX (INT16_MAX >> (CAIRO_FIXED_FRAC_BITS - 16))
 #elif CAIRO_FIXED_BITS == 32
 typedef struct _cairo_rectangle_int32 cairo_rectangle_int_t;
 typedef struct _cairo_point_int32 cairo_point_int_t;
-#define CAIRO_RECT_INT_MIN INT32_MIN
-#define CAIRO_RECT_INT_MAX INT32_MAX
+#define CAIRO_RECT_INT_MIN (INT32_MIN >> CAIRO_FIXED_FRAC_BITS)
+#define CAIRO_RECT_INT_MAX (INT32_MAX >> CAIRO_FIXED_FRAC_BITS)
 #else
 #error Not sure how to pick a cairo_rectangle_int_t and cairo_point_int_t for your CAIRO_FIXED_BITS!
 #endif
commit eb63e5609ebb2b666f0cce552dec4c335f210baf
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 13:00:28 2008 +0200

    [_cairo_surface_set_device_scale] zero xy and yx matrix entries
    
    Just in case...

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index b2addf0..5a68959 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -785,9 +785,13 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
 
     surface->device_transform.xx = sx;
     surface->device_transform.yy = sy;
+    surface->device_transform.xy = 0.0;
+    surface->device_transform.yx = 0.0;
 
     surface->device_transform_inverse.xx = 1.0 / sx;
     surface->device_transform_inverse.yy = 1.0 / sy;
+    surface->device_transform_inverse.xy = 0.0;
+    surface->device_transform_inverse.yx = 0.0;
 }
 
 /**
commit 80c59062675ad86d7201352140043f9e27d4b7d4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 12:59:07 2008 +0200

    [cairo-surface] Tone down a Caution comment
    
    We have tested the case of device transforms that have both translate and
    scale.  So it basically works.  We just are not sure that we handle it in
    all places (In fact we know we don't.)

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 941e173..b2addf0 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -763,11 +763,8 @@ slim_hidden_def (cairo_surface_mark_dirty_rectangle);
  * different backend space, (differing by the fallback resolution
  * scale factors), we need a scale factor correction.
  *
- * Caution: There is no guarantee that a surface with both a
- * device_scale and a device_offset will be treated in consistent
- * fashion. So, for now, just don't do that. (And we'll need to
- * examine this issue in more detail if we were to ever want to export
- * support for device scaling.)
+ * Caution: Not all places we use device transform correctly handle
+ * both a translate and a scale.  An audit would be nice.
  **/
 void
 _cairo_surface_set_device_scale (cairo_surface_t *surface,
commit 901c56cba28f9eef3a7a27a25dfbb993b492518b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:35:08 2008 +0200

    [image surface] Rename cairo_image_surface_backend to _cairo_image_surface_backend

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 41e6bbd..cd80aed 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -124,7 +124,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
     if (surface == NULL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    _cairo_surface_init (&surface->base, &cairo_image_surface_backend,
+    _cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
 			 _cairo_content_from_pixman_format (pixman_format));
 
     surface->pixman_image = pixman_image;
@@ -1247,10 +1247,10 @@ _cairo_image_surface_reset (void *abstract_surface)
 cairo_bool_t
 _cairo_surface_is_image (const cairo_surface_t *surface)
 {
-    return surface->backend == &cairo_image_surface_backend;
+    return surface->backend == &_cairo_image_surface_backend;
 }
 
-const cairo_surface_backend_t cairo_image_surface_backend = {
+const cairo_surface_backend_t _cairo_image_surface_backend = {
     CAIRO_SURFACE_TYPE_IMAGE,
     _cairo_image_surface_create_similar,
     _cairo_image_surface_finish,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 0230703..941e173 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -43,7 +43,7 @@
 
 #define DEFINE_NIL_SURFACE(status, name)			\
 const cairo_surface_t name = {					\
-    &cairo_image_surface_backend,	/* backend */		\
+    &_cairo_image_surface_backend,	/* backend */		\
     CAIRO_SURFACE_TYPE_IMAGE,					\
     CAIRO_CONTENT_COLOR,					\
     CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */		\
diff --git a/src/cairoint.h b/src/cairoint.h
old mode 100644
new mode 100755
index f843c89..5ec657d
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -739,7 +739,7 @@ struct _cairo_image_surface {
     pixman_image_t *pixman_image;
 };
 
-extern const cairo_private cairo_surface_backend_t cairo_image_surface_backend;
+extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend;
 
 /* XXX: Right now, the _cairo_color structure puts unpremultiplied
    color in the doubles and premultiplied color in the shorts. Yes,
commit 5744b0b9a563e5cf329cc0ba31f96ff238d86210
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:41:05 2008 +0200

    [cairo-deprecated.h] Remove mention of cairoint.h from public header

diff --git a/src/cairo-deprecated.h b/src/cairo-deprecated.h
index c73d2b7..b59ea64 100644
--- a/src/cairo-deprecated.h
+++ b/src/cairo-deprecated.h
@@ -52,8 +52,6 @@
 
 #define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
 
-#ifndef _CAIROINT_H_
-
 /* Obsolete functions. These definitions exist to coerce the compiler
  * into providing a little bit of guidance with its error
  * messages. The idea is to help users port their old code without
@@ -137,6 +135,4 @@
 #define cairo_get_status_string		cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
 #define cairo_status_string		cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
 
-#endif
-
 #endif /* CAIRO_DEPRECATED_H */
commit 5f633580189fa48f5b650d3c63c585521bb833a9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 09:53:40 2008 -0400

    [src/check-doc-syntax.sh] Fix some bugs in the check and fix errors found

diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index d95da8c..1241225 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -82,7 +82,7 @@ _lzw_buf_init (lzw_buf_t *buf, int size)
 
 /* Increase the buffer size by doubling.
  *
- * Returns %CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
+ * Returns %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
  */
 static cairo_status_t
 _lzw_buf_grow (lzw_buf_t *buf)
diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h
index 1a29dcb..f68afb7 100644
--- a/src/cairo-mutex-type-private.h
+++ b/src/cairo-mutex-type-private.h
@@ -72,7 +72,9 @@ CAIRO_BEGIN_DECLS
  *   You should be able to compile the following snippet (don't try
  *   running it):
  *
+ *   <programlisting>
  *	cairo_mutex_t _cairo_some_mutex;
+ *   </programlisting>
  *
  * - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to
  *   proper statement to lock/unlock the mutex object passed in.
@@ -82,44 +84,52 @@ CAIRO_BEGIN_DECLS
  *   No trailing semicolons are needed (in any macro you define here).
  *   You should be able to compile the following snippet:
  *
+ *   <programlisting>
  *	cairo_mutex_t _cairo_some_mutex;
  *
  *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
  *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
  *
  * - #define %CAIRO_MUTEX_NIL_INITIALIZER to something that can
  *   initialize the #cairo_mutex_t type you defined.  Most of the
  *   time one of 0, %NULL, or {} works.  At this point
  *   you should be able to compile the following snippet:
  *
+ *   <programlisting>
  *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
  *
  *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
  *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
  *
  * - If the above code is not enough to initialize a mutex on
  *   your platform, #define CAIRO_MUTEX_INIT(mutex) to statement
  *   to initialize the mutex (allocate resources, etc).  Such that
  *   you should be able to compile AND RUN the following snippet:
  *
+ *   <programlisting>
  *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
  *
- *      %CAIRO_MUTEX_INIT (_cairo_some_mutex);
+ *      CAIRO_MUTEX_INIT (_cairo_some_mutex);
  *
  *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
  *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
  *
  * - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to
  *   initialize all static mutex'es.  If for any reason that should
  *   not happen (eg. %CAIRO_MUTEX_INIT is just a faster way than
  *   what cairo does using %CAIRO_MUTEX_NIL_INITIALIZER), then
- *   #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
+ *   </programlisting>
  *
  * - If your system supports freeing a mutex object (deallocating
  *   resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do
@@ -130,8 +140,10 @@ CAIRO_BEGIN_DECLS
  *   However, it's up to you to call CAIRO_MUTEX_FINALIZE() at
  *   proper places, eg. when the system is unloading the cairo library.
  *   So, if for any reason finalizing static mutex'es is not needed
- *   (eg. you never call %CAIRO_MUTEX_FINALIZE), then
- *   #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
+ *   (eg. you never call CAIRO_MUTEX_FINALIZE()), then
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
+ *   </programlisting>
  *
  * - That is all.  If for any reason you think the above API is
  *   not enough to implement #cairo_mutex_t on your system, please
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 351585e..e2fffb2 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -49,7 +49,7 @@
  */
 #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
 
-/* Numbers printed with %g are assumed to only have CAIRO_FIXED_FRAC_BITS
+/* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
  * bits of precision available after the decimal point.
  *
  * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
@@ -58,10 +58,12 @@
  *
  * The conversion is:
  *
+ * <programlisting>
  * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
+ * </programlisting>
  *
  * We can replace ceil(x) with (int)(x+1) since x will never be an
- * integer for any likely value of CAIRO_FIXED_FRAC_BITS.
+ * integer for any likely value of %CAIRO_FIXED_FRAC_BITS.
  */
 #define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
 
diff --git a/src/cairo-paginated-private.h b/src/cairo-paginated-private.h
index 35384c9..bb31487 100644
--- a/src/cairo-paginated-private.h
+++ b/src/cairo-paginated-private.h
@@ -90,27 +90,27 @@ struct _cairo_paginated_surface_backend {
  * operations for a page into a meta-surface. Then when the user calls
  * cairo_show_page, the paginated surface performs the following
  * sequence of operations (using the backend functions passed to
- * cairo_paginated_surface_create):
+ * cairo_paginated_surface_create()):
  *
- * 1. Calls start_page (if non %NULL). At this point, it is appropriate
+ * 1. Calls start_page() (if not %NULL). At this point, it is appropriate
  *    for the target to emit any page-specific header information into
  *    its output.
  *
- * 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
+ * 2. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_ANALYZE
  *
  * 3. Replays the meta-surface to the target surface, (with an
  *    analysis surface inserted between which watches the return value
  *    from each operation). This analysis stage is used to decide which
  *    operations will require fallbacks.
  *
- * 4. Calls set_bounding_box to provide the target surface with the
+ * 4. Calls set_bounding_box() to provide the target surface with the
  *    tight bounding box of the page.
  *
- * 5. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
+ * 5. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_RENDER
  *
  * 6. Replays a subset of the meta-surface operations to the target surface
  *
- * 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
+ * 7. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_FALLBACK
  *
  * 8. Replays the remaining operations to an image surface, sets an
  *    appropriate clip on the target, then paints the resulting image
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 0d5a3f8..0230703 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -476,7 +476,7 @@ cairo_surface_get_reference_count (cairo_surface_t *surface)
  * After calling cairo_surface_finish() the only valid operations on a
  * surface are getting and setting user data and referencing and
  * destroying it.  Further drawing to the surface will not affect the
- * surface but will instead trigger a CAIRO_STATUS_SURFACE_FINISHED
+ * surface but will instead trigger a %CAIRO_STATUS_SURFACE_FINISHED
  * error.
  *
  * When the last call to cairo_surface_destroy() decreases the
@@ -2081,7 +2081,7 @@ _cairo_surface_get_extents (cairo_surface_t         *surface,
 }
 
 /* Note: the backends may modify the contents of the glyph array as long as
- * they do not return %CAIRO_STATUS_UNSUPPORTED. This makes it possible to
+ * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to
  * avoid copying the array again and again, and edit it in-place.
  * Backends are in fact free to use the array as a generic buffer as they
  * see fit.
diff --git a/src/cairo.h b/src/cairo.h
index 4a3a773..42eb027 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1369,26 +1369,26 @@ typedef enum _cairo_path_data_type {
  *
  * <informalexample><programlisting>
  *      int i;
- *      #cairo_path_t *path;
- *      #cairo_path_data_t *data;
+ *      cairo_path_t *path;
+ *      cairo_path_data_t *data;
  * &nbsp;
  *      path = cairo_copy_path (cr);
  * &nbsp;
  *      for (i=0; i < path->num_data; i += path->data[i].header.length) {
  *          data = &amp;path->data[i];
  *          switch (data->header.type) {
- *          case %CAIRO_PATH_MOVE_TO:
+ *          case CAIRO_PATH_MOVE_TO:
  *              do_move_to_things (data[1].point.x, data[1].point.y);
  *              break;
- *          case %CAIRO_PATH_LINE_TO:
+ *          case CAIRO_PATH_LINE_TO:
  *              do_line_to_things (data[1].point.x, data[1].point.y);
  *              break;
- *          case %CAIRO_PATH_CURVE_TO:
+ *          case CAIRO_PATH_CURVE_TO:
  *              do_curve_to_things (data[1].point.x, data[1].point.y,
  *                                  data[2].point.x, data[2].point.y,
  *                                  data[3].point.x, data[3].point.y);
  *              break;
- *          case %CAIRO_PATH_CLOSE_PATH:
+ *          case CAIRO_PATH_CLOSE_PATH:
  *              do_close_path_things ();
  *              break;
  *          }
diff --git a/src/check-doc-syntax.sh b/src/check-doc-syntax.sh
index 1ed24b5..1e5e76a 100755
--- a/src/check-doc-syntax.sh
+++ b/src/check-doc-syntax.sh
@@ -21,36 +21,25 @@ if test "x$SGML_DOCS" = x; then
     fi
 fi
 
-# Note: This test reports false positives on non-gtk-doc comments and
-# non-public enum values, (such as CAIRO_FIXED_FRAC_BITS in the comment
-# for _cairo_output_stream_init). I'm opposed to uglifying those comments
-# with % just to shut this warning up. So instead, I'm turning this check
-# off. (cworth 2008-03-02)
-#
-# Meanwhile, I'd love to see a system that would just link things like
-# enums up without any decoration.
-#
-#enum_regexp='\([^%@]\|^\)\<\(FALSE\|TRUE\|NULL\|CAIRO_[0-9A-Z_]*[^(0-9A-Z_]\)'
-#if test "x$SGML_DOCS" = x; then
-#	enum_regexp='^[/ ][*] .*'$enum_regexp
-#fi
-#if grep "$enum_regexp" $FILES | grep -v '#####'; then
-#	status=1
-#	echo Error: some macros in the docs are not prefixed by percent sign.
-#	echo Fix this by searching for the following regexp in the above files:
-#	echo "	'$enum_regexp'"
-#fi
+enum_regexp='\([^%@]\|^\)\<\(FALSE\|TRUE\|NULL\|CAIRO_[0-9A-Z_]*\)\($\|[^(A-Za-z0-9_]\)'
+if test "x$SGML_DOCS" = x; then
+	enum_regexp='^[^:]*:[/ ][*] .*'$enum_regexp
+fi
+if grep . /dev/null $FILES | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep "$enum_regexp" | grep -v '#####'; then
+	status=1
+	echo Error: some macros in the docs are not prefixed by percent sign.
+	echo Fix this by searching for the following regexp in the above files:
+	echo "	'$enum_regexp'"
+fi
 
 type_regexp='\( .*[^#]\| \|^\)\<cairo[0-9a-z_]*_t\>\($\|[^:]$\|[^:].\)'
 if test "x$SGML_DOCS" = x; then
-	type_regexp='^[/ ][*]'$type_regexp
+	type_regexp='^[^:]*:[/ ][*]'$type_regexp
 else
 	type_regexp='\(.'$type_regexp'\)\|\('$type_regexp'.\)'
 fi
 
-# We need to filter out gtk-doc markup errors for program listings.
-files=`grep "$type_regexp" $FILES | grep -v '#####' | cut -d: -f1 | sort | uniq`
-if test -n "$files" && sed -e '/<programlisting>/,/<\/programlisting>/d' $files | grep "$type_regexp" | grep -v '#####'; then
+if grep . /dev/null $FILES | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep "$type_regexp" | grep -v '#####'; then
 	status=1
 	echo Error: some type names in the docs are not prefixed by hash sign,
 	echo neither are the only token in the doc line followed by colon.
@@ -60,12 +49,11 @@ fi
 
 func_regexp='\([^#]\|^\)\<\(cairo_[][<>/0-9a-z_]*\> \?[^][ <>(]\)'
 if test "x$SGML_DOCS" = x; then
-	func_regexp='^[/ ][*] .*'$func_regexp
+	func_regexp='^[^:]*:[/ ][*] .*'$func_regexp
 fi
 
 # We need to filter out gtk-doc markup errors for program listings.
-files=`grep "$func_regexp" $FILES | grep -v '#####' | cut -d: -f1 | sort | uniq`
-if test -n "$files" && sed -e '/<programlisting>/,/<\/programlisting>/d' $files | grep "$func_regexp" | grep -v '#####'; then
+if grep . /dev/null $FILES | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep "$func_regexp" | grep -v '#####'; then
 	status=1
 	echo Error: some function names in the docs are not followed by parentheses.
 	echo Fix this by searching for the following regexp in the above files:
commit 7dce5360424a98e4100bd78e768c220959633145
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 15:28:02 2008 +0200

    Add XXX marker

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index e12446c..8b250a2 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -818,6 +818,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
 	     * the reference count). To make room for it, we do actually
 	     * destroy the least-recently-used holdover.
 	     */
+
 	    if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
 	    {
 		lru = font_map->holdovers[0];
@@ -1217,7 +1218,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
 	if (status)
 	    return _cairo_scaled_font_set_error (scaled_font, status);
 
-	/* glyph images are snapped to pixel locations */
+	/* XXX glyph images are snapped to pixel locations */
 	x = _cairo_lround (glyphs[i].x);
 	y = _cairo_lround (glyphs[i].y);
 
commit a3c091e29264eec2d3f881dd7c66796d1779d845
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 8 18:18:17 2008 -0400

    [src/check-doc-syntax.sh] Use cairo_all_source_files if available

diff --git a/src/check-doc-syntax.sh b/src/check-doc-syntax.sh
index 1f7cd2a..1ed24b5 100755
--- a/src/check-doc-syntax.sh
+++ b/src/check-doc-syntax.sh
@@ -15,7 +15,10 @@ echo Checking documentation for incorrect syntax
 # Note: this test is also run from doc/public/ to check the SGML files
 
 if test "x$SGML_DOCS" = x; then
-    FILES=`find "$srcdir" -name '*.h' -or -name '*.c' -or -name '*.cpp'`
+    FILES=$cairo_all_source_files
+    if test "x$FILES" = x; then
+        FILES=`find "$srcdir" -name '*.h' -or -name '*.c' -or -name '*.cpp'`
+    fi
 fi
 
 # Note: This test reports false positives on non-gtk-doc comments and
commit e39127627a71fc6655854804de36a802f73c0d42
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 8 18:13:32 2008 -0400

    [Makefile.am] Rename cairo_all_source_file to cairo_all_source_files

diff --git a/src/Makefile.am b/src/Makefile.am
index ebfcf20..e5382d3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -304,7 +304,7 @@ libcairo_la_SOURCES =				\
 	$(cairo_sources)			\
 	$(cairo_special_sources)
 
-cairo_all_source_file =				\
+cairo_all_source_files =			\
 	$(cairo_all_sources)			\
 	$(cairo_special_sources)
 
@@ -354,7 +354,7 @@ install-data-local:
 	  false ;									\
         fi
 
-TESTS_ENVIRONMENT = srcdir="$(srcdir)" MAKE="$(MAKE)" cairo_all_source_file="$(cairo_all_source_file)"
+TESTS_ENVIRONMENT = srcdir="$(srcdir)" MAKE="$(MAKE)" cairo_all_source_files="$(cairo_all_source_files)"
 TESTS = check-def.sh check-plt.sh check-headers.sh check-cairoint.sh check-doc-syntax.sh
 EXTRA_DIST += $(TESTS) check-has-hidden-symbols.c
 DISTCLEANFILES += check-has-hidden-symbols.i
commit d6654ce2a69c3ad30e437d50825166214a5411c2
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 9 11:23:42 2008 +0200

    [Makefile.am] Sort source files

diff --git a/src/Makefile.am b/src/Makefile.am
index 200867a..ebfcf20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,6 +44,7 @@ cairo_base_sources =				\
 	cairo-path-fixed.c			\
 	cairo-path-fixed-private.h		\
 	cairo-path-stroke.c			\
+	cairo-pattern.c				\
 	cairo-pen.c				\
 	cairo-polygon.c				\
 	cairo-rectangle.c			\
@@ -62,7 +63,6 @@ cairo_base_sources =				\
 	cairo-surface-fallback-private.h	\
 	cairo-surface-private.h			\
 	cairo-traps.c				\
-	cairo-pattern.c				\
 	cairo-unicode.c				\
 	cairo-output-stream.c			\
 	cairo-output-stream-private.h		\


More information about the cairo-commit mailing list