[cairo-commit] boilerplate/cairo-boilerplate.c boilerplate/Makefile.win32.features build/configure.ac.features build/Makefile.win32.features-h configure.ac NEWS perf/cairo-perf.c src/cairo.h src/cairo-meta-surface.c src/cairo-meta-surface-private.h src/cairo-paginated-surface.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-script-surface.c src/cairo-surface.c src/cairo-svg-surface.c src/cairo-type3-glyph-surface.c src/cairo-types-private.h src/cairo-user-font.c src/cairo-win32-printing-surface.c src/Makefile.win32.features src/test-meta-surface.c src/test-meta-surface.h test/cairo-test-trace.c test/get-clip.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jul 3 10:34:50 PDT 2009


 NEWS                                |   27 ++++
 boilerplate/Makefile.win32.features |    8 +
 boilerplate/cairo-boilerplate.c     |   12 +-
 build/Makefile.win32.features-h     |    1 
 build/configure.ac.features         |    1 
 configure.ac                        |    4 
 perf/cairo-perf.c                   |    6 -
 src/Makefile.win32.features         |    8 +
 src/cairo-meta-surface-private.h    |   14 --
 src/cairo-meta-surface.c            |  202 +++++++++++++++++++++++++++---------
 src/cairo-paginated-surface.c       |   16 +-
 src/cairo-pdf-surface.c             |    2 
 src/cairo-ps-surface.c              |    2 
 src/cairo-script-surface.c          |   10 -
 src/cairo-surface.c                 |    2 
 src/cairo-svg-surface.c             |    8 -
 src/cairo-type3-glyph-surface.c     |    8 -
 src/cairo-types-private.h           |    3 
 src/cairo-user-font.c               |    7 -
 src/cairo-win32-printing-surface.c  |    2 
 src/cairo.h                         |   22 +++
 src/test-meta-surface.c             |   16 --
 src/test-meta-surface.h             |    8 -
 test/cairo-test-trace.c             |   58 +++-------
 test/get-clip.c                     |    5 
 25 files changed, 296 insertions(+), 156 deletions(-)

New commits:
commit 6003ab77e1ebefadb97338de0e7da4a76d973b1a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jul 3 18:26:50 2009 +0100

    Export meta-surface
    
    The meta-surface is a vital tool to record a trace of drawing commands
    in-memory. As such it is used throughout cairo.
    
    The value of such a surface is immediately obvious and should be
    applicable for many applications. The first such case is by
    cairo-test-trace which wants to record the entire graph of drawing commands
    that affect a surface in the event of a failure.

diff --git a/NEWS b/NEWS
index e23c58b..4072aca 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,30 @@
+Snapshot 1.9.4 (2009-07-xx)
+===========================
+API additions:
+
+  cairo_meta_surface_create()
+  cairo_meta_surface_ink_extents()
+  cairo_meta_surface_replay()
+
+    Finally exporting the internal meta-surface so that applications
+    have a method to record and replay a sequence of drawing commands.
+
+New utilities:
+
+  cairo-test-trace
+
+    A companion to cairo-perf-trace, this utility replays a trace against
+    multiple targets in parallel and looks for differences in the output,
+    and then records any drawing commands that cause a failure.
+    Future plans:
+      Further minimisation of the fail trace using "delta debugging".
+      More control over test/reference targets.
+
+New experimental backends:
+
+   QT
+
+
 Snapshot 1.9.2 (2009-06-12)
 ===========================
 API additions:
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index e80bf03..33eaf5f 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -234,6 +234,14 @@ enabled_cairo_boilerplate_headers += $(cairo_boilerplate_image_headers)
 enabled_cairo_boilerplate_private += $(cairo_boilerplate_image_private)
 enabled_cairo_boilerplate_sources += $(cairo_boilerplate_image_sources)
 
+supported_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_meta_private)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_meta_sources)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_meta_private)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_meta_sources)
+
 supported_cairo_boilerplate_headers += $(cairo_boilerplate_user_headers)
 all_cairo_boilerplate_headers += $(cairo_boilerplate_user_headers)
 all_cairo_boilerplate_private += $(cairo_boilerplate_user_private)
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 285b23a..af6f9fa 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -526,7 +526,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"win32-printing", "win32", ".ps", NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
 	_cairo_boilerplate_win32_printing_create_surface,
 	NULL, NULL,
 	_cairo_boilerplate_win32_printing_get_image_surface,
@@ -613,7 +613,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"ps2", "ps", ".ps", NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
 	_cairo_boilerplate_ps2_create_surface,
 	_cairo_boilerplate_ps_force_fallbacks,
 	_cairo_boilerplate_ps_finish_surface,
@@ -636,7 +636,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"ps3", "ps", ".ps", NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
 	_cairo_boilerplate_ps3_create_surface,
 	_cairo_boilerplate_ps_force_fallbacks,
 	_cairo_boilerplate_ps_finish_surface,
