[cairo-commit] 12 commits - src/cairo-analysis-surface.c src/cairo-directfb-surface.c src/cairo-gstate.c src/cairo.h src/cairoint.h src/cairo-jpeg-info.c src/cairo-jpeg-info-private.h src/cairo-meta-surface.c src/cairo-meta-surface-private.h src/cairo-paginated-surface.c src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-ps-surface.c src/cairo-ps-surface-private.h src/cairo-quartz-surface.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-surface-private.h src/cairo-svg-surface.c src/cairo-type1-subset.c src/cairo-type3-glyph-surface.c src/cairo-win32-printing-surface.c src/cairo-win32-surface.c src/cairo-xlib-surface.c src/Makefile.sources src/test-meta-surface.c src/test-paginated-surface.c test/cairo-test.c test/README

Adrian Johnson ajohnson at kemper.freedesktop.org
Sun Nov 2 01:43:50 PST 2008


 src/Makefile.sources               |    2 
 src/cairo-analysis-surface.c       |   61 ++++++++----
 src/cairo-directfb-surface.c       |    3 
 src/cairo-gstate.c                 |   12 +-
 src/cairo-jpeg-info-private.h      |   54 +++++++++++
 src/cairo-jpeg-info.c              |  142 +++++++++++++++++++++++++++++
 src/cairo-meta-surface-private.h   |    1 
 src/cairo-meta-surface.c           |   48 +++++++--
 src/cairo-paginated-surface.c      |   27 +++--
 src/cairo-pdf-surface-private.h    |    1 
 src/cairo-pdf-surface.c            |  181 ++++++++++++++++++++++++++++++++-----
 src/cairo-ps-surface-private.h     |    1 
 src/cairo-ps-surface.c             |  119 +++++++++++++++++++-----
 src/cairo-quartz-surface.c         |   15 ++-
 src/cairo-surface-fallback.c       |   15 +++
 src/cairo-surface-private.h        |    4 
 src/cairo-surface.c                |  112 +++++++++++++++++++---
 src/cairo-svg-surface.c            |   24 +++-
 src/cairo-type1-subset.c           |   12 --
 src/cairo-type3-glyph-surface.c    |   17 ++-
 src/cairo-win32-printing-surface.c |   12 +-
 src/cairo-win32-surface.c          |    3 
 src/cairo-xlib-surface.c           |    8 +
 src/cairo.h                        |   15 +++
 src/cairoint.h                     |   39 +++++--
 src/test-meta-surface.c            |   25 +++--
 src/test-paginated-surface.c       |   25 +++--
 test/README                        |    2 
 test/cairo-test.c                  |    2 
 29 files changed, 799 insertions(+), 183 deletions(-)

New commits:
commit 1685bbee1bf1ebc015ada94f77756d8d10c7818d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 2 19:50:59 2008 +1030

    test/README: fix typo

diff --git a/test/README b/test/README
index cb8a80e..c039ebb 100644
--- a/test/README
+++ b/test/README
@@ -125,7 +125,7 @@ Here are some of the relevant details:
     X server that uses only software for all rendering. One such X
     server is Xvfb which can be started like this:
 
-	Xfvb -screen 0 1280x1024x24 -ac -nolisten tcp :2
+	Xvfb -screen 0 1280x1024x24 -ac -nolisten tcp :2
 
     after which the test suite can be run against it like so:
 
