[cairo-commit] boilerplate/cairo-boilerplate.c boilerplate/cairo-boilerplate.h boilerplate/cairo-boilerplate-pdf.c boilerplate/cairo-boilerplate-pdf.h boilerplate/cairo-boilerplate-pdf-private.h boilerplate/cairo-boilerplate-ps.c boilerplate/cairo-boilerplate-ps.h boilerplate/cairo-boilerplate-ps-private.h boilerplate/cairo-boilerplate-svg.c boilerplate/cairo-boilerplate-svg.h boilerplate/cairo-boilerplate-svg-private.h boilerplate/cairo-boilerplate-test-surfaces.c boilerplate/cairo-boilerplate-test-surfaces-private.h boilerplate/cairo-boilerplate-win32-printing.c boilerplate/cairo-boilerplate-win32-private.h src/cairo-svg-surface.c test/cairo-test.c test/cairo-test.h test/fallback-resolution.c test/fallback-resolution-ppi150-ref.png test/fallback-resolution-ppi300-ref.png test/fallback-resolution-ppi37.5-ref.png test/fallback-resolution-ppi600-ref.png test/fallback-resolution-ppi72-ref.png test/fallback-resolution-ppi75-ref.png test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Sun Sep 28 06:58:01 PDT 2008


 boilerplate/cairo-boilerplate-pdf-private.h           |    5 
 boilerplate/cairo-boilerplate-pdf.c                   |   29 -
 boilerplate/cairo-boilerplate-pdf.h                   |   33 -
 boilerplate/cairo-boilerplate-ps-private.h            |    9 
 boilerplate/cairo-boilerplate-ps.c                    |   33 -
 boilerplate/cairo-boilerplate-ps.h                    |   33 -
 boilerplate/cairo-boilerplate-svg-private.h           |    5 
 boilerplate/cairo-boilerplate-svg.c                   |   36 -
 boilerplate/cairo-boilerplate-svg.h                   |   33 -
 boilerplate/cairo-boilerplate-test-surfaces-private.h |    1 
 boilerplate/cairo-boilerplate-test-surfaces.c         |    7 
 boilerplate/cairo-boilerplate-win32-printing.c        |    5 
 boilerplate/cairo-boilerplate-win32-private.h         |    1 
 boilerplate/cairo-boilerplate.c                       |   74 +--
 boilerplate/cairo-boilerplate.h                       |    7 
 src/cairo-svg-surface.c                               |    6 
 test/Makefile.am                                      |    6 
 test/cairo-test.c                                     |   36 -
 test/cairo-test.h                                     |   12 
 test/fallback-resolution-ppi150-ref.png               |binary
 test/fallback-resolution-ppi300-ref.png               |binary
 test/fallback-resolution-ppi37.5-ref.png              |binary
 test/fallback-resolution-ppi600-ref.png               |binary
 test/fallback-resolution-ppi72-ref.png                |binary
 test/fallback-resolution-ppi75-ref.png                |binary
 test/fallback-resolution.c                            |  413 +++++++++++++-----
 26 files changed, 486 insertions(+), 298 deletions(-)

New commits:
commit 9841d9d58ea286f798626d325d50a85bf3f02c8f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 28 13:34:50 2008 +0100

    Automate error checking for fallback-resolution.
    
    For this we extend the boilerplate get_image() routines to extract a
    single page out of a paginated document and then proceed to manually
    check each page of the fallback-resolution test.
    
    (Well that's the theory, in practice SVG doesn't support multiple pages
    and so we just generate a new surface for each resolution. But the
    infrastructure is in place so that we can automate other tests,
    e.g. test/multi-pages.)

diff --git a/boilerplate/cairo-boilerplate-pdf-private.h b/boilerplate/cairo-boilerplate-pdf-private.h
index 981fa8d..3c34c3e 100644
--- a/boilerplate/cairo-boilerplate-pdf-private.h
+++ b/boilerplate/cairo-boilerplate-pdf-private.h
@@ -38,6 +38,10 @@ _cairo_boilerplate_pdf_create_surface (const char		 *name,
 				       int                        id,
 				       void			**closure);
 
+void
+_cairo_boilerplate_pdf_force_fallbacks (cairo_surface_t *abstract_surface,
+	                                unsigned int flags);
+
 cairo_status_t
 _cairo_boilerplate_pdf_finish_surface (cairo_surface_t		*surface);
 
@@ -46,6 +50,7 @@ _cairo_boilerplate_pdf_surface_write_to_png (cairo_surface_t *surface, const cha
 
 cairo_surface_t *
 _cairo_boilerplate_pdf_get_image_surface (cairo_surface_t *surface,
+					  int page,
 					  int width,
 					  int height);
 
diff --git a/boilerplate/cairo-boilerplate-pdf.c b/boilerplate/cairo-boilerplate-pdf.c
index 470fb06..7000238 100644
--- a/boilerplate/cairo-boilerplate-pdf.c
+++ b/boilerplate/cairo-boilerplate-pdf.c
@@ -25,7 +25,6 @@
  */
 
 #include "cairo-boilerplate.h"
-#include "cairo-boilerplate-pdf.h"
 #include "cairo-boilerplate-pdf-private.h"
 
 #include <cairo-pdf.h>
@@ -174,26 +173,27 @@ _cairo_boilerplate_pdf_surface_write_to_png (cairo_surface_t *surface, const cha
 }
 
 static cairo_surface_t *
-_cairo_boilerplate_pdf_convert_to_image (cairo_surface_t *surface)
+_cairo_boilerplate_pdf_convert_to_image (cairo_surface_t *surface, int page)
 {
     pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface,
 							     &pdf_closure_key);
 
-    return cairo_boilerplate_convert_to_image (ptc->filename, 1);
+    return cairo_boilerplate_convert_to_image (ptc->filename, page+1);
 }
 
 cairo_surface_t *
 _cairo_boilerplate_pdf_get_image_surface (cairo_surface_t *surface,
+					  int page,
 					  int width,
 					  int height)
 {
     cairo_surface_t *image;
 
-    image = _cairo_boilerplate_pdf_convert_to_image (surface);
+    image = _cairo_boilerplate_pdf_convert_to_image (surface, page);
     cairo_surface_set_device_offset (image,
 				     cairo_image_surface_get_width (image) - width,
 				     cairo_image_surface_get_height (image) - height);
-    surface = _cairo_boilerplate_get_image_surface (image, width, height);
+    surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
     cairo_surface_destroy (image);
 
     return surface;
@@ -209,18 +209,21 @@ _cairo_boilerplate_pdf_cleanup (void *closure)
     free (ptc);
 }
 
-cairo_status_t
-cairo_boilerplate_pdf_surface_force_fallbacks (cairo_surface_t *abstract_surface)
+
+void
+_cairo_boilerplate_pdf_force_fallbacks (cairo_surface_t *abstract_surface,
+	                                unsigned int flags)
 {
-    cairo_paginated_surface_t *paginated = (cairo_paginated_surface_t*) abstract_surface;
+    pdf_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
+							     &pdf_closure_key);
+
+    cairo_paginated_surface_t *paginated;
     cairo_pdf_surface_t *surface;
 