@@ -661,7 +661,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"pdf", "pdf", ".pdf", NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
 	_cairo_boilerplate_pdf_create_surface,
 	_cairo_boilerplate_pdf_force_fallbacks,
 	_cairo_boilerplate_pdf_finish_surface,
@@ -703,7 +703,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"svg11", "svg", NULL, NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
 	_cairo_boilerplate_svg11_create_surface,
 	_cairo_boilerplate_svg_force_fallbacks,
 	_cairo_boilerplate_svg_finish_surface,
@@ -725,7 +725,7 @@ static const cairo_boilerplate_target_t targets[] =
     },
     {
 	"svg12", "svg", NULL, NULL,
-	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+	CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
 	_cairo_boilerplate_svg12_create_surface,
 	_cairo_boilerplate_svg_force_fallbacks,
 	_cairo_boilerplate_svg_finish_surface,
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index 3cfc542..fd5f05d 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -69,5 +69,6 @@ ifeq ($(CAIRO_HAS_TEST_SURFACES),1)
 	@echo "#define CAIRO_HAS_TEST_SURFACES 1" >> src/cairo-features.h
 endif
 	@echo "#define CAIRO_HAS_IMAGE_SURFACE 1" >> src/cairo-features.h
+	@echo "#define CAIRO_HAS_META_SURFACE 1" >> src/cairo-features.h
 	@echo "#define CAIRO_HAS_USER_FONT 1" >> src/cairo-features.h
 	@echo "#endif" >>  src/cairo-features.h
diff --git a/build/configure.ac.features b/build/configure.ac.features
index d3d321f..3f86680 100644
--- a/build/configure.ac.features
+++ b/build/configure.ac.features
@@ -361,6 +361,7 @@ AC_DEFUN([CAIRO_REPORT],
 	echo ""
 	echo "The following surface backends:"
 	echo "  Image:         yes (always builtin)"
+	echo "  Meta:          yes (always builtin)"
 	echo "  Xlib:          $use_xlib"
 	echo "  Xlib Xrender:  $use_xlib_xrender"
 	echo "  Qt:            $use_qt"
diff --git a/configure.ac b/configure.ac
index 06b7fa8..4f8f1b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -472,6 +472,10 @@ CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
 
 dnl ===========================================================================
 
+CAIRO_ENABLE_SURFACE_BACKEND(meta, meta, always)
+
+dnl ===========================================================================
+
 CAIRO_ENABLE_FONT_BACKEND(user, user, always)
 
 dnl ===========================================================================
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 35a89b5..cf757f7 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -68,7 +68,7 @@ const cairo_perf_case_t perf_cases[];
 static cairo_bool_t
 target_is_measurable (const cairo_boilerplate_target_t *target)
 {
-    switch (target->expected_type) {
+    switch ((int) target->expected_type) {
     case CAIRO_SURFACE_TYPE_IMAGE:
 	if (strcmp (target->name, "pdf") == 0 ||
 	    strcmp (target->name, "ps") == 0)
@@ -102,9 +102,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
     case CAIRO_SURFACE_TYPE_QT:
 #endif
 	return TRUE;
-    case CAIRO_SURFACE_TYPE_PDF:
-    case CAIRO_SURFACE_TYPE_PS:
-    case CAIRO_SURFACE_TYPE_SVG:
+
     default:
 	return FALSE;
     }
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index ac8d570..6b989a8 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -316,6 +316,14 @@ enabled_cairo_headers += $(cairo_image_headers)
 enabled_cairo_private += $(cairo_image_private)
 enabled_cairo_sources += $(cairo_image_sources)
 
+supported_cairo_headers += $(cairo_meta_headers)
+all_cairo_headers += $(cairo_meta_headers)
+all_cairo_private += $(cairo_meta_private)
+all_cairo_sources += $(cairo_meta_sources)
+enabled_cairo_headers += $(cairo_meta_headers)
+enabled_cairo_private += $(cairo_meta_private)
+enabled_cairo_sources += $(cairo_meta_sources)
+
 supported_cairo_headers += $(cairo_user_headers)
 all_cairo_headers += $(cairo_user_headers)
 all_cairo_private += $(cairo_user_private)
diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index 8d5e096..f0c95c1 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -150,8 +150,9 @@ typedef struct _cairo_meta_surface {
     /* A meta-surface is logically unbounded, but when used as a
      * source we need to render it to an image, so we need a size at
      * which to create that image. */
-    int width_pixels;
-    int height_pixels;
+    double width_pixels;
+    double height_pixels;
+    cairo_rectangle_int_t extents;
 
     cairo_array_t commands;
     cairo_surface_t *commands_owner;
@@ -160,18 +161,13 @@ typedef struct _cairo_meta_surface {
     int replay_start_idx;
 } cairo_meta_surface_t;
 
-cairo_private cairo_surface_t *
-_cairo_meta_surface_create (cairo_content_t	content,
-			    int			width_pixels,
-			    int			height_pixels);
+slim_hidden_proto (cairo_meta_surface_create);
+slim_hidden_proto (cairo_meta_surface_replay);
 
 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);
 
 cairo_private cairo_status_t
 _cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 9f60007..3c2b74e 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -42,7 +42,9 @@
  * level of paint, mask, stroke, fill, and show_text_glyphs). The meta
  * surface can then be "replayed" against any target surface with:
  *
- *	_cairo_meta_surface_replay (meta, target);
+ * <informalexample><programlisting>
+ *	cairo_meta_surface_replay (meta, target);
+ * </programlisting></informalexample>
  *
  * after which the results in target will be identical to the results
  * that would have been obtained if the original operations applied to
@@ -57,6 +59,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-analysis-surface-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-clip-private.h"
 
@@ -73,13 +76,38 @@ static const cairo_surface_backend_t cairo_meta_surface_backend;
  *
  * XXX: The naming of "pixels" in the size here is a misnomer. It's
  * actually a size in whatever device-space units are desired (again,
- * according to the intended replay target). This should likely also
- * be changed to use doubles not ints.
+ * according to the intended replay target).
  */
+
+/**
+ * cairo_meta_surface_create:
+ * @content: the content of the meta surface
+ * @width_pixels: width of the surface, in pixels
+ * @height_pixels: height of the surface, in pixels
+ *
+ * Creates a meta-surface which can be used to record all drawing operations
+ * at the highest level (that is, the level of paint, mask, stroke, fill
+ * and show_text_glyphs). The meta surface can then be "replayed" against
+ * any target surface with:
+ *
+ * <informalexample><programlisting>
+ *	cairo_meta_surface_replay (meta, target);
+ * </programlisting></informalexample>
+ *
+ * after which the results in target will be identical to the results
+ * that would have been obtained if the original operations applied to
+ * the meta surface had instead been applied to the target surface.
+ *
+ * The recording phase of the meta surface is careful to snapshot all
+ * necessary objects (paths, patterns, etc.), in order to achieve
+ * accurate replay.
+ *
+ * Since 1.10
+ **/
 cairo_surface_t *
-_cairo_meta_surface_create (cairo_content_t	content,
-			    int			width_pixels,
-			    int			height_pixels)
+cairo_meta_surface_create (cairo_content_t	content,
+			   double		width_pixels,
+			   double		height_pixels)
 {
     cairo_meta_surface_t *meta;
 
@@ -94,6 +122,29 @@ _cairo_meta_surface_create (cairo_content_t	content,
     meta->width_pixels = width_pixels;
     meta->height_pixels = height_pixels;
 
+    /* unbounded -> 'infinite' extents */
+    if (width_pixels < 0) {
+	meta->extents.x = CAIRO_RECT_INT_MIN;
+	meta->extents.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    } else {
+	meta->extents.x = 0;
+	if (ceil (width_pixels) > CAIRO_RECT_INT_MAX)
+	    meta->extents.width = CAIRO_RECT_INT_MAX;
+	else
+	    meta->extents.width = ceil (width_pixels);
+    }
+
+    if (height_pixels < 0) {
+	meta->extents.y = CAIRO_RECT_INT_MIN;
+	meta->extents.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    } else {
+	meta->extents.y = 0;
+	if (ceil (height_pixels) > CAIRO_RECT_INT_MAX)
+	    meta->extents.height = CAIRO_RECT_INT_MAX;
+	else
+	    meta->extents.height = ceil (height_pixels);
+    }
+
     _cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
     meta->commands_owner = NULL;
 
@@ -102,6 +153,7 @@ _cairo_meta_surface_create (cairo_content_t	content,
 
     return &meta->base;
 }
+slim_hidden_def (cairo_meta_surface_create);
 
 static cairo_surface_t *
 _cairo_meta_surface_create_similar (void	       *abstract_surface,
@@ -109,7 +161,7 @@ _cairo_meta_surface_create_similar (void	       *abstract_surface,
 				    int			width,
 				    int			height)
 {
-    return _cairo_meta_surface_create (content, width, height);
+    return cairo_meta_surface_create (content, width, height);
 }
 
 static cairo_status_t
@@ -193,10 +245,10 @@ _cairo_meta_surface_acquire_source_image (void			 *abstract_surface,
     cairo_surface_t *image;
 
     image = _cairo_image_surface_create_with_content (surface->content,
-						      surface->width_pixels,
-						      surface->height_pixels);
+						      ceil (surface->width_pixels),
+						      ceil (surface->height_pixels));
 
-    status = _cairo_meta_surface_replay (&surface->base, image);
+    status = cairo_meta_surface_replay (&surface->base, image);
     if (unlikely (status)) {
 	cairo_surface_destroy (image);
 	return status;
@@ -216,6 +268,16 @@ _cairo_meta_surface_release_source_image (void			*abstract_surface,
     cairo_surface_destroy (&image->base);
 }
 
+static void
+_draw_command_init (cairo_command_header_t *command,
+	            cairo_command_type_t type,
+		    cairo_meta_surface_t *meta)
+{
+    command->type = type;
+    command->region = CAIRO_META_REGION_ALL;
+    command->extents = meta->extents;
+}
+
 static cairo_int_status_t
 _cairo_meta_surface_paint (void			*abstract_surface,
 			   cairo_operator_t	 op,
@@ -230,12 +292,7 @@ _cairo_meta_surface_paint (void			*abstract_surface,
     if (unlikely (command == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_PAINT;
-    command->header.region = CAIRO_META_REGION_ALL;
-    command->header.extents.x = 0;
-    command->header.extents.y = 0;
-    command->header.extents.width = meta->width_pixels;
-    command->header.extents.height = meta->height_pixels;
+    _draw_command_init (&command->header, CAIRO_COMMAND_PAINT, meta);
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -276,12 +333,7 @@ _cairo_meta_surface_mask (void			*abstract_surface,
     if (unlikely (command == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_MASK;
-    command->header.region = CAIRO_META_REGION_ALL;
-    command->header.extents.x = 0;
-    command->header.extents.y = 0;
-    command->header.extents.width = meta->width_pixels;
-    command->header.extents.height = meta->height_pixels;
+    _draw_command_init (&command->header, CAIRO_COMMAND_MASK, meta);
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -327,12 +379,7 @@ _cairo_meta_surface_stroke (void			*abstract_surface,
     if (unlikely (command == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_STROKE;
-    command->header.region = CAIRO_META_REGION_ALL;
-    command->header.extents.x = 0;
-    command->header.extents.y = 0;
-    command->header.extents.width = meta->width_pixels;
-    command->header.extents.height = meta->height_pixels;
+    _draw_command_init (&command->header, CAIRO_COMMAND_STROKE, meta);
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -387,12 +434,7 @@ _cairo_meta_surface_fill (void			*abstract_surface,
     if (unlikely (command == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_FILL;
-    command->header.region = CAIRO_META_REGION_ALL;
-    command->header.extents.x = 0;
-    command->header.extents.y = 0;
-    command->header.extents.width = meta->width_pixels;
-    command->header.extents.height = meta->height_pixels;
+    _draw_command_init (&command->header, CAIRO_COMMAND_FILL, meta);
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -450,12 +492,7 @@ _cairo_meta_surface_show_text_glyphs (void			    *abstract_surface,
     if (unlikely (command == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
-    command->header.region = CAIRO_META_REGION_ALL;
-    command->header.extents.x = 0;
-    command->header.extents.y = 0;
-    command->header.extents.width = meta->width_pixels;
-    command->header.extents.height = meta->height_pixels;
+    _draw_command_init (&command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, meta);
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -601,7 +638,7 @@ _cairo_meta_surface_intersect_clip_path (void		    *dst,
 
 /* Currently, we're using as the "size" of a meta surface the largest
  * surface size against which the meta-surface is expected to be
- * replayed, (as passed in to _cairo_meta_surface_create).
+ * replayed, (as passed in to cairo_meta_surface_create()).
  */
 static cairo_int_status_t
 _cairo_meta_surface_get_extents (void			 *abstract_surface,
@@ -609,13 +646,13 @@ _cairo_meta_surface_get_extents (void			 *abstract_surface,
 {
     cairo_meta_surface_t *surface = abstract_surface;
 
-    if (surface->width_pixels == -1 && surface->height_pixels == -1)
+    if (surface->width_pixels < 0 || surface->height_pixels < 0)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     rectangle->x = 0;
     rectangle->y = 0;
-    rectangle->width = surface->width_pixels;
-    rectangle->height = surface->height_pixels;
+    rectangle->width  = ceil (surface->width_pixels);
+    rectangle->height = ceil (surface->height_pixels);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -635,7 +672,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface)
 }
 
 static const cairo_surface_backend_t cairo_meta_surface_backend = {
-    CAIRO_INTERNAL_SURFACE_TYPE_META,
+    CAIRO_SURFACE_TYPE_META,
     _cairo_meta_surface_create_similar,
     _cairo_meta_surface_finish,
     _cairo_meta_surface_acquire_source_image,
@@ -1000,15 +1037,30 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
     return _cairo_surface_set_error (surface, status);
 }
 
+/**
+ * cairo_meta_surface_replay:
+ * @surface: the #cairo_meta_surface_t
+ * @target: a target #cairo_surface_t onto which to replay the operations
+ * @width_pixels: width of the surface, in pixels
+ * @height_pixels: height of the surface, in pixels
+ *
+ * A meta surface can be "replayed" against any target surface,
+ * after which the results in target will be identical to the results
+ * that would have been obtained if the original operations applied to
+ * the meta surface had instead been applied to the target surface.
+ *
+ * Since 1.10
+ **/
 cairo_status_t
-_cairo_meta_surface_replay (cairo_surface_t *surface,
-			    cairo_surface_t *target)
+cairo_meta_surface_replay (cairo_surface_t *surface,
+			   cairo_surface_t *target)
 {
     return _cairo_meta_surface_replay_internal (surface,
 						target,
 						CAIRO_META_REPLAY,
 						CAIRO_META_REGION_ALL);
 }
+slim_hidden_def (cairo_meta_surface_replay);
 
 /* Replay meta to surface. When the return status of each operation is
  * one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
@@ -1036,3 +1088,59 @@ _cairo_meta_surface_replay_region (cairo_surface_t          *surface,
 						CAIRO_META_REPLAY,
 						region);
 }
+
+/**
+ * cairo_meta_surface_ink_extents:
+ * @surface: a #cairo_meta_surface_t
+ * @x0: the x-coordinate of the top-left of the ink bounding box
+ * @y0: the y-coordinate of the top-left of the ink bounding box
+ * @width: the width of the ink bounding box
+ * @height: the height of the ink bounding box
+ *
+ * Measures the extents of the operations stored within the meta-surface.
+ * This is useful to compute the required size of an image surface (or
+ * equivalent) into which to replay the full sequence of drawing operaitions.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_meta_surface_ink_extents (cairo_surface_t *surface,
+				double *x0,
+				double *y0,
+				double *width,
+				double *height)
+{
+    cairo_surface_t *null_surface;
+    cairo_surface_t *analysis_surface;
+    cairo_status_t status;
+    cairo_box_t bbox;
+
+    memset (&bbox, 0, sizeof (bbox));
+
+    if (! _cairo_surface_is_meta (surface)) {
+	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+	goto DONE;
+    }
+
+    null_surface = _cairo_null_surface_create (CAIRO_CONTENT_COLOR_ALPHA);
+    analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
+    cairo_surface_destroy (null_surface);
+
+    status = analysis_surface->status;
+    if (unlikely (status))
+	goto DONE;
+
+    status = cairo_meta_surface_replay (surface, analysis_surface);
+    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
+    cairo_surface_destroy (analysis_surface);
+
+DONE:
+    if (x0)
+	*x0 = _cairo_fixed_to_double (bbox.p1.x);
+    if (y0)
+	*y0 = _cairo_fixed_to_double (bbox.p1.y);
+    if (width)
+	*width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
+    if (height)
+	*height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
+}
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index b84fbff..033df35 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -97,7 +97,7 @@ _cairo_paginated_surface_create (cairo_surface_t				*target,
 
     surface->backend = backend;
 
-    surface->meta = _cairo_meta_surface_create (content, width, height);
+    surface->meta = cairo_meta_surface_create (content, width, height);
     status = cairo_surface_status (surface->meta);
     if (unlikely (status))
 	goto FAIL_CLEANUP_SURFACE;
@@ -148,8 +148,8 @@ _cairo_paginated_surface_set_size (cairo_surface_t	*surface,
     paginated_surface->height = height;
 
     cairo_surface_destroy (paginated_surface->meta);
-    paginated_surface->meta = _cairo_meta_surface_create (paginated_surface->content,
-							  width, height);
+    paginated_surface->meta = cairo_meta_surface_create (paginated_surface->content,
+							 width, height);
     status = cairo_surface_status (paginated_surface->meta);
     if (unlikely (status))
 	return _cairo_surface_set_error (surface, status);
@@ -222,7 +222,7 @@ _cairo_paginated_surface_acquire_source_image (void	       *abstract_surface,
 							   extents.width,
 							   extents.height);
 
-    status = _cairo_meta_surface_replay (surface->meta, image);
+    status = cairo_meta_surface_replay (surface->meta, image);
     if (unlikely (status)) {
 	cairo_surface_destroy (image);
 	return status;
@@ -266,7 +266,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
      * so we have to do the scaling manually. */
     cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
 
-    status = _cairo_meta_surface_replay (surface->meta, image);
+    status = cairo_meta_surface_replay (surface->meta, image);
     if (unlikely (status))
 	goto CLEANUP_IMAGE;
 
@@ -481,9 +481,9 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
 
     cairo_surface_destroy (surface->meta);
 
-    surface->meta = _cairo_meta_surface_create (surface->content,
-						surface->width,
-						surface->height);
+    surface->meta = cairo_meta_surface_create (surface->content,
+					       surface->width,
+                                               surface->height);
     status = cairo_surface_status (surface->meta);
     if (unlikely (status))
 	return status;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 88b1744..6be6245 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1475,7 +1475,7 @@ _cairo_pdf_surface_create_similar (void			*abstract_surface,
 				   int			 width,
 				   int			 height)
 {
-    return _cairo_meta_surface_create (content, width, height);
+    return cairo_meta_surface_create (content, width, height);
 }
 
 static void
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index fde161d..cfe730c 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1294,7 +1294,7 @@ _cairo_ps_surface_create_similar (void			*abstract_surface,
 				  int			 width,
 				  int			 height)
 {
-    return _cairo_meta_surface_create (content, width, height);
+    return cairo_meta_surface_create (content, width, height);
 }
 
 static cairo_status_t
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index dad849f..6d15069 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -840,7 +840,7 @@ _emit_meta_surface_pattern (cairo_script_surface_t *surface,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_meta_surface_replay (source, analysis_surface);
+    status = cairo_meta_surface_replay (source, analysis_surface);
     _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
     cairo_surface_destroy (analysis_surface);
     if (unlikely (status))
@@ -862,7 +862,7 @@ _emit_meta_surface_pattern (cairo_script_surface_t *surface,
 				 _content_to_string (source->content));
     target_push (similar);
 
-    status = _cairo_meta_surface_replay (source, &similar->base);
+    status = cairo_meta_surface_replay (source, &similar->base);
     if (unlikely (status)) {
 	cairo_surface_destroy (&similar->base);
 	return status;
@@ -1145,7 +1145,7 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
     source = surface_pattern->surface;
 
     switch ((int) source->type) {
-    case CAIRO_INTERNAL_SURFACE_TYPE_META:
+    case CAIRO_SURFACE_TYPE_META:
 	return _emit_meta_surface_pattern (surface, pattern);
     case CAIRO_SURFACE_TYPE_SCRIPT:
 	return _emit_script_surface_pattern (surface, pattern);
@@ -2216,8 +2216,8 @@ _emit_scaled_glyph_vector (cairo_script_surface_t *surface,
 
     old_cr = surface->cr;
     _cairo_script_implicit_context_init (&surface->cr);
-    status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
-					 &surface->base);
+    status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
+					&surface->base);
     surface->cr = old_cr;
 
     _cairo_output_stream_puts (surface->ctx->stream, "} set set\n");
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index fd35c12..55aee0e 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1517,7 +1517,7 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
 
 		cairo_surface_set_device_offset (similar, -src_x, -src_y);
 
-		status = _cairo_meta_surface_replay (src, similar);
+		status = cairo_meta_surface_replay (src, similar);
 		if (unlikely (status)) {
 		    cairo_surface_destroy (similar);
 		    return status;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index d74e1f8..15e3684 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -856,7 +856,7 @@ _cairo_svg_surface_create_similar (void			*abstract_src,
 				   int			 width,
 				   int			 height)
 {
-    return _cairo_meta_surface_create (content, width, height);
+    return cairo_meta_surface_create (content, width, height);
 }
 
 static cairo_status_t
@@ -1217,7 +1217,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
 					   document->owner->x_fallback_resolution,
 					   document->owner->y_fallback_resolution);
 
-    status = _cairo_meta_surface_replay (&meta->base, paginated_surface);
+    status = cairo_meta_surface_replay (&meta->base, paginated_surface);
     if (unlikely (status)) {
 	cairo_surface_destroy (&meta->base);
 	cairo_surface_destroy (paginated_surface);
@@ -1334,8 +1334,8 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t	*output,
 				     "patternUnits=\"userSpaceOnUse\" "
 				     "width=\"%d\" height=\"%d\"",
 				     pattern_id,
-				     meta_surface->width_pixels,
-				     meta_surface->height_pixels);
+				     (int) ceil (meta_surface->width_pixels),
+				     (int) ceil (meta_surface->height_pixels));
 	_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
 	_cairo_output_stream_printf (output, ">\n");
     }
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 104da53..6e72596 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -425,8 +425,8 @@ _cairo_type3_glyph_surface_analyze_glyph (void		     *abstract_surface,
 	goto cleanup;
     }
 
-    status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
-					 &surface->base);
+    status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
+					&surface->base);
     if (unlikely (status))
 	goto cleanup;
 
@@ -520,8 +520,8 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
 	_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
 
 	_cairo_output_stream_printf (surface->stream, "q\n");
-	status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
-					     &surface->base);
+	status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
+					    &surface->base);
 
 	status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
 	if (status == CAIRO_STATUS_SUCCESS)
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 1edd24f..2ed3264 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -162,8 +162,7 @@ typedef enum _cairo_int_status {
 } cairo_int_status_t;
 
 typedef enum _cairo_internal_surface_type {
-    CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
-    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED = 0x1000,
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 5ab9751..1adfd7d 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -85,7 +85,7 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
 						     CAIRO_CONTENT_COLOR_ALPHA :
 						     CAIRO_CONTENT_ALPHA;
 
-    meta_surface = _cairo_meta_surface_create (content, -1, -1);
+    meta_surface = cairo_meta_surface_create (content, -1, -1);
     cr = cairo_create (meta_surface);
     cairo_surface_destroy (meta_surface);
 
@@ -158,8 +158,7 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 
 	    _cairo_analysis_surface_set_ctm (analysis_surface,
 					     &scaled_font->extent_scale);
-	    status = _cairo_meta_surface_replay (meta_surface,
-						 analysis_surface);
+	    status = cairo_meta_surface_replay (meta_surface, analysis_surface);
 	    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
 	    cairo_surface_destroy (analysis_surface);
 
@@ -214,7 +213,7 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 	cairo_surface_set_device_offset (surface,
 	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
 	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
-	status = _cairo_meta_surface_replay (meta_surface, surface);
+	status = cairo_meta_surface_replay (meta_surface, surface);
 
 	if (unlikely (status)) {
 	    cairo_surface_destroy(surface);
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index e7ff3bb..9025bfa 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1607,7 +1607,7 @@ _cairo_win32_printing_surface_create_similar (void		*abstract_surface,
 					      int		 width,
 					      int		 height)
 {
-    return _cairo_meta_surface_create (content, width, height);
+    return cairo_meta_surface_create (content, width, height);
 }
 
 static cairo_int_status_t
diff --git a/src/cairo.h b/src/cairo.h
index 37ccdc3..8f7e533 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1890,6 +1890,7 @@ cairo_surface_status (cairo_surface_t *surface);
  * @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
  * @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
  * @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10
+ * @CAIRO_SURFACE_TYPE_META: The surface is a meta-type, since 1.10
  *
  * #cairo_surface_type_t is used to describe the type of a given
  * surface. The surface types are also known as "backends" or "surface
@@ -1930,7 +1931,8 @@ typedef enum _cairo_surface_type {
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
     CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
     CAIRO_SURFACE_TYPE_SCRIPT,
-    CAIRO_SURFACE_TYPE_QT
+    CAIRO_SURFACE_TYPE_QT,
+    CAIRO_SURFACE_TYPE_META
 } cairo_surface_type_t;
 
 cairo_public cairo_surface_type_t
@@ -2108,6 +2110,24 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t	read_func,
 
 #endif
 
+/* Meta-surface functions */
+
+cairo_public cairo_surface_t *
+cairo_meta_surface_create (cairo_content_t	content,
+			   double		width_pixels,
+			   double		height_pixels);
+
+cairo_public void
+cairo_meta_surface_ink_extents (cairo_surface_t *surface,
+				double *x0,
+				double *y0,
+				double *width,
+				double *height);
+
+cairo_public cairo_status_t
+cairo_meta_surface_replay (cairo_surface_t *surface,
+			   cairo_surface_t *target);
+
 /* Pattern creation functions */
 
 cairo_public cairo_pattern_t *
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 7af5df7..80e56f3 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -136,7 +136,7 @@ _test_meta_surface_show_page (void *abstract_surface)
 	    return status;
     }
 
-    status = _cairo_meta_surface_replay (surface->meta, surface->image);
+    status = cairo_meta_surface_replay (surface->meta, surface->image);
     if (status)
 	return status;
 
@@ -338,7 +338,7 @@ _cairo_test_meta_surface_create (cairo_content_t	content,
     _cairo_surface_init (&surface->base, &test_meta_surface_backend,
 			 content);
 
-    surface->meta = _cairo_meta_surface_create (content, width, height);
+    surface->meta = cairo_meta_surface_create (content, width, height);
     status = cairo_surface_status (surface->meta);
     if (status)
 	goto FAIL;
@@ -356,15 +356,3 @@ _cairo_test_meta_surface_create (cairo_content_t	content,
     return _cairo_surface_create_in_error (status);
 }
 slim_hidden_def (_cairo_test_meta_surface_create);
-
-cairo_status_t
-_cairo_test_meta_surface_replay (cairo_surface_t *abstract_surface,
-				 cairo_surface_t *target)
-{
-    test_meta_surface_t *surface = (test_meta_surface_t *) abstract_surface;
-
-    if (abstract_surface->backend != &test_meta_surface_backend)
-	return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
-
-    return _cairo_meta_surface_replay (surface->meta, target);
-}
diff --git a/src/test-meta-surface.h b/src/test-meta-surface.h
index a251fd4..4cd27d8 100644
--- a/src/test-meta-surface.h
+++ b/src/test-meta-surface.h
@@ -42,12 +42,8 @@ CAIRO_BEGIN_DECLS
 
 cairo_surface_t *
 _cairo_test_meta_surface_create (cairo_content_t	content,
-			   int			width,
-			   int			height);
-
-cairo_status_t
-_cairo_test_meta_surface_replay (cairo_surface_t *abstract_surface,
-				 cairo_surface_t *target);
+			         int			width,
+                                 int			height);
 
 CAIRO_END_DECLS
 
diff --git a/test/cairo-test-trace.c b/test/cairo-test-trace.c
index 18e1934..bee0551 100644
--- a/test/cairo-test-trace.c
+++ b/test/cairo-test-trace.c
@@ -64,9 +64,6 @@
 #include <cairo-script.h>
 #endif
 
-/* XXX give me a real meta surface! */
-#include <test-meta-surface.h>
-
 /* For basename */
 #ifdef HAVE_LIBGEN_H
 #include <libgen.h>
@@ -603,9 +600,6 @@ cleanup_recorder (void *arg)
     cairo_surface_finish (thread->surface);
     cairo_surface_destroy (thread->surface);
 
-    if (thread->target->cleanup)
-	thread->target->cleanup (thread->closure);
-
     close (thread->sk);
     free (thread);
 }
@@ -628,9 +622,7 @@ record (void *arg)
  * 2. Runs in the same process, but separate thread.
  */
 static pid_t
-spawn_recorder (const char *socket_path,
-		const cairo_boilerplate_target_t *target,
-		const char *trace)
+spawn_recorder (const char *socket_path, const char *trace)
 {
     test_runner_thread_t *thread;
     pthread_t id;
@@ -653,18 +645,13 @@ spawn_recorder (const char *socket_path,
     }
 
     thread->base = NULL;
-    thread->target = target;
+    thread->target = NULL;
     thread->contexts = NULL;
     thread->context_id = 0;
     thread->trace = trace;
 
-    thread->surface = target->create_surface (NULL,
-					      target->content,
-					      1, 1,
-					      1, 1,
-					      CAIRO_BOILERPLATE_MODE_TEST,
-					      0,
-					      &thread->closure);
+    thread->surface = cairo_meta_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
+                                                 0, 0);
     if (thread->surface == NULL) {
 	cleanup_recorder (thread);
 	return -1;
@@ -853,7 +840,7 @@ static void
 write_images (const char *trace, struct slave *slave, int num_slaves)
 {
     while (num_slaves--) {
-	if (slave->image != NULL) {
+	if (slave->image != NULL && ! slave->is_meta) {
 	    char *filename;
 
 	    xasprintf (&filename, "%s-%s-fail.png",
@@ -887,7 +874,7 @@ write_trace (const char *trace, struct slave *slave)
 					  slave->height);
     free (filename);
 
-    status = _cairo_test_meta_surface_replay (slave->image, script);
+    status = cairo_meta_surface_replay (slave->image, script);
     cairo_surface_destroy (script);
 #endif
 }
@@ -1179,6 +1166,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
     case CAIRO_SURFACE_TYPE_SCRIPT:
     case CAIRO_SURFACE_TYPE_SVG:
     case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
+    case CAIRO_SURFACE_TYPE_META:
     default:
 	return FALSE;
     }
@@ -1243,8 +1231,9 @@ _test_trace (test_runner_t *test,
 	     struct error_info *error)
 {
     const char *shm_path = SHM_PATH_XXX;
-    const cairo_boilerplate_target_t *target, *image, *meta;
+    const cairo_boilerplate_target_t *target, *image;
     struct slave *slaves, *s;
+    pid_t slave;
     char socket_dir[] = "/tmp/cairo-test-trace.XXXXXX";
     char *socket_path;
     int sk, fd;
@@ -1280,29 +1269,22 @@ _test_trace (test_runner_t *test,
 
 #if HAVE_PTHREAD_H
     /* set-up a meta-surface to reconstruct errors */
-    meta = cairo_boilerplate_get_target_by_name ("test-meta",
-						 CAIRO_CONTENT_COLOR_ALPHA);
-    if (meta != NULL) {
-	pid_t slave;
-
-	slave = spawn_recorder (socket_path, meta, trace);
-	if (slave < 0) {
-	    fprintf (stderr, "Unable to create meta surface\n");
-	    goto cleanup_sk;
-	}
-
-	s->pid = slave;
-	s->is_meta = TRUE;
-	s->target = meta;
-	s->fd = -1;
-	s->reference = NULL;
-	s++;
+    slave = spawn_recorder (socket_path, trace);
+    if (slave < 0) {
+        fprintf (stderr, "Unable to create meta surface\n");
+        goto cleanup_sk;
     }
+
+    s->pid = slave;
+    s->is_meta = TRUE;
+    s->target = NULL;
+    s->fd = -1;
+    s->reference = NULL;
+    s++;
 #endif
 
     /* spawn slave processes to run the trace */
     for (i = 0; i < test->num_targets; i++) {
-	pid_t slave;
 	const cairo_boilerplate_target_t *reference;
 	struct slave *master;
 
diff --git a/test/get-clip.c b/test/get-clip.c
index 1a07f01..c7414b4 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -132,10 +132,15 @@ draw (cairo_t *cr, int width, int height)
         uses_clip_rects = TRUE;
 	break;
     case CAIRO_SURFACE_TYPE_QUARTZ:
+    case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
     case CAIRO_SURFACE_TYPE_SVG:
     case CAIRO_SURFACE_TYPE_OS2:
+    case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
+    case CAIRO_SURFACE_TYPE_SCRIPT:
+    case CAIRO_SURFACE_TYPE_QT:
+    case CAIRO_SURFACE_TYPE_META:
     default:
         uses_clip_rects = FALSE;
         break;


More information about the cairo-commit mailing list