commit 540ac11113015f0fd6856d016cb38fec5282b6ce
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 2 11:42:33 2008 +1030

    type1-subset: return unsupported on FT errors
    
    and let type1-fallback handle it. This fixes the bug reported by
    Peter Weilbacher in
    http://lists.cairographics.org/archives/cairo/2008-October/015569.html

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index ddc4ce7..bbff33d 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -553,18 +553,14 @@ cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *f
 	error = FT_Load_Glyph (font->face, i,
 			       FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |
 			       FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
-	if (error != 0) {
-	    printf ("could not load glyph %d\n", i);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
+	if (error != 0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	font->glyphs[i].width = font->face->glyph->metrics.horiAdvance;
 
 	error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
-	if (error != 0) {
-	    printf ("could not get glyph name for glyph %d\n", i);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
+	if (error != 0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	font->glyphs[i].name = strdup (buffer);
 	if (font->glyphs[i].name == NULL)
commit 3707178fa48e23b85c5640f3cee72e19f49c700b
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Sep 8 10:26:58 2008 +0930

    PDF: Implement JPEG image embedding

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 082b6af..6a0e93b 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -64,6 +64,7 @@ cairo_private = \
 	cairo-freelist-private.h \
 	cairo-gstate-private.h \
 	cairo-hash-private.h \
+	cairo-jpeg-info-private.h \
 	cairo-malloc-private.h \
 	cairo-meta-surface-private.h \
 	cairo-mutex-impl-private.h \
@@ -109,6 +110,7 @@ cairo_sources = \
 	cairo-hash.c \
 	cairo-hull.c \
 	cairo-image-surface.c \
+	cairo-jpeg-info.c \
 	cairo-lzw.c \
 	cairo-matrix.c \
 	cairo-meta-surface.c \
diff --git a/src/cairo-jpeg-info-private.h b/src/cairo-jpeg-info-private.h
new file mode 100644
index 0000000..1a376c9
--- /dev/null
+++ b/src/cairo-jpeg-info-private.h
@@ -0,0 +1,54 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#ifndef CAIRO_JPEG_INFO_PRIVATE_H
+#define CAIRO_JPEG_INFO_PRIVATE_H
+
+#include "cairoint.h"
+
+typedef struct _cairo_jpeg_info {
+    int		 width;
+    int		 height;
+    int		 num_components;
+    int		 bits_per_component;
+} cairo_jpeg_info_t;
+
+cairo_private cairo_int_status_t
+_cairo_jpeg_get_info (unsigned char	*data,
+		      long 	  	 length,
+		      cairo_jpeg_info_t *info);
+
+
+#endif /* CAIRO_JPEG_INFO_PRIVATE_H */
diff --git a/src/cairo-jpeg-info.c b/src/cairo-jpeg-info.c
new file mode 100644
index 0000000..75dc0bf
--- /dev/null
+++ b/src/cairo-jpeg-info.c
@@ -0,0 +1,142 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-jpeg-info-private.h"
+
+/* Markers with no parameters. All other markers are followed by a two
+ * byte length of the parameters. */
+#define TEM       0x01
+#define RST_begin 0xd0
+#define RST_end   0xd7
+#define SOI       0xd8
+#define EOI       0xd9
+
+/* Start of frame markers. */
+#define SOF0  0xc0
+#define SOF1  0xc1
+#define SOF2  0xc2
+#define SOF3  0xc3
+#define SOF5  0xc5
+#define SOF6  0xc6
+#define SOF7  0xc7
+#define SOF9  0xc9
+#define SOF10 0xca
+#define SOF11 0xcb
+#define SOF13 0xcd
+#define SOF14 0xce
+#define SOF15 0xcf
+
+static unsigned char *
+_skip_segment (unsigned char *p)
+{
+    int len;
+
+    p++;
+    len = p[0] << 8;
+    len |= p[1];
+
+    return p + len;
+}
+
+static void
+_extract_info (cairo_jpeg_info_t *info, unsigned char *p)
+{
+    info->width = (p[6] << 8) + p[7];
+    info->height = (p[4] << 8) + p[5];;
+    info->num_components = p[8];
+    info->bits_per_component = p[3];
+}
+
+cairo_int_status_t
+_cairo_jpeg_get_info (unsigned char	*data,
+		      long 	  	 length,
+		      cairo_jpeg_info_t *info)
+{
+    unsigned char *p = data;
+
+    while (p + 1 < data + length) {
+	if (*p != 0xff)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	p++;
+
+	switch (*p) {
+	    /* skip fill bytes */
+	case 0xff:
+	    p++;
+	    break;
+
+	case TEM:
+	case SOI:
+	case EOI:
+	    p++;
+	    break;
+
+	case SOF0:
+	case SOF1:
+	case SOF2:
+	case SOF3:
+	case SOF5:
+	case SOF6:
+	case SOF7:
+	case SOF9:
+	case SOF10:
+	case SOF11:
+	case SOF13:
+	case SOF14:
+	case SOF15:
+	    /* Start of frame found. Extract the image parameters. */
+	    if (p + 8 > data + length)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    _extract_info (info, p);
+	    return CAIRO_STATUS_SUCCESS;
+
+	default:
+	    if (*p >= RST_begin && *p <= RST_end) {
+		p++;
+		break;
+	    }
+
+	    if (p + 2 > data + length)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    p = _skip_segment (p);
+	    break;
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 27fcbe0..827c9ea 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -50,6 +50,7 @@
 #include "cairo-paginated-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-type3-glyph-surface-private.h"
+#include "cairo-jpeg-info-private.h"
 
 #include <time.h>
 #include <zlib.h>
@@ -1550,6 +1551,55 @@ CLEANUP:
     return status;
 }
 
+static cairo_int_status_t
+_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
+				    cairo_surface_t 	  *source,
+				    cairo_pdf_resource_t  *res,
+				    int                   *width,
+				    int                   *height)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_jpeg_info_t info;
+
+    if (source->jpeg_data == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_jpeg_get_info (source->jpeg_data,
+				   source->jpeg_data_length,
+				   &info);
+    if (status)
+	return status;
+
+    if (info.num_components != 1 && info.num_components != 3)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_pdf_surface_open_stream (surface,
+					     NULL,
+					     FALSE,
+					     "   /Type /XObject\n"
+					     "   /Subtype /Image\n"
+					     "   /Width %d\n"
+					     "   /Height %d\n"
+					     "   /ColorSpace %s\n"
+					     "   /BitsPerComponent %d\n"
+					     "   /Filter /DCTDecode\n",
+					     info.width,
+					     info.height,
+					     info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB",
+					     info.bits_per_component);
+
+    *res = surface->pdf_stream.self;
+    _cairo_output_stream_write (surface->output,
+				source->jpeg_data,
+				source->jpeg_data_length);
+    status = _cairo_pdf_surface_close_stream (surface);
+
+    *width = info.width;
+    *height = info.height;
+
+    return status;
+}
+
 static cairo_status_t
 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
 				       cairo_pdf_pattern_t     *pdf_pattern,
@@ -1567,6 +1617,11 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
     int x = 0;
     int y = 0;
 
+    status = _cairo_pdf_surface_emit_jpeg_image (surface, pattern->surface,
+						 resource, width, height);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
 	goto BAIL;
commit 3c684347f49a581bfba35202ec61a5f6334acd4a
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Sep 7 20:46:20 2008 +0930

    Add cairo_surface_set_mime_data()
    
    Currently only handles jpeg data.

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index a5dcd57..6266117 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1075,6 +1075,21 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
     snapshot->device_transform = surface->device_transform;
     snapshot->device_transform_inverse = surface->device_transform_inverse;
 
+    if (surface->jpeg_destroy &&
+	surface->jpeg_data != NULL &&
+	surface->jpeg_data_length != 0)
+    {
+	snapshot->jpeg_data = malloc (surface->jpeg_data_length);
+	if (snapshot->jpeg_data == NULL) {
+	    cairo_surface_destroy (snapshot);
+	    return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+	}
+
+	memcpy (snapshot->jpeg_data, surface->jpeg_data, surface->jpeg_data_length);
+	snapshot->jpeg_data_length = surface->jpeg_data_length;
+	snapshot->jpeg_destroy = free;
+    }
+
     snapshot->is_snapshot = TRUE;
 
     return snapshot;
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index efd4365..1b5bb04 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -100,6 +100,10 @@ struct _cairo_surface {
      */
     cairo_bool_t has_font_options;
     cairo_font_options_t font_options;
+
+    unsigned char *jpeg_data;
+    unsigned int jpeg_data_length;
+    cairo_destroy_func_t jpeg_destroy;
 };
 
 #endif /* CAIRO_SURFACE_PRIVATE_H */
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 40b10e7..79366f2 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -220,6 +220,10 @@ _cairo_surface_init (cairo_surface_t			*surface,
     surface->is_snapshot = FALSE;
 
     surface->has_font_options = FALSE;
+
+    surface->jpeg_data = NULL;
+    surface->jpeg_data_length = 0;
+    surface->jpeg_destroy = NULL;
 }
 
 cairo_surface_t *
@@ -440,6 +444,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
 
     _cairo_user_data_array_fini (&surface->user_data);
 
+    if (surface->jpeg_data)
+	surface->jpeg_destroy (surface->jpeg_data);
+
     free (surface);
 }
 slim_hidden_def(cairo_surface_destroy);
@@ -590,6 +597,66 @@ cairo_surface_set_user_data (cairo_surface_t		 *surface,
 }
 
 /**
+ * cairo_surface_get_mime_data:
+ * @surface: a #cairo_surface_t
+ * @mime_type: the mime type of the image data
+ * @data: the image data to attached to the surface
+ * @length: the length of the image data
+ *
+ * Return mime data previously attached to @surface using the
+ * specified mime type.  If no data has been attached with the given
+ * mime type, @data is set NULL.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_surface_get_mime_data (cairo_surface_t		*surface,
+                             const char 		*mime_type,
+                             const unsigned char       **data,
+                             unsigned int		*length)
+{
+    if (strcmp (mime_type, CAIRO_MIME_TYPE_JPEG) == 0) {
+	*data = surface->jpeg_data;
+	*length = surface->jpeg_data_length;
+    } else {
+	*data = NULL;
+    }
+}
+
+/**
+ * cairo_surface_set_mime_data:
+ * @surface: a #cairo_surface_t
+ * @mime_type: the mime type of the image data
+ * @data: the image data to attach to the surface
+ * @length: the length of the image data
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * surface is destroyed or when new image data is attached using the
+ * same mime type.
+ *
+ * Attach an image in the format @mime_type to @surface. To remove
+ * the data from a surface, call this function with same mime type
+ * and %NULL for @data.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_surface_set_mime_data (cairo_surface_t		*surface,
+                             const char			*mime_type,
+                             const unsigned char	*data,
+                             unsigned int		 length,
+			     cairo_destroy_func_t	 destroy)
+{
+    if (strcmp (mime_type, CAIRO_MIME_TYPE_JPEG) == 0) {
+	if (surface->jpeg_data)
+	    surface->jpeg_destroy (surface->jpeg_data);
+
+	surface->jpeg_data = data;
+	surface->jpeg_data_length = length;
+	surface->jpeg_destroy = destroy;
+    }
+}
+
+/**
  * _cairo_surface_set_font_options:
  * @surface: a #cairo_surface_t
  * @options: a #cairo_font_options_t object that contains the
diff --git a/src/cairo.h b/src/cairo.h
index 97d9455..32005bb 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1947,6 +1947,21 @@ cairo_surface_set_user_data (cairo_surface_t		 *surface,
 			     void			 *user_data,
 			     cairo_destroy_func_t	 destroy);
 
+#define CAIRO_MIME_TYPE_JPEG "image/jpeg"
+
+cairo_public void
+cairo_surface_get_mime_data (cairo_surface_t		*surface,
+                             const char 		*mime_type,
+                             const unsigned char       **data,
+                             unsigned int		*length);
+
+cairo_public void
+cairo_surface_set_mime_data (cairo_surface_t		 *surface,
+                             const char			 *mime_type,
+                             const unsigned char         *data,
+                             unsigned int                 length,
+			     cairo_destroy_func_t	  destroy);
+
 cairo_public void
 cairo_surface_get_font_options (cairo_surface_t      *surface,
 				cairo_font_options_t *options);
commit a39a4f52ac4a057f579e881a9a929029bcc514d1
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 21:02:26 2008 +0930

    PS: meta-surface patterns with EXTEND_PAD are unsupported
    
    We have to use fallback images for this.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index ea8a2b7..e050ddb 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1571,8 +1571,12 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
-	if ( _cairo_surface_is_meta (surface_pattern->surface))
-	    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+	if ( _cairo_surface_is_meta (surface_pattern->surface)) {
+	    if (cairo_pattern_get_extend (pattern) == CAIRO_EXTEND_PAD)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	    else
+		return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+	}
     }
 
     if (op == CAIRO_OPERATOR_SOURCE)
commit 19ee13ca2b5b1e08a7fc965516be514d2fe40232
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 21:01:17 2008 +0930

    PS: Implement EXTEND_PAD for image patterns
    
    Images with EXTEND_PAD are painted into a new image the size of the
    operation extents. The new image is then embedded in the PS file with
    the pattern matrix adjusted to ensure the image origin is in the
    correct location.

diff --git a/src/cairo-ps-surface-private.h b/src/cairo-ps-surface-private.h
index e78833d..98d2750 100644
--- a/src/cairo-ps-surface-private.h
+++ b/src/cairo-ps-surface-private.h
@@ -68,6 +68,7 @@ typedef struct cairo_ps_surface {
     int bbox_x1, bbox_y1, bbox_x2, bbox_y2;
     cairo_matrix_t cairo_to_ps;
     cairo_image_surface_t *image;
+    cairo_image_surface_t *acquired_image;
     void *image_extra;
     cairo_bool_t use_string_datasource;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6242143..ea8a2b7 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -79,6 +79,10 @@
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 
+static void
+_cairo_ps_surface_release_surface (cairo_ps_surface_t      *surface,
+				   cairo_surface_pattern_t *pattern);
+
 static const cairo_ps_level_t _cairo_ps_levels[] =
 {
     CAIRO_PS_LEVEL_2,
@@ -2224,11 +2228,16 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t    *surface,
 static cairo_status_t
 _cairo_ps_surface_acquire_surface (cairo_ps_surface_t      *surface,
 				   cairo_surface_pattern_t *pattern,
+				   cairo_rectangle_int_t   *extents,
 				   int                     *width,
 				   int                     *height,
-				   cairo_operator_t	    op)
+				   int 			   *origin_x,
+				   int 			   *origin_y)
 {
     cairo_status_t          status;
+    cairo_surface_t 	   *pad_image;
+    int x = 0;
+    int y = 0;
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	cairo_surface_t *meta_surface = pattern->surface;
@@ -2242,16 +2251,62 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t      *surface,
 	*height = pattern_extents.height;
     } else {
 	status = _cairo_surface_acquire_source_image (pattern->surface,
-						      &surface->image,
+						      &surface->acquired_image,
 						      &surface->image_extra);
 	if (status)
 	    return status;
 
+	pad_image = &surface->acquired_image->base;
+	if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
+	    cairo_box_t box;
+	    cairo_rectangle_int_t rect;
+	    cairo_surface_pattern_t pad_pattern;
+
+	    /* get the operation extents in pattern space */
+	    _cairo_box_from_rectangle (&box, extents);
+	    _cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
+	    _cairo_box_round_to_rectangle (&box, &rect);
+	    x = -rect.x;
+	    y = -rect.y;
+
+	    pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
+								  rect.width,
+								  rect.height);
+	    if (pad_image->status) {
+		status = pad_image->status;
+		goto BAIL;
+	    }
+
+	    _cairo_pattern_init_for_surface (&pad_pattern, &surface->acquired_image->base);
+	    cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
+	    pad_pattern.base.extend = CAIRO_EXTEND_PAD;
+	    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+					       &pad_pattern.base,
+					       NULL,
+					       pad_image,
+					       0, 0,
+					       0, 0,
+					       0, 0,
+					       rect.width,
+					       rect.height);
+	    _cairo_pattern_fini (&pad_pattern.base);
+	    if (status)
+		goto BAIL;
+	}
+
+	surface->image = (cairo_image_surface_t *) pad_image;
 	*width = surface->image->width;
 	*height = surface->image->height;
+	*origin_x = x;
+	*origin_y = y;
     }
 
     return CAIRO_STATUS_SUCCESS;
+
+BAIL:
+    _cairo_ps_surface_release_surface (surface, pattern);
+
+    return status;
 }
 
 static cairo_status_t