-    if (cairo_surface_get_type (abstract_surface) != CAIRO_SURFACE_TYPE_PDF)
-	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+    if (ptc->target)
+	abstract_surface = ptc->target;
 
+    paginated = (cairo_paginated_surface_t*) abstract_surface;
     surface = (cairo_pdf_surface_t*) paginated->target;
-
     surface->force_fallbacks = TRUE;
-
-    return CAIRO_STATUS_SUCCESS;
 }
diff --git a/boilerplate/cairo-boilerplate-pdf.h b/boilerplate/cairo-boilerplate-pdf.h
deleted file mode 100644
index 6aac402..0000000
--- a/boilerplate/cairo-boilerplate-pdf.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/*
- * Copyright © 2007 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.
- *
- * Author: Behdad Esfahbod <behdad at behdad.org>
- */
-
-#ifndef _CAIRO_BOILERPLATE_PDF_H_
-#define _CAIRO_BOILERPLATE_PDF_H_
-
-cairo_status_t
-cairo_boilerplate_pdf_surface_force_fallbacks (cairo_surface_t *surface);
-
-#endif
diff --git a/boilerplate/cairo-boilerplate-ps-private.h b/boilerplate/cairo-boilerplate-ps-private.h
index a6a1950..b97c7db 100644
--- a/boilerplate/cairo-boilerplate-ps-private.h
+++ b/boilerplate/cairo-boilerplate-ps-private.h
@@ -50,6 +50,10 @@ _cairo_boilerplate_ps3_create_surface (const char		 *name,
 				       void			**closure);
 
 void
+_cairo_boilerplate_ps_force_fallbacks (cairo_surface_t *abstract_surface,
+	                               unsigned int flags);
+
+void
 _cairo_boilerplate_ps_cleanup (void *closure);
 
 cairo_status_t
@@ -60,7 +64,8 @@ _cairo_boilerplate_ps_surface_write_to_png (cairo_surface_t *surface, const char
 
 cairo_surface_t *
 _cairo_boilerplate_ps_get_image_surface (cairo_surface_t *surface,
-					  int width,
-					  int height);
+					 int page,
+					 int width,
+					 int height);
 
 #endif
diff --git a/boilerplate/cairo-boilerplate-ps.c b/boilerplate/cairo-boilerplate-ps.c
index 7c6ebe9..b2e1e12 100644
--- a/boilerplate/cairo-boilerplate-ps.c
+++ b/boilerplate/cairo-boilerplate-ps.c
@@ -25,7 +25,6 @@
  */
 
 #include "cairo-boilerplate.h"
-#include "cairo-boilerplate-ps.h"
 #include "cairo-boilerplate-ps-private.h"
 
 #include <cairo-ps.h>
@@ -235,19 +234,27 @@ _cairo_boilerplate_ps_surface_write_to_png (cairo_surface_t *surface, const char
 
 cairo_surface_t *
 _cairo_boilerplate_ps_get_image_surface (cairo_surface_t *surface,
-					  int width,
-					  int height)
+					 int page,
+					 int width,
+					 int height)
 {
     ps_target_closure_t *ptc = cairo_surface_get_user_data (surface,
 							    &ps_closure_key);
     char *filename;
     cairo_status_t status;
 
-    xasprintf (&filename, "%s.png", ptc->filename);
+    if (page == 0)
+	xasprintf (&filename, "%s.png", ptc->filename);
+    else
+	xasprintf (&filename, "%s-%%05d.png", ptc->filename);
     status = _cairo_boilerplate_ps_surface_write_to_png (surface, filename);
     if (status)
 	return cairo_boilerplate_surface_create_in_error (status);
 
+    if (page != 0) {
+	free (filename);
+	xasprintf (&filename, "%s-%05d.png", ptc->filename, page);
+    }
     surface = cairo_boilerplate_get_image_surface_from_png (filename,
 							    width,
 							    height,
@@ -269,18 +276,20 @@ _cairo_boilerplate_ps_cleanup (void *closure)
     free (ptc);
 }
 
-cairo_status_t
-cairo_boilerplate_ps_surface_force_fallbacks (cairo_surface_t *abstract_surface)
+void
+_cairo_boilerplate_ps_force_fallbacks (cairo_surface_t *abstract_surface,
+	                               unsigned int flags)
 {
-    cairo_paginated_surface_t *paginated = (cairo_paginated_surface_t*) abstract_surface;
+    ps_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
+							    &ps_closure_key);
+
+    cairo_paginated_surface_t *paginated;
     cairo_ps_surface_t *surface;
 
-    if (cairo_surface_get_type (abstract_surface) != CAIRO_SURFACE_TYPE_PS)
-	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+    if (ptc->target)
+	abstract_surface = ptc->target;
 
+    paginated = (cairo_paginated_surface_t*) abstract_surface;
     surface = (cairo_ps_surface_t*) paginated->target;
-
     surface->force_fallbacks = TRUE;
-
-    return CAIRO_STATUS_SUCCESS;
 }
diff --git a/boilerplate/cairo-boilerplate-ps.h b/boilerplate/cairo-boilerplate-ps.h
deleted file mode 100644
index 5cc5c18..0000000
--- a/boilerplate/cairo-boilerplate-ps.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/*
- * Copyright © 2007 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.
- *
- * Author: Behdad Esfahbod <behdad at behdad.org>
- */
-
-#ifndef _CAIRO_BOILERPLATE_PS_H_
-#define _CAIRO_BOILERPLATE_PS_H_
-
-cairo_status_t
-cairo_boilerplate_ps_surface_force_fallbacks (cairo_surface_t *surface);
-
-#endif
diff --git a/boilerplate/cairo-boilerplate-svg-private.h b/boilerplate/cairo-boilerplate-svg-private.h
index 075bdcd..d8c0a8f 100644
--- a/boilerplate/cairo-boilerplate-svg-private.h
+++ b/boilerplate/cairo-boilerplate-svg-private.h
@@ -49,6 +49,10 @@ _cairo_boilerplate_svg12_create_surface (const char		 *name,
 					 int                      id,
 					 void			**closure);
 
+void
+_cairo_boilerplate_svg_force_fallbacks (cairo_surface_t *surface,
+	                                unsigned int flags);
+
 
 cairo_status_t
 _cairo_boilerplate_svg_finish_surface (cairo_surface_t		*surface);