@@ -2279,24 +2334,28 @@ _cairo_ps_surface_release_surface (cairo_ps_surface_t      *surface,
 				   cairo_surface_pattern_t *pattern)
 {
     if (!_cairo_surface_is_meta (pattern->surface))
-	_cairo_surface_release_source_image (pattern->surface, surface->image,
+	_cairo_surface_release_source_image (pattern->surface,
+					     surface->acquired_image,
 					     surface->image_extra);
 }
 
 static cairo_status_t
 _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
 				 cairo_surface_pattern_t *pattern,
+				 cairo_rectangle_int_t   *extents,
 				 cairo_operator_t	  op)
 {
     cairo_status_t status;
     int width, height;
     cairo_matrix_t cairo_p2d, ps_p2d;
+    int origin_x = 0;
+    int origin_y = 0;
 
     status = _cairo_ps_surface_acquire_surface (surface,
 						pattern,
-						&width,
-						&height,
-						op);
+						extents,
+						&width, &height,
+						&origin_x, &origin_y);
     if (status)
 	return status;
 
@@ -2329,6 +2388,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
 
     ps_p2d = surface->cairo_to_ps;
     cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
+    cairo_matrix_translate (&ps_p2d, -origin_x, -origin_y);
     cairo_matrix_translate (&ps_p2d, 0.0, height);
     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
 
@@ -2349,6 +2409,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
 static cairo_status_t
 _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 					cairo_surface_pattern_t *pattern,
+					cairo_rectangle_int_t   *extents,
 					cairo_operator_t	 op)
 {
     cairo_status_t status;
@@ -2358,6 +2419,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
     cairo_matrix_t cairo_p2d, ps_p2d;
     cairo_rectangle_int_t surface_extents;
     cairo_bool_t old_use_string_datasource;
+    int origin_x = 0;
+    int origin_y = 0;
 
     cairo_p2d = pattern->base.matrix;
     status = cairo_matrix_invert (&cairo_p2d);
@@ -2366,19 +2429,19 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 
     ps_p2d = surface->cairo_to_ps;
     cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
+    cairo_matrix_translate (&ps_p2d, -origin_x, -origin_y);
     cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
 
     status = _cairo_ps_surface_acquire_surface (surface,
 						pattern,
-						&pattern_width,
-						&pattern_height,
-						op);
+						extents,
+						&pattern_width, &pattern_height,
+						&origin_x, &origin_y);
     if (status)
 	return status;
 
     switch (pattern->base.extend) {
-	/* We implement EXTEND_PAD like EXTEND_NONE for now */
     case CAIRO_EXTEND_PAD:
     case CAIRO_EXTEND_NONE:
     {
@@ -2914,7 +2977,8 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t     *surface,
 static cairo_status_t
 _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
 				const cairo_pattern_t *pattern,
-				cairo_operator_t op)
+				cairo_rectangle_int_t *extents,
+				cairo_operator_t       op)
 {
     cairo_status_t status;
 
@@ -2951,6 +3015,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
     case CAIRO_PATTERN_TYPE_SURFACE:
 	status = _cairo_ps_surface_emit_surface_pattern (surface,
 							 (cairo_surface_pattern_t *) pattern,
+							 extents,
 							 op);
 	if (status)
 	    return status;
@@ -3079,13 +3144,13 @@ _cairo_ps_surface_paint (void			*abstract_surface,
 
 	status = _cairo_ps_surface_paint_surface (surface,
 						 (cairo_surface_pattern_t *) source,
-						 op);
+						  paint_extents, op);
 	if (status)
 	    return status;
 
 	_cairo_output_stream_printf (stream, "Q\n");
     } else {
-	status = _cairo_ps_surface_emit_pattern (surface, source, op);
+	status = _cairo_ps_surface_emit_pattern (surface, source, paint_extents, op);
 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	    return CAIRO_STATUS_SUCCESS;
 
@@ -3125,7 +3190,7 @@ _cairo_ps_surface_stroke (void			*abstract_surface,
 				 "%% _cairo_ps_surface_stroke\n");
 #endif
 
-    status = _cairo_ps_surface_emit_pattern (surface, source, op);
+    status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
         return CAIRO_STATUS_SUCCESS;
 
@@ -3177,14 +3242,14 @@ _cairo_ps_surface_fill (void		*abstract_surface,
 
 	status = _cairo_ps_surface_paint_surface (surface,
 						 (cairo_surface_pattern_t *) source,
-						 op);
+						  extents, op);
 	if (status)
 	    return status;
 
 	_cairo_output_stream_printf (surface->stream, "Q\n");
 	_cairo_pdf_operators_reset (&surface->pdf_operators);
     } else {
-	status = _cairo_ps_surface_emit_pattern (surface, source, op);
+	status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	    return CAIRO_STATUS_SUCCESS;
 
@@ -3225,7 +3290,7 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
     if (num_glyphs <= 0)
         return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_ps_surface_emit_pattern (surface, source, op);
+    status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
         return CAIRO_STATUS_SUCCESS;
 
commit e639b536711c07bc09355205f476ab3f73012268
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 21:00:30 2008 +0930

    PDF: meta-surface patterns with EXTEND_PAD are unsupported
    
    We have to use fallback images for this.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 218cd4f..27fcbe0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4412,8 +4412,12 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
 	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
-	    if ( _cairo_surface_is_meta (surface_pattern->surface))
-		return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+	    if ( _cairo_surface_is_meta (surface_pattern->surface)) {
+		if (cairo_pattern_get_extend (pattern) == CAIRO_EXTEND_PAD)
+		    return CAIRO_INT_STATUS_UNSUPPORTED;
+		else
+		    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+	    }
 	}
     }
 
commit 6c92edd9a3b0c79857cfa8dee482efa56f40c714
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 20:56:49 2008 +0930

    PDF: Implement EXTEND_PAD for image patterns
    
    Images with EXTEND_PAD are painted into a new image the size of the
    operation extents. The new image is then embedded in the PDF file with
    the pattern matrix adjusted to ensure the image origin is in the
    correct location.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3920bd0..218cd4f 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1552,25 +1552,75 @@ CLEANUP:
 
 static cairo_status_t
 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
-				       cairo_surface_pattern_t *pattern,
+				       cairo_pdf_pattern_t     *pdf_pattern,
 				       cairo_pdf_resource_t    *resource,
 				       int                     *width,
-				       int                     *height)
+				       int                     *height,
+				       int 		       *origin_x,
+				       int 		       *origin_y)
 {
     cairo_image_surface_t *image;
+    cairo_surface_t *pad_image;
     void *image_extra;
     cairo_status_t status;
+    cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
+    int x = 0;
+    int y = 0;
 
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
 	goto BAIL;
 
-    status = _cairo_pdf_surface_emit_image (surface, image, resource, pattern->base.filter);
+    pad_image = &image->base;
+    if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
+	cairo_box_t box;
+	cairo_rectangle_int_t rect;
+	cairo_surface_pattern_t pad_pattern;
+
+	/* get the operation extents in pattern space */
+	_cairo_box_from_rectangle (&box, &pdf_pattern->extents);
+	_cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
+	_cairo_box_round_to_rectangle (&box, &rect);
+	x = -rect.x;
+	y = -rect.y;
+
+	pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
+							      rect.width,
+							      rect.height);
+	if (pad_image->status) {
+	    status = pad_image->status;
+	    goto BAIL;
+	}
+
+	_cairo_pattern_init_for_surface (&pad_pattern, &image->base);
+	cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
+	pad_pattern.base.extend = CAIRO_EXTEND_PAD;
+	status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+					   &pad_pattern.base,
+					   NULL,
+					   pad_image,
+					   0, 0,
+					   0, 0,
+					   0, 0,
+					   rect.width,
+					   rect.height);
+	_cairo_pattern_fini (&pad_pattern.base);
+	if (status)
+	    goto BAIL;
+    }
+
+    status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
+					    resource, pattern->base.filter);
     if (status)
 	goto BAIL;
 
-    *width = image->width;
-    *height = image->height;
+    *width = ((cairo_image_surface_t *)pad_image)->width;
+    *height = ((cairo_image_surface_t *)pad_image)->height;
+    *origin_x = x;
+    *origin_y = y;
+
+    if (pad_image != &image->base)
+	cairo_surface_destroy (pad_image);
 
 BAIL:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
@@ -1657,6 +1707,8 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     cairo_rectangle_int_t surface_extents;
     int pattern_width = 0; /* squelch bogus compiler warning */
     int pattern_height = 0; /* squelch bogus compiler warning */
+    int origin_x = 0; /* squelch bogus compiler warning */
+    int origin_y = 0; /* squelch bogus compiler warning */
     int bbox_x, bbox_y;
     char draw_surface[200];
 
@@ -1678,10 +1730,12 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
 	pattern_height = pattern_extents.height;
     } else {
 	status = _cairo_pdf_surface_emit_image_surface (surface,
-							pattern,
+							pdf_pattern,
 							&pattern_resource,
 							&pattern_width,
-							&pattern_height);
+							&pattern_height,
+							&origin_x,
+							&origin_y);
 	if (status)
 	    return status;
     }
@@ -1693,7 +1747,6 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     bbox_x = pattern_width;
     bbox_y = pattern_height;
     switch (extend) {
-	/* We implement EXTEND_PAD like EXTEND_NONE for now */
     case CAIRO_EXTEND_PAD:
     case CAIRO_EXTEND_NONE:
     {
@@ -1777,6 +1830,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
     cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
     cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
commit d146cb4056ab54cf85454a6fe9d36282ca7a3f2e
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 20:56:01 2008 +0930

    PDF: Store the operation extents in each pattern
    
    The extents will be used by EXTEND_PAD patterns as well as any other
    pattern that can benefit from knowing the extents of the operation it
    will be used with.

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index ab222de..7f2764f 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -63,6 +63,7 @@ typedef struct _cairo_pdf_group_resources {
 typedef struct _cairo_pdf_pattern {
     double width;
     double height;
+    cairo_rectangle_int_t extents;
     cairo_pattern_t *pattern;
     cairo_pdf_resource_t pattern_res;
     cairo_pdf_resource_t gstate_res;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6db4cd3..3920bd0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -775,6 +775,7 @@ _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
 static cairo_status_t
 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 				    const cairo_pattern_t	*pattern,
+				    cairo_rectangle_int_t       *extents,
 				    cairo_pdf_resource_t	*pattern_res,
 				    cairo_pdf_resource_t	*gstate_res)
 {
@@ -833,6 +834,15 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 
     pdf_pattern.width = surface->width;
     pdf_pattern.height = surface->height;
+    if (extents) {
+	pdf_pattern.extents = *extents;
+    } else {
+	pdf_pattern.extents.x = 0;
+	pdf_pattern.extents.y = 0;
+	pdf_pattern.extents.width = surface->width;
+	pdf_pattern.extents.height = surface->height;
+    }
+
     *pattern_res = pdf_pattern.pattern_res;
     *gstate_res = pdf_pattern.gstate_res;
 
@@ -3879,7 +3889,8 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t	*surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
+						 &pattern_res, &gstate_res);
     if (status)
 	return status;
 
@@ -3934,7 +3945,8 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t	*surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
+						 &pattern_res, &gstate_res);
     if (status)
 	return status;
 
@@ -4440,7 +4452,8 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
+						 &pattern_res, &gstate_res);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	return CAIRO_STATUS_SUCCESS;
     if (status)
@@ -4601,7 +4614,8 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
+						 &pattern_res, &gstate_res);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	return CAIRO_STATUS_SUCCESS;
     if (status)
@@ -4698,7 +4712,8 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
+						 &pattern_res, &gstate_res);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	return CAIRO_STATUS_SUCCESS;
     if (status)
@@ -4807,6 +4822,7 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
     fill_pattern_res.id = 0;
     gstate_res.id = 0;
     status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
+						 extents,
 						 &fill_pattern_res,
 						 &gstate_res);
     if (status)
@@ -4818,6 +4834,7 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
     gstate_res.id = 0;
     status = _cairo_pdf_surface_add_pdf_pattern (surface,
 						 stroke_source,
+						 extents,
 						 &stroke_pattern_res,
 						 &gstate_res);
     if (status)
@@ -4885,7 +4902,8 @@ _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
 
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
+						 &pattern_res, &gstate_res);
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 	return CAIRO_STATUS_SUCCESS;
     if (status)
commit fb7cfdd94d4e436e066d884f6dc294efd896b344
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 20:52:08 2008 +0930

    Make meta-surface store and replay extents of each operation
    
    To be able to provide the extents of each operation to the backend
    during the render phase the meta-surface needs to store the extents
    computed by the analysis surface during the analysis phase.
    
    The extents argument is either a pointer to the extents of the operation
    stored in the meta-surface or NULL. During analysis the analysis surface
    writes the extents to the meta-surface. During the render phase the extents
    is made available to paginated surface backends.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index be3f734..d5b63e8 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -354,6 +354,8 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
     }
 
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (paint_extents)
+	*paint_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -432,6 +434,8 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
     }
 
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (mask_extents)
+	*mask_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -505,6 +509,8 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 
         _cairo_box_round_to_rectangle (&box, &extents);
     }
+    if (stroke_extents)
+	*stroke_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -574,6 +580,8 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 
         _cairo_box_round_to_rectangle (&box, &extents);
     }
+    if (fill_extents)
+	*fill_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -642,6 +650,8 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_glyphs_extents)
+	*show_glyphs_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -726,6 +736,8 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_text_glyphs_extents)
+	*show_text_glyphs_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index 9a1b169..8d5e096 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -67,6 +67,7 @@ typedef enum {
 typedef struct _cairo_command_header {
     cairo_command_type_t	 type;
     cairo_meta_region_type_t     region;
+    cairo_rectangle_int_t        extents;
 } cairo_command_header_t;
 
 typedef struct _cairo_command_paint {
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 5f9fed2..cfaaf30 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -232,6 +232,10 @@ _cairo_meta_surface_paint (void			*abstract_surface,
 
     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;
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -274,6 +278,10 @@ _cairo_meta_surface_mask (void			*abstract_surface,
 
     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;
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -321,6 +329,10 @@ _cairo_meta_surface_stroke (void			*abstract_surface,
 
     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;
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -377,6 +389,10 @@ _cairo_meta_surface_fill (void			*abstract_surface,
 
     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;
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -436,6 +452,10 @@ _cairo_meta_surface_show_text_glyphs (void			    *abstract_surface,
 
     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;
     command->op = op;
 
     status = _cairo_pattern_init_snapshot (&command->source.base, source);
@@ -811,13 +831,13 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_paint (target,
 					   command->paint.op,
-					   &command->paint.source.base, NULL);
+					   &command->paint.source.base, &command->header.extents);
 	    break;
 	case CAIRO_COMMAND_MASK:
 	    status = _cairo_surface_mask (target,
 					  command->mask.op,
 					  &command->mask.source.base,
-					  &command->mask.mask.base, NULL);
+					  &command->mask.mask.base, &command->header.extents);
 	    break;
 	case CAIRO_COMMAND_STROKE:
 	{
@@ -839,7 +859,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 					    &dev_ctm,
 					    &dev_ctm_inverse,
 					    command->stroke.tolerance,
-					    command->stroke.antialias, NULL);
+					    command->stroke.antialias, &command->header.extents);
 	    break;
 	}
 	case CAIRO_COMMAND_FILL:
@@ -886,7 +906,8 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 						     &dev_ctm,
 						     &dev_ctm_inverse,
 						     stroke_command->stroke.tolerance,
-						     stroke_command->stroke.antialias, NULL);
+						     stroke_command->stroke.antialias,
+						     &stroke_command->header.extents);
 		i++;
 	    } else
 		status = _cairo_surface_fill (target,
@@ -895,7 +916,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 					      dev_path,
 					      command->fill.fill_rule,
 					      command->fill.tolerance,
-					      command->fill.antialias, NULL);
+					      command->fill.antialias, &command->header.extents);
 	    break;
 	}
 	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
@@ -932,7 +953,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 							 dev_glyphs, num_glyphs,
 							 command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
 							 command->show_text_glyphs.cluster_flags,
-							 command->show_text_glyphs.scaled_font, NULL);
+							 command->show_text_glyphs.scaled_font, &command->header.extents);
 
 	    free (dev_glyphs);
 	    break;
commit d682d275b90f7326df76d2764c513c8b6d5b551b
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 1 20:50:53 2008 +0930

    Add an extents argument to the high level surface backend functions
    
    Add a "cairo_rectangle_int_t *extents" argument to to the following
    backend functions:
      paint
      mask,
      stroke
      fill
      show_glyphs
      show_text_glyphs
    
    This will be used to pass the extents of each operation computed by
    the analysis surface to the backend. This is required for implementing
    EXTEND_PAD.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 4337e92..be3f734 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -322,7 +322,8 @@ _cairo_analysis_surface_get_extents (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_analysis_surface_paint (void			*abstract_surface,
 			       cairo_operator_t		op,
-			       const cairo_pattern_t		*source)
+			       const cairo_pattern_t	*source,
+			       cairo_rectangle_int_t    *paint_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -333,7 +334,7 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->paint) (surface->target, op,
-                                                             source);
+                                                             source, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
@@ -363,7 +364,8 @@ static cairo_int_status_t
 _cairo_analysis_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
 			      const cairo_pattern_t	*source,
-			      const cairo_pattern_t	*mask)
+			      const cairo_pattern_t	*mask,
+			      cairo_rectangle_int_t 	*mask_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_int_status_t	      status, backend_status;
@@ -374,7 +376,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->mask) (surface->target, op,
-                                                            source, mask);
+                                                            source, mask, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
 	cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
@@ -445,7 +447,8 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 				cairo_matrix_t		*ctm,
 				cairo_matrix_t		*ctm_inverse,
 				double			 tolerance,
-				cairo_antialias_t	 antialias)
+				cairo_antialias_t	 antialias,
+				cairo_rectangle_int_t   *stroke_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -459,7 +462,7 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 	backend_status = (*surface->target->backend->stroke) (surface->target, op,
 							      source, path, style,
 							      ctm, ctm_inverse,
-							      tolerance, antialias);
+							      tolerance, antialias, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
@@ -515,7 +518,8 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
-			      cairo_antialias_t		 antialias)
+			      cairo_antialias_t		 antialias,
+			      cairo_rectangle_int_t     *fill_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -528,7 +532,7 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
     else
 	backend_status = (*surface->target->backend->fill) (surface->target, op,
 						    source, path, fill_rule,
-						    tolerance, antialias);
+							    tolerance, antialias, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
@@ -583,7 +587,8 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
 				     cairo_scaled_font_t  *scaled_font,
-				     int                  *remaining_glyphs)
+				     int                  *remaining_glyphs,
+				     cairo_rectangle_int_t *show_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -596,7 +601,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 								   source,
 								   glyphs, num_glyphs,
 								   scaled_font,
-								   remaining_glyphs);
+								   remaining_glyphs, NULL);
     else if (surface->target->backend->show_text_glyphs)
 	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
 								     source,
@@ -604,7 +609,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 								     glyphs, num_glyphs,
 								     NULL, 0,
 								     FALSE,
-								     scaled_font);
+								     scaled_font, NULL);
     else
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -662,7 +667,8 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
 					  cairo_text_cluster_flags_t cluster_flags,
-					  cairo_scaled_font_t	    *scaled_font)
+					  cairo_scaled_font_t	    *scaled_font,
+					  cairo_rectangle_int_t     *show_text_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -677,14 +683,14 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 								     utf8, utf8_len,
 								     glyphs, num_glyphs,
 								     clusters, num_clusters, cluster_flags,
-								     scaled_font);
+								     scaled_font, NULL);
     if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
 	int remaining_glyphs = num_glyphs;
 	backend_status = surface->target->backend->show_glyphs (surface->target, op,
 								source,
 								glyphs, num_glyphs,
 								scaled_font,
-								&remaining_glyphs);
+								&remaining_glyphs, NULL);
 	glyphs += num_glyphs - remaining_glyphs;
 	num_glyphs = remaining_glyphs;
 	if (remaining_glyphs == 0)