@@ -58,6 +62,7 @@ _cairo_boilerplate_svg_surface_write_to_png (cairo_surface_t *surface, const cha
 
 cairo_surface_t *
 _cairo_boilerplate_svg_get_image_surface (cairo_surface_t *surface,
+					  int page,
 					  int width,
 					  int height);
 
diff --git a/boilerplate/cairo-boilerplate-svg.c b/boilerplate/cairo-boilerplate-svg.c
index 227088c..195dc78 100644
--- a/boilerplate/cairo-boilerplate-svg.c
+++ b/boilerplate/cairo-boilerplate-svg.c
@@ -25,7 +25,6 @@
  */
 
 #include "cairo-boilerplate.h"
-#include "cairo-boilerplate-svg.h"
 #include "cairo-boilerplate-svg-private.h"
 
 #include <cairo-svg.h>
@@ -37,7 +36,7 @@
 #include <signal.h>
 #endif
 
-cairo_user_data_key_t	svg_closure_key;
+static const cairo_user_data_key_t svg_closure_key;
 
 typedef struct _svg_target_closure {
     char    *filename;
@@ -83,9 +82,8 @@ _cairo_boilerplate_svg_create_surface (const char		 *name,
 						width, height);
 	if (cairo_surface_status (surface))
 	    goto CLEANUP_TARGET;
-    } else {
+    } else
 	ptc->target = NULL;
-    }
 
     status = cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
     if (status == CAIRO_STATUS_SUCCESS)