@@ -898,13 +904,15 @@ typedef cairo_int_status_t
 typedef cairo_int_status_t
 (*_paint_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 const cairo_pattern_t	*source);
+				 const cairo_pattern_t	*source,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_mask_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
-				 const cairo_pattern_t	*mask);
+				 const cairo_pattern_t	*mask,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_stroke_func)			(void			*surface,
@@ -915,7 +923,8 @@ typedef cairo_int_status_t
 				 cairo_matrix_t		*ctm,
 				 cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_fill_func)			(void			*surface,
@@ -924,7 +933,8 @@ typedef cairo_int_status_t
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_show_glyphs_func)		(void			*surface,
@@ -933,7 +943,8 @@ typedef cairo_int_status_t
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
-				 int			*remaining_glyphs);
+				 int			*remaining_glyphs,
+				 cairo_rectangle_int_t  *extents);
 
 static const cairo_surface_backend_t cairo_null_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_NULL,
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index 351e00d..5a970b9 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1687,7 +1687,8 @@ _cairo_directfb_surface_show_glyphs (void		    *abstract_dst,
                                      cairo_glyph_t	    *glyphs,
                                      int		     num_glyphs,
                                      cairo_scaled_font_t    *scaled_font,
-				     int		    *remaining_glyphs)
+				     int		    *remaining_glyphs,
+				     cairo_rectangle_int_t  *extents)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 7e56a77..5b8c87d 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -899,7 +899,7 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
 
     status = _cairo_surface_paint (gstate->target,
 				   gstate->op,
-				   pattern);
+				   pattern, NULL);
 
     if (pattern == &pattern_stack.base)
 	_cairo_pattern_fini (pattern);
@@ -938,7 +938,7 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
     status = _cairo_surface_mask (gstate->target,
 				  gstate->op,
 				  source_pattern,
-				  mask_pattern);
+				  mask_pattern, NULL);
 
     if (mask_pattern == &mask_pattern_stack.base)
 	_cairo_pattern_fini (&mask_pattern_stack.base);
@@ -980,7 +980,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 				    &gstate->ctm,
 				    &gstate->ctm_inverse,
 				    gstate->tolerance,
-				    gstate->antialias);
+				    gstate->antialias, NULL);
 
     if (source_pattern == &source_pattern_stack.base)
 	_cairo_pattern_fini (&source_pattern_stack.base);
@@ -1056,7 +1056,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 				  path,
 				  gstate->fill_rule,
 				  gstate->tolerance,
-				  gstate->antialias);
+				  gstate->antialias, NULL);
 
     if (pattern == &pattern_stack.base)
 	_cairo_pattern_fini (&pattern_stack.base);
@@ -1679,7 +1679,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 						  transformed_glyphs, num_glyphs,
 						  clusters, num_clusters,
 						  cluster_flags,
-						  gstate->scaled_font);
+						  gstate->scaled_font, NULL);
     } else {
 	cairo_path_fixed_t path;
 
@@ -1696,7 +1696,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 					&path,
 					CAIRO_FILL_RULE_WINDING,
 					gstate->tolerance,
-					gstate->scaled_font->options.antialias);
+					gstate->scaled_font->options.antialias, NULL);
 
 	_cairo_path_fixed_fini (&path);
     }
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index faf4855..5f9fed2 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -219,7 +219,8 @@ _cairo_meta_surface_release_source_image (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_meta_surface_paint (void			*abstract_surface,
 			   cairo_operator_t	 op,
-			   const cairo_pattern_t	*source)
+			   const cairo_pattern_t  *source,
+			   cairo_rectangle_int_t  *extents)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -260,7 +261,8 @@ static cairo_int_status_t
 _cairo_meta_surface_mask (void			*abstract_surface,
 			  cairo_operator_t	 op,
 			  const cairo_pattern_t	*source,
-			  const cairo_pattern_t	*mask)
+			  const cairo_pattern_t	*mask,
+			  cairo_rectangle_int_t *extents)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -306,7 +308,8 @@ _cairo_meta_surface_stroke (void			*abstract_surface,
 			    cairo_matrix_t		*ctm,
 			    cairo_matrix_t		*ctm_inverse,
 			    double			 tolerance,
-			    cairo_antialias_t		 antialias)
+			    cairo_antialias_t		 antialias,
+			    cairo_rectangle_int_t 	*extents)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -361,7 +364,8 @@ _cairo_meta_surface_fill (void			*abstract_surface,
 			  cairo_path_fixed_t	*path,
 			  cairo_fill_rule_t	 fill_rule,
 			  double		 tolerance,
-			  cairo_antialias_t	 antialias)
+			  cairo_antialias_t	 antialias,
+			  cairo_rectangle_int_t  *extents)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -419,7 +423,8 @@ _cairo_meta_surface_show_text_glyphs (void			    *abstract_surface,
 				      const cairo_text_cluster_t    *clusters,
 				      int			     num_clusters,
 				      cairo_text_cluster_flags_t     cluster_flags,
-				      cairo_scaled_font_t	    *scaled_font)
+				      cairo_scaled_font_t	    *scaled_font,
+				      cairo_rectangle_int_t 	    *extents)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -806,13 +811,13 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_paint (target,
 					   command->paint.op,
-					   &command->paint.source.base);
+					   &command->paint.source.base, NULL);
 	    break;
 	case CAIRO_COMMAND_MASK:
 	    status = _cairo_surface_mask (target,
 					  command->mask.op,
 					  &command->mask.source.base,
-					  &command->mask.mask.base);
+					  &command->mask.mask.base, NULL);
 	    break;
 	case CAIRO_COMMAND_STROKE:
 	{
@@ -834,7 +839,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 					    &dev_ctm,
 					    &dev_ctm_inverse,
 					    command->stroke.tolerance,
-					    command->stroke.antialias);
+					    command->stroke.antialias, NULL);
 	    break;
 	}
 	case CAIRO_COMMAND_FILL:
@@ -881,7 +886,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 						     &dev_ctm,
 						     &dev_ctm_inverse,
 						     stroke_command->stroke.tolerance,
-						     stroke_command->stroke.antialias);
+						     stroke_command->stroke.antialias, NULL);
 		i++;
 	    } else
 		status = _cairo_surface_fill (target,
@@ -890,7 +895,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 					      dev_path,
 					      command->fill.fill_rule,
 					      command->fill.tolerance,
-					      command->fill.antialias);
+					      command->fill.antialias, NULL);
 	    break;
 	}
 	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
@@ -927,7 +932,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 							 dev_glyphs, num_glyphs,
 							 command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
 							 command->show_text_glyphs.cluster_flags,
-							 command->show_text_glyphs.scaled_font);
+							 command->show_text_glyphs.scaled_font, NULL);
 
 	    free (dev_glyphs);
 	    break;
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index ec9419b..94a599e 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -279,7 +279,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
 
     status = _cairo_surface_paint (surface->target,
 				   CAIRO_OPERATOR_SOURCE,
-				   &pattern.base);
+				   &pattern.base, NULL);
 
     _cairo_pattern_fini (&pattern.base);
 CLEANUP_IMAGE:
@@ -529,7 +529,8 @@ _cairo_paginated_surface_get_font_options (void                  *abstract_surfa
 static cairo_int_status_t
 _cairo_paginated_surface_paint (void			*abstract_surface,
 				cairo_operator_t	 op,
-				const cairo_pattern_t	*source)
+				const cairo_pattern_t	*source,
+				cairo_rectangle_int_t   *extents)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -539,18 +540,19 @@ _cairo_paginated_surface_paint (void			*abstract_surface,
 
     surface->page_is_blank = FALSE;
 
-    return _cairo_surface_paint (surface->meta, op, source);
+    return _cairo_surface_paint (surface->meta, op, source, NULL);
 }
 
 static cairo_int_status_t
 _cairo_paginated_surface_mask (void		*abstract_surface,
 			       cairo_operator_t	 op,
 			       const cairo_pattern_t	*source,
-			       const cairo_pattern_t	*mask)
+			       const cairo_pattern_t	*mask,
+			       cairo_rectangle_int_t    *extents)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
-    return _cairo_surface_mask (surface->meta, op, source, mask);
+    return _cairo_surface_mask (surface->meta, op, source, mask, NULL);
 }
 
 static cairo_int_status_t
@@ -562,7 +564,8 @@ _cairo_paginated_surface_stroke (void			*abstract_surface,
 				 cairo_matrix_t		*ctm,
 				 cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias)
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -575,7 +578,7 @@ _cairo_paginated_surface_stroke (void			*abstract_surface,
     return _cairo_surface_stroke (surface->meta, op, source,
 				  path, style,
 				  ctm, ctm_inverse,
-				  tolerance, antialias);
+				  tolerance, antialias, NULL);
 }
 
 static cairo_int_status_t
@@ -585,7 +588,8 @@ _cairo_paginated_surface_fill (void			*abstract_surface,
 			       cairo_path_fixed_t	*path,
 			       cairo_fill_rule_t	 fill_rule,
 			       double			 tolerance,
-			       cairo_antialias_t	 antialias)
+			       cairo_antialias_t	 antialias,
+			       cairo_rectangle_int_t    *extents)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -597,7 +601,7 @@ _cairo_paginated_surface_fill (void			*abstract_surface,
 
     return _cairo_surface_fill (surface->meta, op, source,
 				path, fill_rule,
-				tolerance, antialias);
+				tolerance, antialias, NULL);
 }
 
 static cairo_bool_t
@@ -619,7 +623,8 @@ _cairo_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
 					  cairo_text_cluster_flags_t cluster_flags,
-					  cairo_scaled_font_t	    *scaled_font)
+					   cairo_scaled_font_t	    *scaled_font,
+					   cairo_rectangle_int_t    *extents)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -645,7 +650,7 @@ _cairo_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					      glyphs, num_glyphs,
 					      clusters, num_clusters,
 					      cluster_flags,
-					      scaled_font);
+					      scaled_font, NULL);
 
     return status;
 }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index b2a5619..6db4cd3 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4420,7 +4420,8 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
 static cairo_int_status_t
 _cairo_pdf_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  const cairo_pattern_t	*source)
+			  const cairo_pattern_t	*source,
+			  cairo_rectangle_int_t *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4500,7 +4501,8 @@ static cairo_int_status_t
 _cairo_pdf_surface_mask	(void			*abstract_surface,
 			 cairo_operator_t	 op,
 			 const cairo_pattern_t	*source,
-			 const cairo_pattern_t	*mask)
+			 const cairo_pattern_t	*mask,
+			 cairo_rectangle_int_t  *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_pdf_smask_group_t *group;
@@ -4584,7 +4586,8 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
 			   cairo_matrix_t	*ctm,
 			   cairo_matrix_t	*ctm_inverse,
 			   double		 tolerance,
-			   cairo_antialias_t	 antialias)
+			   cairo_antialias_t	 antialias,
+			   cairo_rectangle_int_t *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4675,7 +4678,8 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
-			 cairo_antialias_t	 antialias)
+			 cairo_antialias_t	 antialias,
+			 cairo_rectangle_int_t  *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4774,7 +4778,8 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
 				cairo_matrix_t	     *stroke_ctm,
 				cairo_matrix_t	     *stroke_ctm_inverse,
 				double		      stroke_tolerance,
-				cairo_antialias_t     stroke_antialias)
+				cairo_antialias_t     stroke_antialias,
+				cairo_rectangle_int_t *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4865,7 +4870,8 @@ _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
 				     const cairo_text_cluster_t *clusters,
 				     int                         num_clusters,
 				     cairo_text_cluster_flags_t  cluster_flags,
-				     cairo_scaled_font_t	*scaled_font)
+				     cairo_scaled_font_t	*scaled_font,
+				     cairo_rectangle_int_t      *extents)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index fbfdc3e..6242143 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3043,7 +3043,8 @@ _cairo_ps_surface_get_font_options (void                  *abstract_surface,
 static cairo_int_status_t
 _cairo_ps_surface_paint (void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 const cairo_pattern_t	*source)
+			 const cairo_pattern_t	*source,
+			 cairo_rectangle_int_t  *paint_extents)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
@@ -3108,7 +3109,8 @@ _cairo_ps_surface_stroke (void			*abstract_surface,
 			  cairo_matrix_t	*ctm,
 			  cairo_matrix_t	*ctm_inverse,
 			  double		 tolerance,
-			  cairo_antialias_t	 antialias)
+			  cairo_antialias_t	 antialias,
+			  cairo_rectangle_int_t *extents)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -3141,7 +3143,8 @@ _cairo_ps_surface_fill (void		*abstract_surface,
 			cairo_path_fixed_t	*path,
 			cairo_fill_rule_t	 fill_rule,
 			double			 tolerance,
-			cairo_antialias_t	 antialias)
+			cairo_antialias_t	 antialias,
+			cairo_rectangle_int_t   *extents)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -3203,7 +3206,8 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
 			       cairo_glyph_t         *glyphs,
 			       int		      num_glyphs,
 			       cairo_scaled_font_t   *scaled_font,
-			       int		     *remaining_glyphs)
+			       int		     *remaining_glyphs,
+			       cairo_rectangle_int_t *extents)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_status_t status;
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index fc9439e..2addd8b 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1667,7 +1667,8 @@ _cairo_quartz_surface_get_extents (void *abstract_surface,
 static cairo_int_status_t
 _cairo_quartz_surface_paint (void *abstract_surface,
 			     cairo_operator_t op,
-			     cairo_pattern_t *source)
+			     cairo_pattern_t *source,
+			     cairo_rectangle_int_t *extents)
 {
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1722,7 +1723,8 @@ _cairo_quartz_surface_fill (void *abstract_surface,
 			     cairo_path_fixed_t *path,
 			     cairo_fill_rule_t fill_rule,
 			     double tolerance,
-			     cairo_antialias_t antialias)
+			     cairo_antialias_t antialias,
+			     cairo_rectangle_int_t *extents)
 {
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1829,7 +1831,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
 			      cairo_matrix_t *ctm,
 			      cairo_matrix_t *ctm_inverse,
 			      double tolerance,
-			      cairo_antialias_t antialias)
+			      cairo_antialias_t antialias,
+			      cairo_rectangle_int_t *extents)
 {
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1973,7 +1976,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 				   cairo_glyph_t *glyphs,
 				   int num_glyphs,
 				   cairo_scaled_font_t *scaled_font,
-				   int *remaining_glyphs)
+				   int *remaining_glyphs,
+				   cairo_rectangle_int_t *extents)
 {
     CGAffineTransform textTransform, ctm;
 #define STATIC_BUF_SIZE 64
@@ -2286,7 +2290,8 @@ static cairo_int_status_t
 _cairo_quartz_surface_mask (void *abstract_surface,
 			    cairo_operator_t op,
 			    cairo_pattern_t *source,
-			    cairo_pattern_t *mask)
+			    cairo_pattern_t *mask,
+			    cairo_rectangle_int_t *extents)
 {
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index ff75cc2..40b10e7 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -327,7 +327,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
     status = _cairo_surface_paint (surface,
 				   color == CAIRO_COLOR_TRANSPARENT ?
 				   CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
-				   &solid_pattern.base);
+				   &solid_pattern.base, NULL);
 
     _cairo_pattern_fini (&solid_pattern.base);
 
@@ -373,7 +373,7 @@ _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t	    *other,
 	 */
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    return _cairo_surface_paint (solid_surface, CAIRO_OPERATOR_SOURCE, &solid_pattern->base);
+    return _cairo_surface_paint (solid_surface, CAIRO_OPERATOR_SOURCE, &solid_pattern->base, NULL);
 }
 
 cairo_clip_mode_t
@@ -1473,7 +1473,8 @@ _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 cairo_status_t
 _cairo_surface_paint (cairo_surface_t	*surface,
 		      cairo_operator_t	 op,
-		      const cairo_pattern_t *source)
+		      const cairo_pattern_t *source,
+		      cairo_rectangle_int_t *extents)
 {
     cairo_status_t status;
     cairo_pattern_union_t dev_source;
@@ -1490,7 +1491,7 @@ _cairo_surface_paint (cairo_surface_t	*surface,
 	return _cairo_surface_set_error (surface, status);
 
     if (surface->backend->paint) {
-	status = surface->backend->paint (surface, op, source);
+	status = surface->backend->paint (surface, op, source, extents);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto FINISH;
     }
@@ -1508,7 +1509,8 @@ cairo_status_t
 _cairo_surface_mask (cairo_surface_t		*surface,
 		     cairo_operator_t		 op,
 		     const cairo_pattern_t	*source,
-		     const cairo_pattern_t	*mask)
+		     const cairo_pattern_t	*mask,
+		     cairo_rectangle_int_t      *extents)
 {
     cairo_status_t status;
     cairo_pattern_union_t dev_source;
@@ -1532,7 +1534,7 @@ _cairo_surface_mask (cairo_surface_t		*surface,
 	goto CLEANUP_SOURCE;
 
     if (surface->backend->mask) {
-	status = surface->backend->mask (surface, op, source, mask);
+	status = surface->backend->mask (surface, op, source, mask, extents);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto CLEANUP_MASK;
     }
@@ -1564,7 +1566,8 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 			    cairo_matrix_t	    *stroke_ctm,
 			    cairo_matrix_t	    *stroke_ctm_inverse,
 			    double		     stroke_tolerance,
-			    cairo_antialias_t	     stroke_antialias)
+			    cairo_antialias_t	     stroke_antialias,
+			    cairo_rectangle_int_t   *extents)
 {
     cairo_status_t status;
 
@@ -1600,7 +1603,8 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 						stroke_op, stroke_source,
 						stroke_style,
 						&dev_ctm, &dev_ctm_inverse,
-						stroke_tolerance, stroke_antialias);
+						stroke_tolerance, stroke_antialias,
+						extents);
 
 	if (stroke_source == &dev_stroke_source.base)
 	    _cairo_pattern_fini (&dev_stroke_source.base);
@@ -1613,13 +1617,13 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
     }
 
     status = _cairo_surface_fill (surface, fill_op, fill_source, path,
-				  fill_rule, fill_tolerance, fill_antialias);
+				  fill_rule, fill_tolerance, fill_antialias, NULL);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
     status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path,
 				    stroke_style, stroke_ctm, stroke_ctm_inverse,
-				    stroke_tolerance, stroke_antialias);
+				    stroke_tolerance, stroke_antialias, NULL);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
@@ -1635,7 +1639,8 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_matrix_t		*ctm,
 		       cairo_matrix_t		*ctm_inverse,
 		       double			 tolerance,
-		       cairo_antialias_t	 antialias)
+		       cairo_antialias_t	 antialias,
+		       cairo_rectangle_int_t    *extents)
 {
     cairo_status_t status;
     cairo_pattern_union_t dev_source;
@@ -1659,7 +1664,7 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 	status = surface->backend->stroke (surface, op, source,
 					   path, stroke_style,
 					   &dev_ctm, &dev_ctm_inverse,
-					   tolerance, antialias);
+					   tolerance, antialias, extents);
 
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto FINISH;
@@ -1687,7 +1692,8 @@ _cairo_surface_fill (cairo_surface_t	*surface,
 		     cairo_path_fixed_t	*path,
 		     cairo_fill_rule_t	 fill_rule,
 		     double		 tolerance,
-		     cairo_antialias_t	 antialias)
+		     cairo_antialias_t	 antialias,
+		     cairo_rectangle_int_t *extents)
 {
     cairo_status_t status;
     cairo_pattern_union_t dev_source;
@@ -1706,7 +1712,7 @@ _cairo_surface_fill (cairo_surface_t	*surface,
     if (surface->backend->fill) {
 	status = surface->backend->fill (surface, op, source,
 					 path, fill_rule,
-					 tolerance, antialias);
+					 tolerance, antialias, extents);
 
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto FINISH;
@@ -2258,7 +2264,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 const cairo_text_cluster_t *clusters,
 				 int			     num_clusters,
 				 cairo_text_cluster_flags_t  cluster_flags,
-				 cairo_scaled_font_t	    *scaled_font)
+				 cairo_scaled_font_t	    *scaled_font,
+				 cairo_rectangle_int_t      *extents)
 {
     cairo_status_t status;
     cairo_scaled_font_t *dev_scaled_font = scaled_font;
@@ -2314,7 +2321,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 							 utf8, utf8_len,
 							 glyphs, num_glyphs,
 							 clusters, num_clusters, cluster_flags,
-							 dev_scaled_font);
+							 dev_scaled_font, extents);
 	}
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
 	    int remaining_glyphs = num_glyphs;