@@ -144,7 +142,8 @@ _cairo_boilerplate_svg12_create_surface (const char		 *name,
 cairo_status_t
 _cairo_boilerplate_svg_finish_surface (cairo_surface_t		*surface)
 {
-    svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
+    svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
+	                                                     &svg_closure_key);
     cairo_status_t status;
 
     /* Both surface and ptc->target were originally created at the
@@ -187,7 +186,8 @@ _cairo_boilerplate_svg_finish_surface (cairo_surface_t		*surface)
 cairo_status_t
 _cairo_boilerplate_svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
 {
-    svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
+    svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
+	                                                     &svg_closure_key);
     char    command[4096];
     int exitstatus;
 
@@ -216,16 +216,20 @@ _cairo_boilerplate_svg_convert_to_image (cairo_surface_t *surface)
 
 cairo_surface_t *
 _cairo_boilerplate_svg_get_image_surface (cairo_surface_t *surface,
+					  int page,
 					  int width,
 					  int height)
 {
     cairo_surface_t *image;
 
+    if (page != 0)
+	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+
     image = _cairo_boilerplate_svg_convert_to_image (surface);
     cairo_surface_set_device_offset (image,
 				     cairo_image_surface_get_width (image) - width,
 				     cairo_image_surface_get_height (image) - height);
-    surface = _cairo_boilerplate_get_image_surface (image, width, height);
+    surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
     cairo_surface_destroy (image);
 
     return surface;
@@ -241,18 +245,20 @@ _cairo_boilerplate_svg_cleanup (void *closure)
     free (ptc);
 }
 
-cairo_status_t
-cairo_boilerplate_svg_surface_force_fallbacks (cairo_surface_t *abstract_surface)
+void
+_cairo_boilerplate_svg_force_fallbacks (cairo_surface_t *abstract_surface,
+	                                unsigned int flags)
 {
-    cairo_paginated_surface_t *paginated = (cairo_paginated_surface_t*) abstract_surface;
+    svg_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
+							     &svg_closure_key);
+
+    cairo_paginated_surface_t *paginated;
     cairo_svg_surface_t *surface;
 
-    if (cairo_surface_get_type (abstract_surface) != CAIRO_SURFACE_TYPE_SVG)
-	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+    if (ptc->target)
+	abstract_surface = ptc->target;
 
+    paginated = (cairo_paginated_surface_t*) abstract_surface;
     surface = (cairo_svg_surface_t*) paginated->target;
-
     surface->force_fallbacks = TRUE;
-
-    return CAIRO_STATUS_SUCCESS;
 }
diff --git a/boilerplate/cairo-boilerplate-svg.h b/boilerplate/cairo-boilerplate-svg.h
deleted file mode 100644
index 1229916..0000000
--- a/boilerplate/cairo-boilerplate-svg.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/*
- * Copyright © 2007 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.
- *
- * Author: Behdad Esfahbod <behdad at behdad.org>
- */
-
-#ifndef _CAIRO_BOILERPLATE_SVG_H_
-#define _CAIRO_BOILERPLATE_SVG_H_
-
-cairo_status_t
-cairo_boilerplate_svg_surface_force_fallbacks (cairo_surface_t *surface);
-
-#endif
diff --git a/boilerplate/cairo-boilerplate-test-surfaces-private.h b/boilerplate/cairo-boilerplate-test-surfaces-private.h
index ed6cb5b..481b531 100644
--- a/boilerplate/cairo-boilerplate-test-surfaces-private.h
+++ b/boilerplate/cairo-boilerplate-test-surfaces-private.h
@@ -68,6 +68,7 @@ _cairo_boilerplate_test_paginated_surface_write_to_png (cairo_surface_t	*surface
 
 cairo_surface_t *
 _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
+						     int page,
 						     int width,
 						     int height);
 
diff --git a/boilerplate/cairo-boilerplate-test-surfaces.c b/boilerplate/cairo-boilerplate-test-surfaces.c
index 297faff..f6fd63a 100644
--- a/boilerplate/cairo-boilerplate-test-surfaces.c
+++ b/boilerplate/cairo-boilerplate-test-surfaces.c
@@ -166,6 +166,7 @@ _cairo_boilerplate_test_paginated_surface_write_to_png (cairo_surface_t	*surface
 
 cairo_surface_t *
 _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
+						     int page,
 						     int width,
 						     int height)
 {
@@ -173,6 +174,10 @@ _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
     test_paginated_closure_t *tpc;
     cairo_status_t status;
 
+    /* XXX separate finish as per PDF */
+    if (page != 0)
+	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+
     /* show page first.  the automatic show_page is too late for us */
     cairo_surface_show_page (surface);
     status = cairo_surface_status (surface);
@@ -200,7 +205,7 @@ _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
 	cairo_surface_set_device_offset (image,
 					 tpc->width - width,
 					 tpc->height - height);
-	surface = _cairo_boilerplate_get_image_surface (image, width, height);
+	surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
 	cairo_surface_destroy (image);
 	return surface;
     }
diff --git a/boilerplate/cairo-boilerplate-win32-printing.c b/boilerplate/cairo-boilerplate-win32-printing.c
index faddb6a..a5f21ff 100644
--- a/boilerplate/cairo-boilerplate-win32-printing.c
+++ b/boilerplate/cairo-boilerplate-win32-printing.c
@@ -302,6 +302,7 @@ _cairo_boilerplate_win32_printing_surface_write_to_png (cairo_surface_t *surface
 
 cairo_surface_t *
 _cairo_boilerplate_win32_printing_get_image_surface (cairo_surface_t *surface,
+						     int page,
 						     int width,
 						     int height)
 {
@@ -310,6 +311,10 @@ _cairo_boilerplate_win32_printing_get_image_surface (cairo_surface_t *surface,
     char *filename;
     cairo_status_t status;
 
+    /* XXX test paginated interface */
+    if (page != 0)
+	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+
     xasprintf (&filename, "%s.png", ptc->filename);
     status = _cairo_boilerplate_win32_printing_surface_write_to_png (surface, filename);
     if (status)
diff --git a/boilerplate/cairo-boilerplate-win32-private.h b/boilerplate/cairo-boilerplate-win32-private.h
index 093ca9b..fc039ae 100644
--- a/boilerplate/cairo-boilerplate-win32-private.h
+++ b/boilerplate/cairo-boilerplate-win32-private.h
@@ -58,6 +58,7 @@ _cairo_boilerplate_win32_printing_surface_write_to_png (cairo_surface_t *surface
 
 cairo_surface_t *
 _cairo_boilerplate_win32_printing_get_image_surface (cairo_surface_t *surface,
+						     int page,
 						     int width,
 						     int height);
 
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index f88d983..cc64490 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -160,6 +160,7 @@ _cairo_boilerplate_image_create_surface (const char			 *name,
 
 cairo_surface_t *
 _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
+				      int page,
 				      int width,
 				      int height)
 {
@@ -187,6 +188,9 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
     }
 #endif
 
+    if (page != 0)
+	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+
     /* extract sub-surface */
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
     cr = cairo_create (surface);
@@ -265,50 +269,50 @@ static cairo_boilerplate_target_t targets[] =
      * for tolerance. There shouldn't ever be anything that is out of
      * our control here. */
     { "image", NULL, CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_image_create_surface,
+      _cairo_boilerplate_image_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
     { "image", NULL, CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_image_create_surface,
+      _cairo_boilerplate_image_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
 #ifdef CAIRO_HAS_TEST_SURFACES
     { "test-fallback", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
       CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_fallback_create_surface,
+      _cairo_boilerplate_test_fallback_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
     { "test-fallback", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
       CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_fallback_create_surface,
+      _cairo_boilerplate_test_fallback_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
     { "test-meta", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
       CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_meta_create_surface,
+      _cairo_boilerplate_test_meta_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
     { "test-meta", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
       CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_meta_create_surface,
+      _cairo_boilerplate_test_meta_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
     { "test-paginated", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
       CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_paginated_create_surface,
+      _cairo_boilerplate_test_paginated_create_surface, NULL,
       NULL,
       _cairo_boilerplate_test_paginated_get_image_surface,
       _cairo_boilerplate_test_paginated_surface_write_to_png,
       _cairo_boilerplate_test_paginated_cleanup },
     { "test-paginated", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
       CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_paginated_create_surface,
+      _cairo_boilerplate_test_paginated_create_surface, NULL,
       NULL,
       _cairo_boilerplate_test_paginated_get_image_surface,
       _cairo_boilerplate_test_paginated_surface_write_to_png,
@@ -317,13 +321,13 @@ static cairo_boilerplate_target_t targets[] =
 #ifdef CAIRO_HAS_GLITZ_SURFACE
 #if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
     { "glitz-glx", NULL, CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_glx_create_surface,
+      _cairo_boilerplate_glitz_glx_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_glitz_glx_cleanup },
     { "glitz-glx", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_glx_create_surface,
+      _cairo_boilerplate_glitz_glx_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -331,13 +335,13 @@ static cairo_boilerplate_target_t targets[] =
 #endif
 #if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
     { "glitz-agl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_agl_create_surface,
+      _cairo_boilerplate_glitz_agl_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_glitz_agl_cleanup },
     { "glitz-agl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_agl_create_surface,
+      _cairo_boilerplate_glitz_agl_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -345,13 +349,13 @@ static cairo_boilerplate_target_t targets[] =
 #endif
 #if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
     { "glitz-wgl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_wgl_create_surface,
+      _cairo_boilerplate_glitz_wgl_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_glitz_wgl_cleanup },
     { "glitz-wgl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_wgl_create_surface,
+      _cairo_boilerplate_glitz_wgl_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -360,13 +364,13 @@ static cairo_boilerplate_target_t targets[] =
 #endif /* CAIRO_HAS_GLITZ_SURFACE */
 #if CAIRO_HAS_QUARTZ_SURFACE
     { "quartz", NULL, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_quartz_create_surface,
+      _cairo_boilerplate_quartz_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_quartz_cleanup },
     { "quartz", NULL, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_quartz_create_surface,
+      _cairo_boilerplate_quartz_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -374,7 +378,7 @@ static cairo_boilerplate_target_t targets[] =
 #endif
 #if CAIRO_HAS_WIN32_SURFACE
     { "win32", NULL, CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_win32_create_surface,
+      _cairo_boilerplate_win32_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
@@ -382,21 +386,21 @@ static cairo_boilerplate_target_t targets[] =
      * ARGB images it just chains to the image backend
      */
     { "win32", NULL, CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_win32_create_surface,
+      _cairo_boilerplate_win32_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png },
 #if CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE
     { "win32-printing", ".ps", CAIRO_SURFACE_TYPE_WIN32_PRINTING,
       CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
-      _cairo_boilerplate_win32_printing_create_surface,
+      _cairo_boilerplate_win32_printing_create_surface, NULL,
       NULL,
       _cairo_boilerplate_win32_printing_get_image_surface,
       _cairo_boilerplate_win32_printing_surface_write_to_png,
       _cairo_boilerplate_win32_printing_cleanup,
       NULL, TRUE },
     { "win32-printing", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_win32_printing_create_surface,
+      _cairo_boilerplate_win32_printing_create_surface, NULL,
       NULL,
       _cairo_boilerplate_win32_printing_get_image_surface,
       _cairo_boilerplate_win32_printing_surface_write_to_png,
@@ -408,7 +412,7 @@ static cairo_boilerplate_target_t targets[] =
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
     { "xcb", NULL, CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_xcb_create_surface,
+      _cairo_boilerplate_xcb_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -419,14 +423,14 @@ static cairo_boilerplate_target_t targets[] =
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
     { "xlib", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_xlib_create_surface,
+      _cairo_boilerplate_xlib_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_xlib_cleanup,
       _cairo_boilerplate_xlib_synchronize},
     { "xlib", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_xlib_create_surface,
+      _cairo_boilerplate_xlib_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -437,7 +441,7 @@ static cairo_boilerplate_target_t targets[] =
     /* This is a fallback surface which uses xlib fallbacks instead of
      * the Render extension. */
     { "xlib-fallback", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_xlib_fallback_create_surface,
+      _cairo_boilerplate_xlib_fallback_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -448,6 +452,7 @@ static cairo_boilerplate_target_t targets[] =
     { "ps2", ".ps", CAIRO_SURFACE_TYPE_PS,
       CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
       _cairo_boilerplate_ps2_create_surface,
+      _cairo_boilerplate_ps_force_fallbacks,
       _cairo_boilerplate_ps_finish_surface,
       _cairo_boilerplate_ps_get_image_surface,
       _cairo_boilerplate_ps_surface_write_to_png,
@@ -455,6 +460,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "ps2", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
       _cairo_boilerplate_ps2_create_surface,
+      _cairo_boilerplate_ps_force_fallbacks,
       _cairo_boilerplate_ps_finish_surface,
       _cairo_boilerplate_ps_get_image_surface,
       _cairo_boilerplate_ps_surface_write_to_png,
@@ -463,6 +469,7 @@ static cairo_boilerplate_target_t targets[] =
     { "ps3", ".ps", CAIRO_SURFACE_TYPE_PS,
       CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
       _cairo_boilerplate_ps3_create_surface,
+      _cairo_boilerplate_ps_force_fallbacks,
       _cairo_boilerplate_ps_finish_surface,
       _cairo_boilerplate_ps_get_image_surface,
       _cairo_boilerplate_ps_surface_write_to_png,
@@ -470,6 +477,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "ps3", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
       _cairo_boilerplate_ps3_create_surface,
+      _cairo_boilerplate_ps_force_fallbacks,
       _cairo_boilerplate_ps_finish_surface,
       _cairo_boilerplate_ps_get_image_surface,
       _cairo_boilerplate_ps_surface_write_to_png,
@@ -480,6 +488,7 @@ static cairo_boilerplate_target_t targets[] =
     { "pdf", ".pdf", CAIRO_SURFACE_TYPE_PDF,
       CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
       _cairo_boilerplate_pdf_create_surface,
+      _cairo_boilerplate_pdf_force_fallbacks,
       _cairo_boilerplate_pdf_finish_surface,
       _cairo_boilerplate_pdf_get_image_surface,
       _cairo_boilerplate_pdf_surface_write_to_png,
@@ -487,6 +496,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "pdf", ".pdf", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
       _cairo_boilerplate_pdf_create_surface,
+      _cairo_boilerplate_pdf_force_fallbacks,
       _cairo_boilerplate_pdf_finish_surface,
       _cairo_boilerplate_pdf_get_image_surface,
       _cairo_boilerplate_pdf_surface_write_to_png,
@@ -501,6 +511,7 @@ static cairo_boilerplate_target_t targets[] =
      * For now just set the svg error tolerance to 1. */
     { "svg11", ".svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
       _cairo_boilerplate_svg11_create_surface,
+      _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
       _cairo_boilerplate_svg_get_image_surface,
       _cairo_boilerplate_svg_surface_write_to_png,
@@ -508,6 +519,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "svg11", ".svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
       _cairo_boilerplate_svg11_create_surface,
+      _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
       _cairo_boilerplate_svg_get_image_surface,
       _cairo_boilerplate_svg_surface_write_to_png,
@@ -515,6 +527,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "svg12", ".svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
       _cairo_boilerplate_svg12_create_surface,
+      _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
       _cairo_boilerplate_svg_get_image_surface,
       _cairo_boilerplate_svg_surface_write_to_png,
@@ -522,6 +535,7 @@ static cairo_boilerplate_target_t targets[] =
       NULL, TRUE },
     { "svg12", ".svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
       _cairo_boilerplate_svg12_create_surface,
+      _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
       _cairo_boilerplate_svg_get_image_surface,
       _cairo_boilerplate_svg_surface_write_to_png,
@@ -533,19 +547,19 @@ static cairo_boilerplate_target_t targets[] =
      * is related to the fact that it doesn't use premultiplied alpha...
      * Just ignore the small difference. */
     { "beos", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_beos_create_surface,
+      _cairo_boilerplate_beos_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_beos_cleanup},
     { "beos-bitmap", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_beos_create_surface_for_bitmap,
+      _cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_beos_cleanup_bitmap},
     { "beos-bitmap", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_beos_create_surface_for_bitmap,
+      _cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -555,13 +569,13 @@ static cairo_boilerplate_target_t targets[] =
 
 #if CAIRO_HAS_DIRECTFB_SURFACE
     { "directfb", NULL, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_directfb_create_surface,
+      _cairo_boilerplate_directfb_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
       _cairo_boilerplate_directfb_cleanup},
     { "directfb-bitmap", NULL, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_directfb_create_surface,
+      _cairo_boilerplate_directfb_create_surface, NULL,
       NULL,
       _cairo_boilerplate_get_image_surface,
       cairo_surface_write_to_png,
@@ -863,7 +877,7 @@ cairo_boilerplate_convert_to_image (const char *filename, int page)
     cairo_surface_t *image;
 
   RETRY:
-    file = cairo_boilerplate_open_any2ppm (filename, 1, flags);
+    file = cairo_boilerplate_open_any2ppm (filename, page, flags);
     if (file == NULL)
 	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
 
diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h
index 7b6dbc3..11fb1c3 100644
--- a/boilerplate/cairo-boilerplate.h
+++ b/boilerplate/cairo-boilerplate.h
@@ -123,11 +123,16 @@ typedef cairo_surface_t *
 				       int                        id,
 				       void			**closure);
 
+typedef void
+(*cairo_boilerplate_force_fallbacks_t) (cairo_surface_t *surface,
+	                                unsigned int flags);
+
 typedef cairo_status_t
 (*cairo_boilerplate_finish_surface_t) (cairo_surface_t *surface);
 
 typedef cairo_surface_t *
 (*cairo_boilerplate_get_image_surface_t) (cairo_surface_t *surface,
+	                                  int page,
 					  int width,
 					  int height);
 
@@ -149,6 +154,7 @@ typedef struct _cairo_boilerplate_target
     cairo_content_t				 content;
     unsigned int				 error_tolerance;
     cairo_boilerplate_create_surface_t		 create_surface;
+    cairo_boilerplate_force_fallbacks_t		 force_fallbacks;
     cairo_boilerplate_finish_surface_t		 finish_surface;
     cairo_boilerplate_get_image_surface_t	 get_image_surface;
     cairo_boilerplate_write_to_png_t		 write_to_png;
@@ -165,6 +171,7 @@ cairo_boilerplate_free_targets (cairo_boilerplate_target_t **targets);
 
 cairo_surface_t *
 _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
+				      int page,
 				      int width,
 				      int height);
 cairo_surface_t *
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 8890865..3854f05 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -766,8 +766,6 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
     return status;
 }
 
-static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
-
 static cairo_int_status_t
 _cairo_svg_surface_analyze_operation (cairo_svg_surface_t   *surface,
 				      cairo_operator_t	     op,
@@ -775,8 +773,8 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t   *surface,
 {
     cairo_svg_document_t *document = surface->document;
 
-    if (cairo_svg_force_fallbacks)
-	return FALSE;
+    if (surface->force_fallbacks)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* SVG doesn't support extend reflect for image pattern */
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
diff --git a/test/Makefile.am b/test/Makefile.am
index 75a561f..4ad2a4e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -435,6 +435,12 @@ REFERENCE_IMAGES = \
 	extend-reflect-ps3-ref.png \
 	extend-repeat-ref.png	\
 	extend-repeat-similar-ref.png	\
+	fallback-resolution-ppi37.5-ref.png \
+	fallback-resolution-ppi72-ref.png \
+	fallback-resolution-ppi75-ref.png \
+	fallback-resolution-ppi150-ref.png \
+	fallback-resolution-ppi300-ref.png \
+	fallback-resolution-ppi600-ref.png \
 	fill-alpha-ref.png	\
 	fill-alpha-pattern-ref.png	\
 	fill-alpha-pattern-pdf-argb32-ref.png	\
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 36d88de..0e076c6 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -252,12 +252,12 @@ _xunlink (const cairo_test_context_t *ctx, const char *pathname)
     }
 }
 
-static char *
-cairo_ref_name_for_test_target_format (const cairo_test_context_t *ctx,
-	                               const char *base_name,
-	                               const char *test_name,
-				       const char *target_name,
-				       const char *format)
+char *
+cairo_test_reference_image_filename (const cairo_test_context_t *ctx,
+	                             const char *base_name,
+				     const char *test_name,
+				     const char *target_name,
+				     const char *format)
 {
     char *ref_name = NULL;
 
@@ -397,7 +397,7 @@ _cairo_test_flatten_reference_image (cairo_test_context_t *ctx,
     return surface;
 }
 
-static cairo_surface_t *
+cairo_surface_t *
 cairo_test_get_reference_image (cairo_test_context_t *ctx,
 				const char *filename,
 				cairo_bool_t flatten)
@@ -563,11 +563,11 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
       free (thread_str);
 
 
-    ref_name = cairo_ref_name_for_test_target_format (ctx,
-						      base_name,
-						      ctx->test->name,
-						      target->name,
-						      format);
+    ref_name = cairo_test_reference_image_filename (ctx,
+						    base_name,
+						    ctx->test->name,
+						    target->name,
+						    format);
     xasprintf (&png_name,  "%s%s", base_name, CAIRO_TEST_PNG_SUFFIX);
     xasprintf (&diff_name, "%s%s", base_name, CAIRO_TEST_DIFF_SUFFIX);
 
@@ -709,9 +709,9 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 
 	    /* we may be running this test to generate reference images */
 	    _xunlink (ctx, png_name);
-	    test_image = target->get_image_surface (surface,
-		    ctx->test->width,
-		    ctx->test->height);
+	    test_image = target->get_image_surface (surface, 0,
+		                                    ctx->test->width,
+						    ctx->test->height);
 	    diff_status = cairo_surface_write_to_png (test_image, png_name);
 	    if (diff_status) {
 		cairo_test_log (ctx,
@@ -755,9 +755,9 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	    }
 	}
 
-	test_image = target->get_image_surface (surface,
-					       ctx->test->width,
-					       ctx->test->height);
+	test_image = target->get_image_surface (surface, 0,
+					        ctx->test->width,
+						ctx->test->height);
 	if (cairo_surface_status (test_image)) {
 	    cairo_test_log (ctx, "Error: Failed to extract image: %s\n",
 			    cairo_status_to_string (cairo_surface_status (test_image)));
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 5dd61f8..69b3d85 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -184,6 +184,18 @@ cairo_bool_t
 cairo_test_is_target_enabled (const cairo_test_context_t *ctx,
 	                      const char *target);
 
+char *
+cairo_test_reference_image_filename (const cairo_test_context_t *ctx,
+	                             const char *base_name,
+				     const char *test_name,
+				     const char *target_name,
+				     const char *format);
+
+cairo_surface_t *
+cairo_test_get_reference_image (cairo_test_context_t *ctx,
+				const char *filename,
+				cairo_bool_t flatten);
+
 CAIRO_END_DECLS
 
 #endif
diff --git a/test/fallback-resolution-ppi150-ref.png b/test/fallback-resolution-ppi150-ref.png
new file mode 100644
index 0000000..4d3723e
Binary files /dev/null and b/test/fallback-resolution-ppi150-ref.png differ
diff --git a/test/fallback-resolution-ppi300-ref.png b/test/fallback-resolution-ppi300-ref.png
new file mode 100644
index 0000000..54de6cc
Binary files /dev/null and b/test/fallback-resolution-ppi300-ref.png differ
diff --git a/test/fallback-resolution-ppi37.5-ref.png b/test/fallback-resolution-ppi37.5-ref.png
new file mode 100644
index 0000000..3b0cc16
Binary files /dev/null and b/test/fallback-resolution-ppi37.5-ref.png differ
diff --git a/test/fallback-resolution-ppi600-ref.png b/test/fallback-resolution-ppi600-ref.png
new file mode 100644
index 0000000..291a453
Binary files /dev/null and b/test/fallback-resolution-ppi600-ref.png differ
diff --git a/test/fallback-resolution-ppi72-ref.png b/test/fallback-resolution-ppi72-ref.png
new file mode 100644
index 0000000..5d72f87
Binary files /dev/null and b/test/fallback-resolution-ppi72-ref.png differ
diff --git a/test/fallback-resolution-ppi75-ref.png b/test/fallback-resolution-ppi75-ref.png
new file mode 100644
index 0000000..7d68781
Binary files /dev/null and b/test/fallback-resolution-ppi75-ref.png differ
diff --git a/test/fallback-resolution.c b/test/fallback-resolution.c
index 60ff78b..6f814a8 100644
--- a/test/fallback-resolution.c
+++ b/test/fallback-resolution.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
  *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without
@@ -21,27 +22,24 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * Author: Carl D. Worth <cworth at cworth.org>
+ *         Chris Wilson <chris at chris-wilson.co.uk>
  */
 
-#include <stdio.h>
-#include <cairo.h>
-
-#if CAIRO_HAS_PDF_SURFACE
-#include <cairo-pdf.h>
-#include <cairo-boilerplate-pdf.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
 #endif
 
-#if CAIRO_HAS_PS_SURFACE
-#include <cairo-ps.h>
-#include <cairo-boilerplate-ps.h>
-#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <cairo.h>
 
-#if CAIRO_HAS_SVG_SURFACE
-#include <cairo-svg.h>
-#include <cairo-boilerplate-svg.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#include <errno.h>
 #endif
 
 #include "cairo-test.h"
+#include "buffer-diff.h"
 
 /* This test exists to test cairo_surface_set_fallback_resolution
  *
@@ -57,10 +55,15 @@
 #define INCHES_TO_POINTS(in) ((in) * 72.0)
 #define SIZE INCHES_TO_POINTS(1)
 
+/* cairo_set_tolerance() is not respected by the PS/PDF backends currently */
+#define SET_TOLERANCE 0
+
+#define GENERATE_REFERENCE 0
+
 static void
-draw_with_ppi (cairo_t *cr, double width, double height, double ppi)
+draw (cairo_t *cr, double width, double height)
 {
-    char message[80];
+    const char *text = "cairo";
     cairo_text_extents_t extents;
 
     cairo_save (cr);
@@ -78,142 +81,344 @@ draw_with_ppi (cairo_t *cr, double width, double height, double ppi)
 	       0, 2.0 * M_PI);
     cairo_fill (cr);
 
-    sprintf (message, "Fallback PPI: %g", ppi);
     cairo_set_source_rgb (cr, 1, 1, 1); /* white */
-    cairo_set_font_size (cr, .1 * SIZE / 2.0);
-    cairo_text_extents (cr, message, &extents);
+    cairo_set_font_size (cr, .25 * SIZE / 2.0);
+    cairo_text_extents (cr, text, &extents);
     cairo_move_to (cr, (SIZE-extents.width)/2.0-extents.x_bearing,
 		       (SIZE-extents.height)/2.0-extents.y_bearing);
-    cairo_show_text (cr, message);
+    cairo_show_text (cr, text);
 
     cairo_restore (cr);
 }
 
-typedef enum {
-    PDF, PS, SVG, NUM_BACKENDS
-} backend_t;
-static const char *backend_filename[NUM_BACKENDS] = {
-    "fallback-resolution.pdf",
-    "fallback-resolution.ps",
-    "fallback-resolution.svg"
-};
+static void
+_xunlink (const cairo_test_context_t *ctx, const char *pathname)
+{
+    if (unlink (pathname) < 0 && errno != ENOENT) {
+	cairo_test_log (ctx, "Error: Cannot remove %s: %s\n",
+			pathname, strerror (errno));
+	exit (1);
+    }
+}
+
+static cairo_bool_t
+check_result (cairo_test_context_t *ctx,
+	      const cairo_boilerplate_target_t *target,
+	      const char *test_name,
+	      const char *base_name,
+	      cairo_surface_t *surface)
+{
+    const char *format;
+    char *ref_name;
+    char *png_name;
+    char *diff_name;
+    cairo_surface_t *test_image, *ref_image, *diff_image;
+    buffer_diff_result_t result;
+    cairo_status_t status;
+    cairo_bool_t ret;
+
+    /* XXX log target, OUTPUT, REFERENCE, DIFFERENCE for index.html */
+
+    if (target->finish_surface != NULL) {
+	status = target->finish_surface (surface);
+	if (status) {
+	    cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
+		    cairo_status_to_string (status));
+	    cairo_surface_destroy (surface);
+	    return FALSE;
+	}
+    }
+
+    xasprintf (&png_name,  "%s-out.png", base_name);
+    xasprintf (&diff_name, "%s-diff.png", base_name);
+
+    test_image = target->get_image_surface (surface, 0, SIZE, SIZE);
+    if (cairo_surface_status (test_image)) {
+	cairo_test_log (ctx, "Error: Failed to extract page: %s\n",
+		        cairo_status_to_string (cairo_surface_status (test_image)));
+	cairo_surface_destroy (test_image);
+	free (png_name);
+	free (diff_name);
+	return FALSE;
+    }
+
+    _xunlink (ctx, png_name);
+    status = cairo_surface_write_to_png (test_image, png_name);
+    if (status) {
+	cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
+		cairo_status_to_string (status));
+	cairo_surface_destroy (test_image);
+	free (png_name);
+	free (diff_name);
+	return FALSE;
+    }
+
+    format = cairo_boilerplate_content_name (target->content);
+    ref_name = cairo_test_reference_image_filename (ctx,
+	                                            base_name,
+						    test_name,
+						    target->name,
+						    format);
+    if (ref_name == NULL) {
+	cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
+		        base_name);
+	cairo_surface_destroy (test_image);
+	free (png_name);
+	free (diff_name);
+	return FALSE;
+    }
+
+
+    ref_image = cairo_test_get_reference_image (ctx, ref_name,
+	    target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
+    if (cairo_surface_status (ref_image)) {
+	cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
+		        ref_name,
+		cairo_status_to_string (cairo_surface_status (ref_image)));
+	cairo_surface_destroy (ref_image);
+	cairo_surface_destroy (test_image);
+	free (png_name);
+	free (diff_name);
+	return FALSE;
+    }
+
+    diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+	    SIZE, SIZE);
+
+    ret = TRUE;
+    status = image_diff (ctx,
+	    test_image, ref_image, diff_image,
+	    &result);
+    _xunlink (ctx, diff_name);
+    if (status) {
+	cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
+			cairo_status_to_string (status));
+	ret = TRUE;
+    } else if (result.pixels_changed &&
+	       result.max_diff > target->error_tolerance)
+    {
+	ret = FALSE;
+
+	status = cairo_surface_write_to_png (diff_image, diff_name);
+	if (status) {
+	    cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
+		    cairo_status_to_string (status));
+	}
+    }
+
+    cairo_surface_destroy (test_image);
+    cairo_surface_destroy (diff_image);
+    free (png_name);
+    free (diff_name);
+
+    return ret;
+}
+
+#if GENERATE_REFERENCE
+static void
+generate_reference (double ppi, const char *filename)
+{
+    cairo_surface_t *surface, *target;
+    cairo_t *cr;
+    cairo_status_t status;
+
+    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+	                                  SIZE*ppi/72, SIZE*ppi/72);
+    cr = cairo_create (surface);
+    cairo_surface_destroy (surface);
+
+#if SET_TOLERANCE
+    cairo_set_tolerance (cr, 3.0);
+#endif
+
+    cairo_save (cr); {
+	cairo_set_source_rgb (cr, 1, 1, 1);
+	cairo_paint (cr);
+    } cairo_restore (cr);
+
+    cairo_scale (cr, ppi/72., ppi/72.);
+    draw (cr, SIZE, SIZE);
+
+    surface = cairo_surface_reference (cairo_get_target (cr));
+    cairo_destroy (cr);
+
+    target = cairo_image_surface_create (CAIRO_FORMAT_RGB24, SIZE, SIZE);
+    cr = cairo_create (target);
+    cairo_scale (cr, 72./ppi, 72./ppi);
+    cairo_set_source_surface (cr, surface, 0, 0);
+    cairo_paint (cr);
+
+    status = cairo_surface_write_to_png (cairo_get_target (cr), filename);
+    cairo_destroy (cr);
+
+    if (status) {
+	fprintf (stderr, "Failed to generate reference image '%s': %s\n",
+		 filename, cairo_status_to_string (status));
+	exit (1);
+    }
+}
+#endif
 
 int
 main (void)
 {
     cairo_test_context_t ctx;
     cairo_t *cr;
-    cairo_status_t status;
     cairo_test_status_t ret = CAIRO_TEST_UNTESTED;
-    double ppi[] = { 600., 300., 150., 75., 37.5 };
-    backend_t backend;
+    double ppi[] = { 600., 300., 150., 75., 72, 37.5 };
+    unsigned int i;
     int page, num_pages;
 
     num_pages = sizeof (ppi) / sizeof (ppi[0]);
 
     cairo_test_init (&ctx, "fallback-resolution");
 
-    for (backend=0; backend < NUM_BACKENDS; backend++) {
-	cairo_surface_t *surface = NULL;
-
-	/* Create backend-specific surface and force image fallbacks. */
-	switch (backend) {
-	case PDF:
-#if CAIRO_HAS_PDF_SURFACE
-	    if (cairo_test_is_target_enabled (&ctx, "pdf")) {
-		surface = cairo_pdf_surface_create (backend_filename[backend],
-						    SIZE, SIZE);
-		cairo_boilerplate_pdf_surface_force_fallbacks (surface);
-	    }
-#endif
-	    break;
-	case PS:
-#if CAIRO_HAS_PS_SURFACE
-	    if (cairo_test_is_target_enabled (&ctx, "ps2") ||
-		cairo_test_is_target_enabled (&ctx, "ps3"))
-	    {
-		surface = cairo_ps_surface_create (backend_filename[backend],
-						   SIZE, SIZE);
-		cairo_boilerplate_ps_surface_force_fallbacks (surface);
-	    }
-#endif
-	    break;
-	case SVG:
-#if CAIRO_HAS_SVG_SURFACE
-	    if (cairo_test_is_target_enabled (&ctx, "svg11") ||
-	        cairo_test_is_target_enabled (&ctx, "svg12"))
-	    {
-		surface = cairo_svg_surface_create (backend_filename[backend],
-						    SIZE, SIZE);
-		cairo_boilerplate_svg_surface_force_fallbacks (surface);
-		cairo_svg_surface_restrict_to_version (surface, CAIRO_SVG_VERSION_1_2);
-	    }
+#if GENERATE_REFERENCE
+    for (page = 0; page < num_pages; page++) {
+	char *ref_name;
+	xasprintf (&ref_name, "fallback-resolution-ppi%g-ref.png", ppi[page]);
+	generate_reference (ppi[page], ref_name);
+	free (ref_name);
+    }
 #endif
-	    break;
 
-	case NUM_BACKENDS:
-	    break;
-	}
+    for (i = 0; i < ctx.num_targets; i++) {
+	const cairo_boilerplate_target_t *target = ctx.targets_to_test[i];
+	cairo_surface_t *surface = NULL;
+	char *base_name;
+	void *closure;
+	const char *format;
+	cairo_status_t status;
 
-	if (surface == NULL)
+	if (! target->is_vector)
 	    continue;
 
+	format = cairo_boilerplate_content_name (target->content);
+	xasprintf (&base_name, "fallback-resolution-%s-%s",
+		   target->name,
+		   format);
+
+	surface = (target->create_surface) (base_name,
+		                            target->content,
+					    SIZE, SIZE,
+					    SIZE, SIZE,
+					    CAIRO_BOILERPLATE_MODE_TEST,
+					    0,
+					    &closure);
+
+	if (surface == NULL) {
+	    free (base_name);
+	    continue;
+	}
+
 	if (ret == CAIRO_TEST_UNTESTED)
 	    ret = CAIRO_TEST_SUCCESS;
 
-	cr = cairo_create (surface);
-	cairo_set_tolerance (cr, 3.0);
+	cairo_surface_destroy (surface);
+	if (target->cleanup)
+	    target->cleanup (closure);
+	free (base_name);
+
+	/* we need to recreate the surface for each resolution as we include
+	 * SVG in testing which does not support the paginated interface.
+	 */
+	for (page = 0; page < num_pages; page++) {
+	    char *test_name;
+	    cairo_bool_t pass;
+
+	    xasprintf (&test_name, "fallback-resolution-ppi%g",
+		       ppi[page]);
+	    xasprintf (&base_name, "%s-%s-%s",
+		       test_name,
+		       target->name,
+		       format);
+
+	    surface = (target->create_surface) (base_name,
+						target->content,
+						SIZE + 25, SIZE + 25,
+						SIZE + 25, SIZE + 25,
+						CAIRO_BOILERPLATE_MODE_TEST,
+						0,
+						&closure);
+	    if (surface == NULL || cairo_surface_status (surface)) {
+		cairo_test_log (&ctx, "Failed to generate surface: %s-%s\n",
+		    target->name,
+		    format);
+		free (base_name);
+		ret = CAIRO_TEST_FAILURE;
+		continue;
+	    }
+
+	    cairo_test_log (&ctx, "Testing fallback-resolution %g with %s target\n", ppi[page], target->name);
+	    printf ("%s:\t", base_name);
+	    fflush (stdout);
+
+	    if (target->force_fallbacks != NULL)
+		target->force_fallbacks (surface, ~0U);
+	    cr = cairo_create (surface);
+#if SET_TOLERANCE
+	    cairo_set_tolerance (cr, 3.0);
+#endif
+
+	    cairo_surface_set_device_offset (surface, 25, 25);
+	    cairo_surface_set_fallback_resolution (surface,
+		                                   ppi[page], ppi[page]);
 
-	for (page = 0; page < num_pages; page++)
-	{
-	    cairo_surface_set_fallback_resolution (surface, ppi[page], ppi[page]);
+	    cairo_save (cr); {
+		cairo_set_source_rgb (cr, 1, 1, 1);
+		cairo_paint (cr);
+	    } cairo_restore (cr);
 
 	    /* First draw the top half in a conventional way. */
-	    cairo_save (cr);
-	    {
+	    cairo_save (cr); {
 		cairo_rectangle (cr, 0, 0, SIZE, SIZE / 2.0);
 		cairo_clip (cr);
 
-		draw_with_ppi (cr, SIZE, SIZE, ppi[page]);
-	    }
-	    cairo_restore (cr);
+		draw (cr, SIZE, SIZE);
+	    } cairo_restore (cr);
 
 	    /* Then draw the bottom half in a separate group,
 	     * (exposing a bug in 1.6.4 with the group not being
 	     * rendered with the correct fallback resolution). */
-	    cairo_save (cr);
-	    {
+	    cairo_save (cr); {
 		cairo_rectangle (cr, 0, SIZE / 2.0, SIZE, SIZE / 2.0);
 		cairo_clip (cr);
 
-		cairo_push_group (cr);
-		{
-		    draw_with_ppi (cr, SIZE, SIZE, ppi[page]);
-		}
-		cairo_pop_group_to_source (cr);
+		cairo_push_group (cr); {
+		    draw (cr, SIZE, SIZE);
+		} cairo_pop_group_to_source (cr);
 
 		cairo_paint (cr);
+	    } cairo_restore (cr);
+
+	    status = cairo_status (cr);
+	    cairo_destroy (cr);
+
+	    pass = FALSE;
+	    if (status) {
+		cairo_test_log (&ctx, "Error: Failed to create target surface: %s\n",
+			        cairo_status_to_string (status));
+		ret = CAIRO_TEST_FAILURE;
+	    } else {
+		/* extract the image and compare it to our reference */
+		if (! check_result (&ctx, target, test_name, base_name, surface))
+		    ret = CAIRO_TEST_FAILURE;
+		else
+		    pass = TRUE;
 	    }
-	    cairo_restore (cr);
-
-	    cairo_show_page (cr);
-	}
+	    cairo_surface_destroy (surface);
+	    if (target->cleanup)
+		target->cleanup (closure);
 
-	status = cairo_status (cr);
+	    free (base_name);
 
-	cairo_destroy (cr);
-	cairo_surface_destroy (surface);
-
-	if (status) {
-	    cairo_test_log (&ctx, "Failed to create pdf surface for file %s: %s\n",
-			    backend_filename[backend],
-			    cairo_status_to_string (status));
-	    ret = CAIRO_TEST_FAILURE;
-	    break;
+	    if (pass) {
+		printf ("PASS\n");
+	    } else {
+		printf ("FAIL\n");
+	    }
+	    fflush (stdout);
 	}
-
-	printf ("fallback-resolution: Please check %s to ensure it looks correct.\n",
-		backend_filename[backend]);
     }
 
     cairo_test_fini (&ctx);


More information about the cairo-commit mailing list