@@ -2322,7 +2329,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 						    source,
 						    glyphs, num_glyphs,
 						    dev_scaled_font,
-						    &remaining_glyphs);
+						    &remaining_glyphs, extents);
 	    glyphs += num_glyphs - remaining_glyphs;
 	    num_glyphs = remaining_glyphs;
 	    if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
@@ -2336,7 +2343,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 						    source,
 						    glyphs, num_glyphs,
 						    dev_scaled_font,
-						    &remaining_glyphs);
+						    &remaining_glyphs, extents);
 	    glyphs += num_glyphs - remaining_glyphs;
 	    num_glyphs = remaining_glyphs;
 	    if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
@@ -2355,7 +2362,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 							 utf8, utf8_len,
 							 glyphs, num_glyphs,
 							 clusters, num_clusters, cluster_flags,
-							 dev_scaled_font);
+							 dev_scaled_font, extents);
 	}
     }
 
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index a50f13b..039cc39 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1890,7 +1890,8 @@ _cairo_svg_surface_fill_stroke (void			*abstract_surface,
 				cairo_matrix_t		*stroke_ctm,
 				cairo_matrix_t		*stroke_ctm_inverse,
 				double			 stroke_tolerance,
-				cairo_antialias_t	 stroke_antialias)
+				cairo_antialias_t	 stroke_antialias,
+				cairo_rectangle_int_t    *extents)
 {
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -1925,7 +1926,8 @@ _cairo_svg_surface_fill (void			*abstract_surface,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
-			 cairo_antialias_t	 antialias)
+			 cairo_antialias_t	 antialias,
+			 cairo_rectangle_int_t  *extents)
 {
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -2013,7 +2015,8 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
 static cairo_int_status_t
 _cairo_svg_surface_paint (void		    *abstract_surface,
 			  cairo_operator_t   op,
-			  const cairo_pattern_t   *source)
+			  const cairo_pattern_t   *source,
+			  cairo_rectangle_int_t   *extents)
 {
     cairo_status_t status;
     cairo_svg_surface_t *surface = abstract_surface;
@@ -2065,9 +2068,10 @@ _cairo_svg_surface_paint (void		    *abstract_surface,
 
 static cairo_int_status_t
 _cairo_svg_surface_mask (void		    *abstract_surface,
-			cairo_operator_t     op,
-			const cairo_pattern_t	    *source,
-			const cairo_pattern_t	    *mask)
+			 cairo_operator_t     op,
+			 const cairo_pattern_t	    *source,
+			 const cairo_pattern_t	    *mask,
+			 cairo_rectangle_int_t      *extents)
 {
     cairo_status_t status;
     cairo_svg_surface_t *surface = abstract_surface;
@@ -2154,7 +2158,8 @@ _cairo_svg_surface_stroke (void			*abstract_dst,
 			   cairo_matrix_t	*ctm,
 			   cairo_matrix_t	*ctm_inverse,
 			   double		 tolerance,
-			   cairo_antialias_t	 antialias)
+			   cairo_antialias_t	 antialias,
+			   cairo_rectangle_int_t *extents)
 {
     cairo_svg_surface_t *surface = abstract_dst;
     cairo_status_t status;
@@ -2189,7 +2194,8 @@ _cairo_svg_surface_show_glyphs (void			*abstract_surface,
 				cairo_glyph_t		*glyphs,
 				int			 num_glyphs,
 				cairo_scaled_font_t	*scaled_font,
-				int			*remaining_glyphs)
+				int			*remaining_glyphs,
+				cairo_rectangle_int_t   *extents)
 {
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_svg_document_t *document = surface->document;
@@ -2261,7 +2267,7 @@ FALLBACK:
     }
 
     status = _cairo_svg_surface_fill (abstract_surface, op, pattern,
-				      &path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL);
+				      &path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL, NULL);
 
     _cairo_path_fixed_fini (&path);
 
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 58048ac..6f9eb43 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -182,7 +182,8 @@ _cairo_type3_glyph_surface_intersect_clip_path (void		   *abstract_surface,
 static cairo_int_status_t
 _cairo_type3_glyph_surface_paint (void			*abstract_surface,
 				  cairo_operator_t	 op,
-				  const cairo_pattern_t	*source)
+				  const cairo_pattern_t	*source,
+				  cairo_rectangle_int_t	*extents)
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
     const cairo_surface_pattern_t *pattern;
@@ -212,9 +213,10 @@ static cairo_int_status_t
 _cairo_type3_glyph_surface_mask (void			*abstract_surface,
 				 cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
-				 const cairo_pattern_t	*mask)
+				 const cairo_pattern_t	*mask,
+				 cairo_rectangle_int_t	*extents)
 {
-    return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask);
+    return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask, extents);
 }
 
 static cairo_int_status_t
@@ -226,7 +228,8 @@ _cairo_type3_glyph_surface_stroke (void			*abstract_surface,
 				   cairo_matrix_t	*ctm,
 				   cairo_matrix_t	*ctm_inverse,
 				   double		 tolerance,
-				   cairo_antialias_t	 antialias)
+				   cairo_antialias_t	 antialias,
+				   cairo_rectangle_int_t *extents)
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
 
@@ -244,7 +247,8 @@ _cairo_type3_glyph_surface_fill (void			*abstract_surface,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias)
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents)
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -263,7 +267,8 @@ _cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
 					cairo_glyph_t        *glyphs,
 					int		      num_glyphs,
 					cairo_scaled_font_t  *scaled_font,
-					int		     *remaining_glyphs)
+					int		     *remaining_glyphs,
+					cairo_rectangle_int_t *extents)
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 553ef40..77febf0 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1037,7 +1037,8 @@ _cairo_win32_printing_surface_get_font_options (void                  *abstract_
 static cairo_int_status_t
 _cairo_win32_printing_surface_paint (void			*abstract_surface,
                                      cairo_operator_t		 op,
-                                     const cairo_pattern_t	*source)
+                                     const cairo_pattern_t	*source,
+				     cairo_rectangle_int_t      *extents)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_solid_pattern_t clear;
@@ -1114,7 +1115,8 @@ _cairo_win32_printing_surface_stroke (void			*abstract_surface,
                                       cairo_matrix_t		*stroke_ctm,
                                       cairo_matrix_t		*stroke_ctm_inverse,
                                       double			tolerance,
-                                      cairo_antialias_t		antialias)
+                                      cairo_antialias_t		antialias,
+				      cairo_rectangle_int_t    *extents)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -1235,7 +1237,8 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
 				    cairo_path_fixed_t		*path,
 				    cairo_fill_rule_t		 fill_rule,
 				    double			 tolerance,
-				    cairo_antialias_t		 antialias)
+				    cairo_antialias_t		 antialias,
+				    cairo_rectangle_int_t 	*extents)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -1294,7 +1297,8 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
                                            cairo_glyph_t        *glyphs,
                                            int			 num_glyphs,
                                            cairo_scaled_font_t  *scaled_font,
-					   int			*remaining_glyphs)
+					   int			*remaining_glyphs,
+					   cairo_rectangle_int_t *extents)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 05f5188..70af72b 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1566,7 +1566,8 @@ _cairo_win32_surface_show_glyphs (void			*surface,
 				  cairo_glyph_t		*glyphs,
 				  int			 num_glyphs,
 				  cairo_scaled_font_t	*scaled_font,
-				  int			*remaining_glyphs)
+				  int			*remaining_glyphs,
+				  cairo_rectangle_int_t *extents)
 {
 #if CAIRO_HAS_WIN32_FONT
     cairo_win32_surface_t *dst = surface;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 7efe828..c59694d 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -86,7 +86,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
 				 cairo_scaled_font_t *scaled_font,
-				 int		     *remaining_glyphs);
+				 int		     *remaining_glyphs,
+				 cairo_rectangle_int_t *extents);
 
 /*
  * Instead of taking two round trips for each blending request,
@@ -1283,7 +1284,7 @@ _cairo_xlib_surface_create_solid_pattern_surface (void                  *abstrac
 
     status = _cairo_surface_paint (&image->base,
 				   CAIRO_OPERATOR_SOURCE,
-				   &solid_pattern->base);
+				   &solid_pattern->base, NULL);
     if (status)
 	goto BAIL;
 
@@ -3966,7 +3967,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
 				 cairo_scaled_font_t *scaled_font,
-				 int		     *remaining_glyphs)
+				 int		     *remaining_glyphs,
+				 cairo_rectangle_int_t *extents)
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst;
diff --git a/src/cairoint.h b/src/cairoint.h
index f94e682..4e9eea4 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -726,13 +726,15 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*paint)			(void			*surface,
 				 cairo_operator_t	 op,
-				 const cairo_pattern_t	*source);
+				 const cairo_pattern_t	*source,
+				 cairo_rectangle_int_t  *extents);
 
     cairo_warn cairo_int_status_t
     (*mask)			(void			*surface,
 				 cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
-				 const cairo_pattern_t	*mask);
+				 const cairo_pattern_t	*mask,
+				 cairo_rectangle_int_t  *extents);
 
     cairo_warn cairo_int_status_t
     (*stroke)			(void			*surface,
@@ -743,7 +745,8 @@ struct _cairo_surface_backend {
 				 cairo_matrix_t		*ctm,
 				 cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
     cairo_warn cairo_int_status_t
     (*fill)			(void			*surface,
@@ -752,7 +755,8 @@ struct _cairo_surface_backend {
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
     cairo_warn cairo_int_status_t
     (*show_glyphs)		(void			*surface,
@@ -761,7 +765,8 @@ struct _cairo_surface_backend {
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
-				 int			*remaining_glyphs);
+				 int			*remaining_glyphs,
+				 cairo_rectangle_int_t	*extents);
 
     cairo_surface_t *
     (*snapshot)			(void			*surface);
@@ -788,7 +793,8 @@ struct _cairo_surface_backend {
 				 cairo_matrix_t		*stroke_ctm,
 				 cairo_matrix_t		*stroke_ctm_inverse,
 				 double			 stroke_tolerance,
-				 cairo_antialias_t	 stroke_antialias);
+				 cairo_antialias_t	 stroke_antialias,
+				 cairo_rectangle_int_t	*extents);
 
     cairo_surface_t *
     (*create_solid_pattern_surface)
@@ -809,7 +815,8 @@ struct _cairo_surface_backend {
 				 const cairo_text_cluster_t *clusters,
 				 int			     num_clusters,
 				 cairo_text_cluster_flags_t  cluster_flags,
-				 cairo_scaled_font_t	    *scaled_font);
+				 cairo_scaled_font_t	    *scaled_font,
+				 cairo_rectangle_int_t	    *extents);
 };
 
 #include "cairo-surface-private.h"
@@ -1734,13 +1741,15 @@ _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 cairo_private cairo_status_t
 _cairo_surface_paint (cairo_surface_t	*surface,
 		      cairo_operator_t	 op,
-		      const cairo_pattern_t *source);
+		      const cairo_pattern_t *source,
+		      cairo_rectangle_int_t  *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_mask (cairo_surface_t	*surface,
 		     cairo_operator_t	 op,
 		     const cairo_pattern_t	*source,
-		     const cairo_pattern_t	*mask);
+		     const cairo_pattern_t	*mask,
+		     cairo_rectangle_int_t      *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
@@ -1756,7 +1765,8 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 			    cairo_matrix_t	    *stroke_ctm,
 			    cairo_matrix_t	    *stroke_ctm_inverse,
 			    double		     stroke_tolerance,
-			    cairo_antialias_t	     stroke_antialias);
+			    cairo_antialias_t	     stroke_antialias,
+			    cairo_rectangle_int_t   *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_stroke (cairo_surface_t		*surface,
@@ -1767,7 +1777,8 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_matrix_t		*ctm,
 		       cairo_matrix_t		*ctm_inverse,
 		       double			 tolerance,
-		       cairo_antialias_t	 antialias);
+		       cairo_antialias_t	 antialias,
+		       cairo_rectangle_int_t    *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_fill (cairo_surface_t	*surface,
@@ -1776,7 +1787,8 @@ _cairo_surface_fill (cairo_surface_t	*surface,
 		     cairo_path_fixed_t	*path,
 		     cairo_fill_rule_t	 fill_rule,
 		     double		 tolerance,
-		     cairo_antialias_t	 antialias);
+		     cairo_antialias_t	 antialias,
+		     cairo_rectangle_int_t  *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
@@ -1789,7 +1801,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 const cairo_text_cluster_t *clusters,
 				 int			     num_clusters,
 				 cairo_text_cluster_flags_t  cluster_flags,
-				 cairo_scaled_font_t	    *scaled_font);
+				 cairo_scaled_font_t	    *scaled_font,
+				 cairo_rectangle_int_t      *extents);
 
 cairo_private cairo_status_t
 _cairo_surface_composite_trapezoids (cairo_operator_t	op,
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index f19cbd6..71700bd 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -194,26 +194,28 @@ _test_meta_surface_get_extents (void			*abstract_surface,
 static cairo_int_status_t
 _test_meta_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  const cairo_pattern_t	*source)
+			  const cairo_pattern_t	*source,
+			  cairo_rectangle_int_t *extents)
 {
     test_meta_surface_t *surface = abstract_surface;
 
     surface->image_reflects_meta = FALSE;
 
-    return _cairo_surface_paint (surface->meta, op, source);
+    return _cairo_surface_paint (surface->meta, op, source, extents);
 }
 
 static cairo_int_status_t
 _test_meta_surface_mask (void			*abstract_surface,
 			 cairo_operator_t	 op,
 			 const cairo_pattern_t	*source,
-			 const cairo_pattern_t	*mask)
+			 const cairo_pattern_t	*mask,
+			 cairo_rectangle_int_t  *extents)
 {
     test_meta_surface_t *surface = abstract_surface;
 
     surface->image_reflects_meta = FALSE;
 
-    return _cairo_surface_mask (surface->meta, op, source, mask);
+    return _cairo_surface_mask (surface->meta, op, source, mask, extents);
 }
 
 static cairo_int_status_t
@@ -225,7 +227,8 @@ _test_meta_surface_stroke (void				*abstract_surface,
 			   cairo_matrix_t		*ctm,
 			   cairo_matrix_t		*ctm_inverse,
 			   double			 tolerance,
-			   cairo_antialias_t		 antialias)
+			   cairo_antialias_t		 antialias,
+			   cairo_rectangle_int_t 	*extents)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -234,7 +237,7 @@ _test_meta_surface_stroke (void				*abstract_surface,
     return _cairo_surface_stroke (surface->meta, op, source,
 				  path, style,
 				  ctm, ctm_inverse,
-				  tolerance, antialias);
+				  tolerance, antialias, extents);
 }
 
 static cairo_int_status_t
@@ -244,7 +247,8 @@ _test_meta_surface_fill (void			*abstract_surface,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
-			 cairo_antialias_t	 antialias)
+			 cairo_antialias_t	 antialias,
+			 cairo_rectangle_int_t  *extents)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -252,7 +256,7 @@ _test_meta_surface_fill (void			*abstract_surface,
 
     return _cairo_surface_fill (surface->meta, op, source,
 				path, fill_rule,
-				tolerance, antialias);
+				tolerance, antialias, extents);
 }
 
 static cairo_bool_t
@@ -274,7 +278,8 @@ _test_meta_surface_show_text_glyphs (void		    *abstract_surface,
 				     const cairo_text_cluster_t *clusters,
 				     int		     num_clusters,
 				     cairo_text_cluster_flags_t cluster_flags,
-				     cairo_scaled_font_t    *scaled_font)
+				     cairo_scaled_font_t    *scaled_font,
+				     cairo_rectangle_int_t  *extents)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -284,7 +289,7 @@ _test_meta_surface_show_text_glyphs (void		    *abstract_surface,
 					    utf8, utf8_len,
 					    glyphs, num_glyphs,
 					    clusters, num_clusters, cluster_flags,
-					    scaled_font);
+					    scaled_font, extents);
 }
 
 
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index ba80a10..cfb87f3 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -169,28 +169,30 @@ _test_paginated_surface_get_extents (void			*abstract_surface,
 static cairo_int_status_t
 _test_paginated_surface_paint (void		*abstract_surface,
 			       cairo_operator_t	 op,
-			       const cairo_pattern_t	*source)
+			       const cairo_pattern_t	*source,
+			       cairo_rectangle_int_t *extents)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return CAIRO_STATUS_SUCCESS;
 
-    return _cairo_surface_paint (surface->target, op, source);
+    return _cairo_surface_paint (surface->target, op, source, extents);
 }
 
 static cairo_int_status_t
 _test_paginated_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
 			      const cairo_pattern_t	*source,
-			      const cairo_pattern_t	*mask)
+			      const cairo_pattern_t	*mask,
+			      cairo_rectangle_int_t     *extents)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return CAIRO_STATUS_SUCCESS;
 
-    return _cairo_surface_mask (surface->target, op, source, mask);
+    return _cairo_surface_mask (surface->target, op, source, mask, extents);
 }
 
 static cairo_int_status_t
@@ -202,7 +204,8 @@ _test_paginated_surface_stroke (void				*abstract_surface,
 				cairo_matrix_t			*ctm,
 				cairo_matrix_t			*ctm_inverse,
 				double				 tolerance,
-				cairo_antialias_t		 antialias)
+				cairo_antialias_t		 antialias,
+				cairo_rectangle_int_t           *extents)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -212,7 +215,7 @@ _test_paginated_surface_stroke (void				*abstract_surface,
     return _cairo_surface_stroke (surface->target, op, source,
 				  path, style,
 				  ctm, ctm_inverse,
-				  tolerance, antialias);
+				  tolerance, antialias, extents);
 }
 
 static cairo_int_status_t
@@ -222,7 +225,8 @@ _test_paginated_surface_fill (void				*abstract_surface,
 			      cairo_path_fixed_t		*path,
 			      cairo_fill_rule_t			 fill_rule,
 			      double				 tolerance,
-			      cairo_antialias_t			 antialias)
+			      cairo_antialias_t			 antialias,
+			      cairo_rectangle_int_t     	*extents)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -231,7 +235,7 @@ _test_paginated_surface_fill (void				*abstract_surface,
 
     return _cairo_surface_fill (surface->target, op, source,
 				path, fill_rule,
-				tolerance, antialias);
+				tolerance, antialias, extents);
 }
 
 static cairo_bool_t
@@ -253,7 +257,8 @@ _test_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
 					  cairo_text_cluster_flags_t cluster_flags,
-					  cairo_scaled_font_t	    *scaled_font)
+					  cairo_scaled_font_t	    *scaled_font,
+					  cairo_rectangle_int_t     *extents)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -264,7 +269,7 @@ _test_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					    utf8, utf8_len,
 					    glyphs, num_glyphs,
 					    clusters, num_clusters, cluster_flags,
-					    scaled_font);
+					    scaled_font, extents);
 }
 
 
commit ed2081d97401741db10b0244eaba7ff31ae63346
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 2 15:05:07 2008 +1030

    Specify a background color for XFAIL text
    
    To improve readability on terminals with a white background.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 11ca650..90ca0af 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -192,7 +192,7 @@ _cairo_test_init (cairo_test_context_t *ctx,
 #ifdef HAVE_UNISTD_H
     if (*fail_face == '\0' && isatty (2)) {
 	fail_face = "\033[41;37;1m";
-	xfail_face = "\033[33;1m";
+	xfail_face = "\033[43;37;1m";
 	normal_face = "\033[m";
 	if (isatty (1))
 	    print_fail_on_stdout = FALSE;


More information about the cairo-commit mailing list