[cairo-commit] 26 commits - src/cairo-analysis-surface.c src/cairo-array.c src/cairo.c src/cairo-cff-subset.c src/cairo-clip.c src/cairo-directfb-surface.c src/cairo-glitz-surface.c src/cairo-gstate.c src/cairo-image-surface.c src/cairoint.h src/cairo-matrix.c src/cairo-meta-surface.c src/cairo-paginated-surface.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-region.c src/cairo-scaled-font.c src/cairo-scaled-font-subsets.c src/cairo-sdl-surface.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-surface-fallback-private.h src/cairo-svg-surface.c src/cairo-traps.c src/cairo-type3-glyph-surface.c src/cairo-user-font.c src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-display.c src/cairo-xlib-private.h src/cairo-xlib-screen.c src/cairo-xlib-surface.c src/test-meta-surface.c src/test-paginated-surface.c test/.gitignore

Chris Wilson ickle at kemper.freedesktop.org
Thu Oct 30 11:01:33 PDT 2008


 src/cairo-analysis-surface.c         |   51 ++--
 src/cairo-array.c                    |   16 -
 src/cairo-cff-subset.c               |    8 
 src/cairo-clip.c                     |    4 
 src/cairo-directfb-surface.c         |   33 +--
 src/cairo-glitz-surface.c            |   42 +--
 src/cairo-gstate.c                   |  126 +++++++----
 src/cairo-image-surface.c            |    6 
 src/cairo-matrix.c                   |   79 ++++++-
 src/cairo-meta-surface.c             |   12 -
 src/cairo-paginated-surface.c        |   12 -
 src/cairo-pattern.c                  |  380 +++++++++++++++++------------------
 src/cairo-pdf-surface.c              |   96 +++++---
 src/cairo-ps-surface.c               |   43 ++-
 src/cairo-quartz-surface.c           |   10 
 src/cairo-region.c                   |    6 
 src/cairo-scaled-font-subsets.c      |    4 
 src/cairo-scaled-font.c              |    3 
 src/cairo-sdl-surface.c              |   22 +-
 src/cairo-surface-fallback-private.h |   45 ++--
 src/cairo-surface-fallback.c         |   65 +++--
 src/cairo-surface.c                  |  199 +++++++++++-------
 src/cairo-svg-surface.c              |   50 ++--
 src/cairo-traps.c                    |   33 +--
 src/cairo-type3-glyph-surface.c      |   18 -
 src/cairo-user-font.c                |    1 
 src/cairo-win32-font.c               |   26 +-
 src/cairo-win32-printing-surface.c   |   51 ++--
 src/cairo-win32-private.h            |    2 
 src/cairo-win32-surface.c            |    6 
 src/cairo-xcb-surface.c              |   42 +--
 src/cairo-xlib-display.c             |   19 +
 src/cairo-xlib-private.h             |   26 +-
 src/cairo-xlib-screen.c              |  100 ++++++---
 src/cairo-xlib-surface.c             |  108 +++++----
 src/cairo.c                          |    6 
 src/cairoint.h                       |   89 ++++----
 src/test-meta-surface.c              |   28 +-
 src/test-paginated-surface.c         |   40 +--
 test/.gitignore                      |    2 
 40 files changed, 1082 insertions(+), 827 deletions(-)

New commits:
commit cc109df2a70e953d71e3e6fc4e6e54cce4ba0d47
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 30 15:50:20 2008 +0000

    [test] Update .gitignore
    
    Add a couple of new programs to gitignore.

diff --git a/test/.gitignore b/test/.gitignore
index 9c8995d..8da34a0 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -160,6 +160,7 @@ pdf-surface-source.pdf
 png
 png-test.png
 png-flatten
+ps2png
 ps-features
 ps-features.ps
 ps-surface-source
@@ -236,6 +237,7 @@ unantialiased-shapes
 unbounded-operator
 user-data
 user-font
+user-font-mask
 user-font-proxy
 user-font-rescale
 xlib-expose-event
commit 7d546bba213c3b89404bb3c58a5665343abfcd51
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 29 15:46:10 2008 +0000

    [xlib] Eliminate shadowed variable.
    
    Cleanup a minor -Wshadow warning.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index e8e2dd3..0d79292 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -669,7 +669,8 @@ _get_image_surface (cairo_xlib_surface_t    *surface,
 	 * temporary pixmap
 	 */
 	Pixmap pixmap;
-	cairo_status_t status = _cairo_xlib_surface_ensure_gc (surface);
+
+	status = _cairo_xlib_surface_ensure_gc (surface);
 	if (status)
 	    return status;
 
commit e3388b8180e38f79e0d5b66cc640c3d5c37db2a8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 29 15:45:09 2008 +0000

    [cff-subset] Eliminate shadowed variable.
    
    Cleanup a minor -Wshadow warning.

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 008cc68..9a4e3d6 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -456,7 +456,7 @@ _cairo_dict_init_key (cff_dict_operator_t *key, int operator)
 static cairo_status_t
 cff_dict_create_operator (int            operator,
                           unsigned char *operand,
-                          int            operand_length,
+                          int            size,
 			  cff_dict_operator_t **out)
 {
     cff_dict_operator_t *op;
@@ -466,14 +466,14 @@ cff_dict_create_operator (int            operator,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_dict_init_key (op, operator);
-    op->operand = malloc (operand_length);
+    op->operand = malloc (size);
     if (op->operand == NULL) {
         free (op);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    memcpy (op->operand, operand, operand_length);
-    op->operand_length = operand_length;
+    memcpy (op->operand, operand, size);
+    op->operand_length = size;
     op->operand_offset = -1;
 
     *out = op;
commit 3e18114aff21acfa73a7d13a419719375ae9b5a6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 29 15:43:23 2008 +0000

    [user-font] Eliminate shadowed variable
    
    Cleanup a minor -Wshadow warning.

diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index ddcbc77..c272966 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -187,7 +187,6 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 
     if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
 	cairo_surface_t	*surface;
-	cairo_status_t status = CAIRO_STATUS_SUCCESS;
 	cairo_format_t format;
 	int width, height;
 
commit d073537e82b57738068a7e1cf1d36ce452876804
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 29 15:41:44 2008 +0000

    [scaled-font] Eliminate shadowed variable.
    
    Cleanup a minor -Wshadow warning.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 32fd62a..c3cf17a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1872,7 +1872,6 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
 	    _cairo_format_bits_per_pixel (glyph_surface->format) )
 	{
 	    cairo_surface_t *new_mask;
-	    cairo_surface_pattern_t mask_pattern;
 
 	    switch (glyph_surface->format) {
 	    case CAIRO_FORMAT_ARGB32:
commit 6429e3f39468ef4f865681b3b5988d35906deeb0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 28 17:38:09 2008 +0000

    [xlib] Only set Picture clip as necessary.
    
    Only set ClipRectangles on a new Picture, avoiding redundant calls to
    clear the non-existent ClipMask otherwise.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 34c86fd..e8e2dd3 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -888,8 +888,9 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t    *surface)
 						     surface->drawable,
 						     surface->xrender_format,
 						     0, NULL);
-	_cairo_xlib_surface_set_picture_clip_rects (surface);
-    } else if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE)
+    }
+
+    if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE)
 	_cairo_xlib_surface_set_picture_clip_rects (surface);
 }
 
commit cd45258c5bf6a06f7bd3f2bfaf928e423a9b70e1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 28 16:54:10 2008 +0000

    [xlib] Only clear the GC clip mask as necessary.
    
    Avoid redundant calls to XSetClipMask() for clean GCs.

diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 58edbeb..b9c84b8 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -152,9 +152,15 @@ cairo_private void
 _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
 
 cairo_private GC
-_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
+_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info,
+			   int depth,
+			   unsigned int *need_reset);
+
 cairo_private cairo_status_t
-_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
+_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info,
+			   int depth,
+			   GC gc,
+			   cairo_bool_t reset_clip);
 
 cairo_private cairo_font_options_t *
 _cairo_xlib_screen_get_font_options (cairo_xlib_screen_info_t *info);
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 65d131c..9dd411e 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -57,6 +57,8 @@
 #include "cairo-xlib-private.h"
 #include "cairo-xlib-xrender-private.h"
 
+#include "cairo-xlib-surface-private.h"
+
 #include <fontconfig/fontconfig.h>
 
 static int
@@ -404,7 +406,9 @@ depth_to_index (int depth)
 }
 
 GC
-_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
+_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info,
+			   int depth,
+			   unsigned int *dirty)
 {
     GC gc;
     cairo_bool_t needs_reset;
@@ -419,7 +423,7 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
     CAIRO_MUTEX_UNLOCK (info->mutex);
 
     if (needs_reset)
-	XSetClipMask(info->display->display, gc, None);
+	*dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
 
     return gc;
 }
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index d078dcd..34c86fd 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -900,7 +900,8 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
 
     if (surface->gc == NULL) {
 	surface->gc = _cairo_xlib_screen_get_gc (surface->screen_info,
-						 surface->depth);
+						 surface->depth,
+						 &surface->clip_dirty);
 	if (surface->gc == NULL) {
 	    gcv.graphics_exposures = False;
 	    surface->gc = XCreateGC (surface->dpy, surface->drawable,
@@ -908,9 +909,9 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
 	    if (!surface->gc)
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
+    }
 
-	_cairo_xlib_surface_set_gc_clip_rects (surface);
-    } else if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC)
+    if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC)
 	_cairo_xlib_surface_set_gc_clip_rects (surface);
 
     return CAIRO_STATUS_SUCCESS;
commit d384f864992fbf7513446a70158135a08e704678
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 28 16:33:51 2008 +0000

    [xlib] Propagate real status from get_screen_info().
    
    Return the real error from _cairo_xlib_screen_info_get() in order to avoid
    having to create a fake NO_MEMORY error.

diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index cd89290..58edbeb 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -138,8 +138,10 @@ cairo_private XRenderPictFormat *
 _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t	*display,
 	                                cairo_format_t		 format);
 
-cairo_private cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen);
+cairo_private cairo_status_t
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display,
+			     Screen *screen,
+			     cairo_xlib_screen_info_t **out);
 
 cairo_private cairo_xlib_screen_info_t *
 _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index a864fec..65d131c 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -318,15 +318,17 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
     free (info);
 }
 
-cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
+cairo_status_t
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display,
+			     Screen *screen,
+			     cairo_xlib_screen_info_t **out)
 {
     cairo_xlib_screen_info_t *info = NULL, **prev;
 
     CAIRO_MUTEX_LOCK (display->mutex);
     if (display->closed) {
 	CAIRO_MUTEX_UNLOCK (display->mutex);
-	return NULL;
+	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
     }
 
     for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
@@ -348,35 +350,41 @@ _cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
 	info = _cairo_xlib_screen_info_reference (info);
     } else {
 	info = malloc (sizeof (cairo_xlib_screen_info_t));
-	if (info != NULL) {
-	    CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
-	    CAIRO_MUTEX_INIT (info->mutex);
-	    info->display = _cairo_xlib_display_reference (display);
-	    info->screen = screen;
-	    info->has_render = FALSE;
-	    info->has_font_options = FALSE;
-	    memset (info->gc, 0, sizeof (info->gc));
-	    info->gc_needs_clip_reset = 0;
-
-	    _cairo_array_init (&info->visuals,
-			       sizeof (cairo_xlib_visual_info_t*));
-
-	    if (screen) {
-		Display *dpy = display->display;
-		int event_base, error_base;
-
-		info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
-			(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
-	    }
-
-	    CAIRO_MUTEX_LOCK (display->mutex);
-	    info->next = display->screens;
-	    display->screens = info;
-	    CAIRO_MUTEX_UNLOCK (display->mutex);
+	if (info == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
+	CAIRO_MUTEX_INIT (info->mutex);
+	info->display = _cairo_xlib_display_reference (display);
+	info->screen = screen;
+	info->has_render = FALSE;
+	info->has_font_options = FALSE;
+	memset (info->gc, 0, sizeof (info->gc));
+	info->gc_needs_clip_reset = 0;
+
+	_cairo_array_init (&info->visuals,
+			   sizeof (cairo_xlib_visual_info_t*));
+
+	if (screen) {
+	    Display *dpy = display->display;
+	    int event_base, error_base;
+
+	    info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
+		    (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
 	}
+
+	/* Small window of opportunity for two screen infos for the same
+	 * Screen - just wastes a little bit of memory but should not cause
+	 * any corruption.
+	 */
+	CAIRO_MUTEX_LOCK (display->mutex);
+	info->next = display->screens;
+	display->screens = info;
+	CAIRO_MUTEX_UNLOCK (display->mutex);
     }
 
-    return info;
+    *out = info;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static int
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 4d7e6a8..d078dcd 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2545,10 +2545,10 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     if (status)
 	return _cairo_surface_create_in_error (status);
 
-    screen_info = _cairo_xlib_screen_info_get (display, screen);
-    if (screen_info == NULL) {
+    status = _cairo_xlib_screen_info_get (display, screen, &screen_info);
+    if (status) {
 	_cairo_xlib_display_destroy (display);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	return _cairo_surface_create_in_error (status);
     }
 
     surface = malloc (sizeof (cairo_xlib_surface_t));
commit e25b106e9c33e220fb104afb0929e766647b6de9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 28 16:27:58 2008 +0000

    [xlib] Propagate real status from get_display()
    
    Avoid throwing away the error and inventing a new NO_MEMORY error for
    _cairo_xlib_display_get().

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 3c835f6..14e50d6 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -208,13 +208,15 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
     return 0;
 }
 
-cairo_xlib_display_t *
-_cairo_xlib_display_get (Display *dpy)
+cairo_status_t
+_cairo_xlib_display_get (Display *dpy,
+			 cairo_xlib_display_t **out)
 {
     cairo_xlib_display_t *display;
     cairo_xlib_display_t **prev;
     XExtCodes *codes;
     int render_major, render_minor;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     /* There is an apparent deadlock between this mutex and the
      * mutex for the display, but it's actually safe. For the
@@ -247,7 +249,7 @@ _cairo_xlib_display_get (Display *dpy)
 
     display = malloc (sizeof (cairo_xlib_display_t));
     if (display == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto UNLOCK;
     }
 
@@ -261,7 +263,7 @@ _cairo_xlib_display_get (Display *dpy)
 
     codes = XAddExtension (dpy);
     if (codes == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (display);
 	display = NULL;
 	goto UNLOCK;
@@ -316,7 +318,8 @@ _cairo_xlib_display_get (Display *dpy)
 
 UNLOCK:
     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
-    return display;
+    *out = display;
+    return status;
 }
 
 void
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 4b0a94d..cd89290 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -108,8 +108,8 @@ struct _cairo_xlib_screen_info {
     cairo_array_t visuals;
 };
 
-cairo_private cairo_xlib_display_t *
-_cairo_xlib_display_get (Display *display);
+cairo_private cairo_status_t
+_cairo_xlib_display_get (Display *display, cairo_xlib_display_t **out);
 
 cairo_private cairo_xlib_display_t *
 _cairo_xlib_display_reference (cairo_xlib_display_t *info);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index c898838..4d7e6a8 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2510,6 +2510,7 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     cairo_xlib_surface_t *surface;
     cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *screen_info;
+    cairo_status_t status;
 
     CAIRO_MUTEX_INITIALIZE ();
 
@@ -2540,9 +2541,9 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     if (depth == 0)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    status = _cairo_xlib_display_get (dpy, &display);
+    if (status)
+	return _cairo_surface_create_in_error (status);
 
     screen_info = _cairo_xlib_screen_info_get (display, screen);
     if (screen_info == NULL) {
@@ -3139,6 +3140,7 @@ _cairo_xlib_surface_font_init (Display		    *dpy,
 			       cairo_scaled_font_t  *scaled_font)
 {
     cairo_xlib_surface_font_private_t	*font_private;
+    cairo_status_t status;
     int i;
 
     font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
@@ -3146,10 +3148,10 @@ _cairo_xlib_surface_font_init (Display		    *dpy,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font_private->scaled_font = scaled_font;
-    font_private->display = _cairo_xlib_display_get (dpy);
-    if (font_private->display == NULL) {
+    status = _cairo_xlib_display_get (dpy, &font_private->display);
+    if (status) {
 	free (font_private);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return status;
     }
 
     /* initialize and hook into the CloseDisplay callback */
commit 2555f83b11ee23829cfdeaae703420ca3e572fa1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 28 16:22:49 2008 +0000

    [xlib] Avoid repeated calls to XRenderQueryVersion
    
    Use the value determined during display initialisation in order to avoid
    redundant XRenderQueryFormats requests.

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 5e6dba1..3c835f6 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -214,7 +214,7 @@ _cairo_xlib_display_get (Display *dpy)
     cairo_xlib_display_t *display;
     cairo_xlib_display_t **prev;
     XExtCodes *codes;
-    int major_unused, minor_unused;
+    int render_major, render_minor;
 
     /* There is an apparent deadlock between this mutex and the
      * mutex for the display, but it's actually safe. For the
@@ -257,7 +257,7 @@ _cairo_xlib_display_get (Display *dpy)
      * add our hook. For now, that means Render, so we call into its
      * QueryVersion function to ensure it gets initialized.
      */
-    XRenderQueryVersion (dpy, &major_unused, &minor_unused);
+    XRenderQueryVersion (dpy, &render_major, &render_minor);
 
     codes = XAddExtension (dpy);
     if (codes == NULL) {
@@ -279,6 +279,8 @@ _cairo_xlib_display_get (Display *dpy)
     display->close_display_hooks = NULL;
     display->closed = FALSE;
 
+    display->render_major = render_major;
+    display->render_minor = render_minor;
     memset (display->cached_xrender_formats, 0,
 	    sizeof (display->cached_xrender_formats));
 
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 79cd6b5..4b0a94d 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -64,6 +64,8 @@ struct _cairo_xlib_display {
     Display *display;
     cairo_xlib_screen_info_t *screens;
 
+    int render_major;
+    int render_minor;
     XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_A1 + 1];
 
     cairo_xlib_job_t *workqueue;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 154e89c..c898838 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2561,11 +2561,8 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     surface->close_display_hook.func = _cairo_xlib_surface_detach_display;
     _cairo_xlib_add_close_display_hook (display, &surface->close_display_hook);
 
-    if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
-	surface->render_major = -1;
-	surface->render_minor = -1;
-    }
-
+    surface->render_major = display->render_major;
+    surface->render_minor = display->render_minor;
     if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
 	if (!xrender_format) {
 	    if (visual) {
commit 0d0c6a199c5b631299c72dce80d66ac0f4936a64
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Oct 26 12:53:29 2008 +0000

    [matrix] Optimise invert for simple scaling|translation matrices.
    
    The matrix is quite often just a simple scale and translate (or even
    identity!). For this class of matrix, we can skip the full adjoint
    rearrangement and determinant calculation and just compute the inverse
    directly.

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 643c986..b644dec 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -525,9 +525,33 @@ _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
 cairo_status_t
 cairo_matrix_invert (cairo_matrix_t *matrix)
 {
-    /* inv (A) = 1/det (A) * adj (A) */
     double det;
 
+    /* Simple scaling|translation matrices are quite common... */
+    if (matrix->xy == 0. && matrix->yx == 0.) {
+	matrix->x0 = -matrix->x0;
+	matrix->y0 = -matrix->y0;
+
+	if (matrix->xx != 1.) {
+	    if (matrix->xx == 0.)
+		return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
+	    matrix->xx = 1. / matrix->xx;
+	    matrix->x0 *= matrix->xx;
+	}
+
+	if (matrix->yy != 1.) {
+	    if (matrix->yy == 0.)
+		return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
+	    matrix->yy = 1. / matrix->yy;
+	    matrix->y0 *= matrix->yy;
+	}
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    /* inv (A) = 1/det (A) * adj (A) */
     det = _cairo_matrix_compute_determinant (matrix);
 
     if (! ISFINITE (det))
commit 74876b00cd969d5cfc209fa903dfad50bda59361
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Oct 25 11:33:52 2008 +0100

    [xlib] Exploit compaction of XRenderFillRectangle()
    
    libXrender amalgamates sequences of XRenderFillRectangle() into a single
    XRenderFillRectangles request (when permissible). Since it is common for a
    cairo application to draw rectangles individually in order to exploit fast
    paths within cairo [rectilinear fills], it is a reasonably common pattern.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 6439cb1..154e89c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1931,27 +1931,41 @@ _cairo_xlib_surface_fill_rectangles (void		     *abstract_surface,
     render_color.blue  = color->blue_short;
     render_color.alpha = color->alpha_short;
 
-    if (num_rects > ARRAY_LENGTH (static_xrects)) {
-        xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle));
-	if (xrects == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
+    _cairo_xlib_surface_ensure_dst_picture (surface);
+    if (num_rects == 1) {
+	/* Take advantage of the protocol compaction that libXrender performs
+	 * to amalgamate sequences of XRenderFillRectangle().
+	 */
+	XRenderFillRectangle (surface->dpy,
+			      _render_operator (op),
+			      surface->dst_picture,
+			      &render_color,
+			      rects->x,
+			      rects->y,
+			      rects->width,
+			      rects->height);
+    } else {
+	if (num_rects > ARRAY_LENGTH (static_xrects)) {
+	    xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle));
+	    if (xrects == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
 
-    for (i = 0; i < num_rects; i++) {
-        xrects[i].x = rects[i].x;
-        xrects[i].y = rects[i].y;
-        xrects[i].width = rects[i].width;
-        xrects[i].height = rects[i].height;
-    }
+	for (i = 0; i < num_rects; i++) {
+	    xrects[i].x = rects[i].x;
+	    xrects[i].y = rects[i].y;
+	    xrects[i].width = rects[i].width;
+	    xrects[i].height = rects[i].height;
+	}
 
-    _cairo_xlib_surface_ensure_dst_picture (surface);
-    XRenderFillRectangles (surface->dpy,
-			   _render_operator (op),
-			   surface->dst_picture,
-			   &render_color, xrects, num_rects);
+	XRenderFillRectangles (surface->dpy,
+			       _render_operator (op),
+			       surface->dst_picture,
+			       &render_color, xrects, num_rects);
 
-    if (xrects != static_xrects)
-        free (xrects);
+	if (xrects != static_xrects)
+	    free (xrects);
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
commit 64726ccfb99ba964420f3a840fd707998927e902
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 24 17:06:04 2008 +0100

    [traps] Whitespace.
    
    Fixup whitespace in line with CODING_STYLE and rest of file.

diff --git a/src/cairo-region.c b/src/cairo-region.c
index 23a042f..a89c4d0 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -62,8 +62,8 @@ _cairo_region_init_boxes (cairo_region_t *region,
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     int i;
 
-    if (count > ARRAY_LENGTH(stack_pboxes)) {
-	pboxes = _cairo_malloc_ab (count, sizeof(pixman_box32_t));
+    if (count > ARRAY_LENGTH (stack_pboxes)) {
+	pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
 	if (pboxes == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
@@ -75,7 +75,7 @@ _cairo_region_init_boxes (cairo_region_t *region,
 	pboxes[i].y2 = boxes[i].p2.y;
     }
 
-    if (!pixman_region32_init_rects (&region->rgn, pboxes, count))
+    if (! pixman_region32_init_rects (&region->rgn, pboxes, count))
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (pboxes != stack_pboxes)
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index b76e908..4fa3656 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -615,18 +615,25 @@ _cairo_traps_extract_region (const cairo_traps_t  *traps,
     int i, box_count;
     cairo_int_status_t status;
 
-    for (i = 0; i < traps->num_traps; i++)
-	if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
-	      && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
-	      && _cairo_fixed_is_integer(traps->traps[i].top)
-	      && _cairo_fixed_is_integer(traps->traps[i].bottom)
-	      && _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
-	      && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
+    if (traps->num_traps == 0) {
+	_cairo_region_init (region);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    for (i = 0; i < traps->num_traps; i++) {
+	if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
+	    traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
+	    ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
+	    ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
+	    ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
+	    ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
+	{
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
+    }
 
-    if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) {
-	boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t));
+    if (traps->num_traps > ARRAY_LENGTH (stack_boxes)) {
+	boxes = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_box_int_t));
 
 	if (boxes == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -635,10 +642,10 @@ _cairo_traps_extract_region (const cairo_traps_t  *traps,
     box_count = 0;
 
     for (i = 0; i < traps->num_traps; i++) {
-	int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
-	int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
-	int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
-	int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);
+	int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
+	int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
+	int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
+	int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
 
 	/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
 	 * skip these.
commit d5543005e7b7cc08f97578f301182ef4807a05fe
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 24 09:00:45 2008 +0100

    [surface] Only copy font options if the target surface has them.
    
    No need to copy font options if the similar surface is from the same
    backend and no special options have been applied by the user. Doing so
    breaks lazy initialisation of backend specific options.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 4041790..ff75cc2 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -229,9 +229,6 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
 				       int		height)
 {
     cairo_surface_t *surface = NULL;
-    cairo_font_options_t options;
-
-    cairo_format_t format = _cairo_format_from_content (content);
 
     if (other->status)
 	return _cairo_surface_create_in_error (other->status);
@@ -242,15 +239,22 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
 	    return surface;
     }
 
-    if (surface == NULL)
-	surface = cairo_image_surface_create (format, width, height);
+    if (surface == NULL) {
+	surface =
+	    cairo_image_surface_create (_cairo_format_from_content (content),
+					width, height);
+    }
 
     /* If any error occurred, then return the nil surface we received. */
     if (surface->status)
 	return surface;
 
-    cairo_surface_get_font_options (other, &options);
-    _cairo_surface_set_font_options (surface, &options);
+    if (other->has_font_options || other->backend != surface->backend) {
+	cairo_font_options_t options;
+
+	cairo_surface_get_font_options (other, &options);
+	_cairo_surface_set_font_options (surface, &options);
+    }
 
     cairo_surface_set_fallback_resolution (surface,
 					   other->x_fallback_resolution,
commit a0023758104b700751ba8d7a66d75db139eea6cb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 24 08:39:29 2008 +0100

    [xlib] Defer querying of font options until first use
    
    Constructing the font options cause the initialisation of Xlc and invoke
    several round-trips to the X server, significantly delaying the creation
    of the first surface. By deferring that operation until the first use of
    fonts then we avoid that overhead for very simple applications (like the
    test suite) and should improve start-up latency for larger application.

diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index e381e58..79cd6b5 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -97,6 +97,7 @@ struct _cairo_xlib_screen_info {
     Screen *screen;
     cairo_bool_t has_render;
 
+    cairo_bool_t has_font_options;
     cairo_font_options_t font_options;
 
     GC gc[9];
@@ -151,6 +152,9 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
 cairo_private cairo_status_t
 _cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
 
+cairo_private cairo_font_options_t *
+_cairo_xlib_screen_get_font_options (cairo_xlib_screen_info_t *info);
+
 cairo_private cairo_status_t
 _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
 				    Visual *visual,
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index f670b8a..a864fec 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -144,7 +144,8 @@ get_integer_default (Display    *dpy,
 #endif
 
 static void
-_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
+_cairo_xlib_init_screen_font_options (Display *dpy,
+				      cairo_xlib_screen_info_t *info)
 {
     cairo_bool_t xft_hinting;
     cairo_bool_t xft_antialias;
@@ -353,7 +354,7 @@ _cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
 	    info->display = _cairo_xlib_display_reference (display);
 	    info->screen = screen;
 	    info->has_render = FALSE;
-	    _cairo_font_options_init_default (&info->font_options);
+	    info->has_font_options = FALSE;
 	    memset (info->gc, 0, sizeof (info->gc));
 	    info->gc_needs_clip_reset = 0;
 
@@ -366,7 +367,6 @@ _cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
 
 		info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
 			(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
-		_cairo_xlib_init_screen_font_options (dpy, info);
 	    }
 
 	    CAIRO_MUTEX_LOCK (display->mutex);
@@ -502,3 +502,25 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
     *out = ret;
     return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_font_options_t *
+_cairo_xlib_screen_get_font_options (cairo_xlib_screen_info_t *info)
+{
+    if (info->has_font_options)
+	return &info->font_options;
+
+    CAIRO_MUTEX_LOCK (info->mutex);
+    if (! info->has_font_options) {
+	Display *dpy = info->display->display;
+
+	_cairo_font_options_init_default (&info->font_options);
+
+	if (info->screen != NULL)
+	    _cairo_xlib_init_screen_font_options (dpy, info);
+
+	info->has_font_options = TRUE;
+    }
+    CAIRO_MUTEX_UNLOCK (info->mutex);
+
+    return &info->font_options;
+}
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 1d35843..6439cb1 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2348,7 +2348,7 @@ _cairo_xlib_surface_get_font_options (void                  *abstract_surface,
 {
     cairo_xlib_surface_t *surface = abstract_surface;
 
-    *options = surface->screen_info->font_options;
+    *options = *_cairo_xlib_screen_get_font_options (surface->screen_info);
 }
 
 static void
commit 6706590d4e7ad19dae0b8e3efe6f573d5688e19a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 29 16:22:48 2008 +0100

    [pattern] Reduce likelihood of range overflow with large downscaling.
    
    Exploit the auxiliary offset vector in the attributes to reduce
    likelihood of range overflow in the translation components when converting
    the pattern matrix to fixed-point pixman_matrix_t.
    
    An example of this is bug 9148
      Bug 9148 - invalid rendering when painting large scaled-down surfaces
      (https://bugs.freedesktop.org/show_bug.cgi?id=9148)
    but the issue is perhaps even more likely with high resolution fallback
    images.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index e58b96c..02b0674 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1989,6 +1989,25 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pat
 	}
     }
 
+    /* reduce likelihood of range overflow with large downscaling */
+    if (! is_identity) {
+	cairo_matrix_t m;
+	cairo_status_t invert_status;
+
+	m = attr->matrix;
+	invert_status = cairo_matrix_invert (&m);
+	assert (invert_status == CAIRO_STATUS_SUCCESS);
+
+	if (m.x0 != 0. || m.y0 != 0.) {
+	    x = floor (m.x0);
+	    y = floor (m.y0);
+	    attr->x_offset -= x;
+	    attr->y_offset -= y;
+	    cairo_matrix_init_translate (&m, x, y);
+	    cairo_matrix_multiply (&attr->matrix, &m, &attr->matrix);
+	}
+    }
+
   BAIL:
     cairo_surface_destroy (surface);
     return status;
commit c0af8c70635d641fc5770afc0cd6e9285122fd72
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Oct 20 16:49:23 2008 +0100

    [pattern] Tweak REFLECT HACK
    
    In order to workaound a directfb bug, tweak the reflect->repeat pattern so
    that it covers the destination rectangle. Although the number of paint()
    increases, the number of read/written pixels remain the same so that
    performance should not deteriorate, but instead be improved by using a
    cloned source. The early return of the REFLECT surface is discarded so
    that the latter optimisations for surface sources can be applied. One side
    effect of this is that acquire_source_image() is removed due to its lax
    reference counting which thereby exposes the ROI optimisations for image
    destinations as well.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 8113ff9..e58b96c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1359,7 +1359,6 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
 	attr->matrix = matrix;
 	attr->extend = pattern->base.extend;
 	attr->filter = CAIRO_FILTER_NEAREST;
-	attr->acquired = FALSE;
 
 	*out = &image->base;
 
@@ -1450,7 +1449,6 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
     cairo_matrix_init_identity (&attr->matrix);
     attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
     attr->filter = CAIRO_FILTER_NEAREST;
-    attr->acquired = FALSE;
 
     return status;
 }
@@ -1601,7 +1599,6 @@ NOCACHE:
     cairo_matrix_init_identity (&attribs->matrix);
     attribs->extend = CAIRO_EXTEND_REPEAT;
     attribs->filter = CAIRO_FILTER_NEAREST;
-    attribs->acquired = FALSE;
 
     status = CAIRO_STATUS_SUCCESS;
 
@@ -1778,31 +1775,36 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pat
 					    cairo_surface_t	       **out,
 					    cairo_surface_attributes_t *attr)
 {
-    cairo_int_status_t status;
+    cairo_surface_t *surface;
+    cairo_rectangle_int_t extents;
+    cairo_rectangle_int_t sampled_area;
+    double x1, y1, x2, y2;
     int tx, ty;
     double pad;
+    cairo_bool_t is_identity;
+    cairo_bool_t is_empty;
+    cairo_int_status_t status;
 
-    attr->acquired = FALSE;
+    surface = cairo_surface_reference (pattern->surface);
 
+    is_identity = FALSE;
+    attr->matrix = pattern->base.matrix;
     attr->extend = pattern->base.extend;
     attr->filter = _cairo_pattern_analyze_filter (pattern, &pad);
 
-    if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
-					      &tx, &ty))
-    {
+    attr->x_offset = attr->y_offset = tx = ty = 0;
+    if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
 	cairo_matrix_init_identity (&attr->matrix);
 	attr->x_offset = tx;
 	attr->y_offset = ty;
-    }
-    else if (attr->filter == CAIRO_FILTER_NEAREST)
-    {
+	is_identity = TRUE;
+    } else if (attr->filter == CAIRO_FILTER_NEAREST) {
 	/*
 	 * For NEAREST, we can remove the fractional translation component
 	 * from the transformation - this ensures that the pattern will always
 	 * hit fast-paths in the backends for simple transformations that
 	 * become (almost) identity, without loss of quality.
 	 */
-	attr->matrix = pattern->base.matrix;
 	attr->matrix.x0 = 0;
 	attr->matrix.y0 = 0;
 	if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
@@ -1816,15 +1818,12 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pat
 	    attr->matrix.y0 = pattern->base.matrix.y0;
 	}
 
-	attr->x_offset = attr->y_offset = 0;
-	tx = ty = 0;
-    }
-    else
-    {
-	attr->matrix = pattern->base.matrix;
-	attr->x_offset = attr->y_offset = 0;
-	tx = 0;
-	ty = 0;
+	if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
+	    cairo_matrix_init_identity (&attr->matrix);
+	    attr->x_offset = tx;
+	    attr->y_offset = ty;
+	    is_identity = TRUE;
+	}
     }
 
     /* XXX: Hack:
@@ -1833,156 +1832,165 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pat
      * an image twice bigger on each side, and create a pattern of four
      * images such that the new image, when repeated, has the same effect
      * of reflecting the original pattern.
-     *
-     * This is because the reflect support in pixman is broken and we
-     * pass repeat instead of reflect to pixman.  See
-     * _cairo_image_surface_set_attributes() for that.
      */
     if (attr->extend == CAIRO_EXTEND_REFLECT) {
 	cairo_t *cr;
-	int w,h;
+	cairo_surface_t *src;
+	int w, h;
 
-	cairo_rectangle_int_t extents;
-	status = _cairo_surface_get_extents (pattern->surface, &extents);
+	status = _cairo_surface_get_extents (surface, &extents);
 	if (status)
-	    return status;
+	    goto BAIL;
 
-	attr->extend = CAIRO_EXTEND_REPEAT;
+	status = _cairo_surface_clone_similar (dst, pattern->surface,
+					       extents.x, extents.y,
+					       extents.width, extents.height,
+					       &extents.x, &extents.y, &src);
+	if (status)
+	    goto BAIL;
 
-	/* TODO: Instead of rendering pattern->surface four times to
-	 * out, we should first copy pattern->surface to surface similar
-	 * to dst and then copy that four times to out.  This may cause
-	 * an extra copy in the case of image destination, but for X servers,
-	 * this will send pattern->surface just once over the wire instead
-	 * of current four.
-	 */
-	x = extents.x;
-	y = extents.y;
 	w = 2 * extents.width;
 	h = 2 * extents.height;
 
-	*out = cairo_surface_create_similar (dst, dst->content, w, h);
-	status = cairo_surface_status (*out);
-	if (status) {
-	    cairo_surface_destroy (*out);
-	    *out = NULL;
-	    return status;
+	if (is_identity) {
+	    attr->x_offset = -x;
+	    x += tx;
+	    while (x <= -w)
+		x += w;
+	    while (x >= w)
+		x -= w;
+	    extents.x += x;
+	    tx = x = 0;
+
+	    attr->y_offset = -y;
+	    y += ty;
+	    while (y <= -h)
+		y += h;
+	    while (y >= h)
+		y -= h;
+	    extents.y += y;
+	    ty = y = 0;
 	}
 
-	(*out)->device_transform = pattern->surface->device_transform;
-	(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
+	cairo_surface_destroy (surface);
+	surface = cairo_surface_create_similar (dst, dst->content, w, h);
+	if (surface->status) {
+	    cairo_surface_destroy (src);
+	    return surface->status;
+	}
+
+	surface->device_transform = pattern->surface->device_transform;
+	surface->device_transform_inverse = pattern->surface->device_transform_inverse;
 
-	cr = cairo_create (*out);
+	cr = cairo_create (surface);
 
-	cairo_set_source_surface (cr, pattern->surface, -x, -y);
+	cairo_set_source_surface (cr, src, -extents.x, -extents.y);
 	cairo_paint (cr);
 
 	cairo_scale (cr, -1, +1);
-	cairo_set_source_surface (cr, pattern->surface, x-w, -y);
+	cairo_set_source_surface (cr, src, extents.x-w, -extents.y);
+	cairo_paint (cr);
+	cairo_set_source_surface (cr, src, extents.x, -extents.y);
 	cairo_paint (cr);
 
 	cairo_scale (cr, +1, -1);
-	cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
+	cairo_set_source_surface (cr, src, extents.x-w, extents.y-h);
+	cairo_paint (cr);
+	cairo_set_source_surface (cr, src, extents.x, extents.y-h);
+	cairo_paint (cr);
+	cairo_set_source_surface (cr, src, extents.x-w, extents.y);
+	cairo_paint (cr);
+	cairo_set_source_surface (cr, src, extents.x, extents.y);
 	cairo_paint (cr);
 
 	cairo_scale (cr, -1, +1);
-	cairo_set_source_surface (cr, pattern->surface, -x, y-h);
+	cairo_set_source_surface (cr, src, -extents.x, extents.y-h);
+	cairo_paint (cr);
+	cairo_set_source_surface (cr, src, -extents.x, extents.y);
 	cairo_paint (cr);
 
 	status = cairo_status (cr);
 	cairo_destroy (cr);
 
-	if (status) {
-	    cairo_surface_destroy (*out);
-	    *out = NULL;
-	}
+	cairo_surface_destroy (src);
 
-	return status;
+	if (status)
+	    goto BAIL;
+
+	attr->extend = CAIRO_EXTEND_REPEAT;
     }
 
-    if (_cairo_surface_is_image (dst)) {
-	cairo_image_surface_t *image;
+    status = _cairo_surface_get_extents (surface, &extents);
+    if (status)
+	goto BAIL;
 
-	status = _cairo_surface_acquire_source_image (pattern->surface,
-						      &image,
-						      &attr->extra);
-	if (status)
-	    return status;
+    /* We first transform the rectangle to the coordinate space of the
+     * source surface so that we only need to clone that portion of the
+     * surface that will be read.
+     */
+    x1 = x;
+    y1 = y;
+    x2 = x + (int) width;
+    y2 = y + (int) height;
+    if (! is_identity) {
+	_cairo_matrix_transform_bounding_box (&attr->matrix,
+					      &x1, &y1, &x2, &y2,
+					      NULL);
+    }
 
-	*out = &image->base;
-	attr->acquired = TRUE;
-    } else {
-	cairo_rectangle_int_t extents;
-	cairo_bool_t is_empty;
+    sampled_area.x = floor (x1 - pad);
+    sampled_area.y = floor (y1 - pad);
+    sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
+    sampled_area.height = ceil (y2 + pad) - sampled_area.y;
 
-	status = _cairo_surface_get_extents (pattern->surface, &extents);
-	if (status)
-	    return status;
+    sampled_area.x += tx;
+    sampled_area.y += ty;
 
-	/* If we're repeating, we just play it safe and clone the
-	 * entire surface - i.e. we use the existing extents.
-	 */
-	if (attr->extend != CAIRO_EXTEND_REPEAT) {
-	    cairo_rectangle_int_t sampled_area;
+    if (attr->extend != CAIRO_EXTEND_REPEAT) {
+	/* Never acquire a larger area than the source itself */
+	is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
+    } else {
+	if (sampled_area.x >= extents.x &&
+	    sampled_area.y >= extents.y &&
+	    sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width &&
+	    sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
+	{
+	    /* source is wholly contained within extents, drop the REPEAT */
+	    extents = sampled_area;
+	    attr->extend = CAIRO_EXTEND_NONE;
+	}
 
-	    /* Otherwise, we first transform the rectangle to the
-	     * coordinate space of the source surface so that we can
-	     * clone only that portion of the surface that will be
-	     * read.
-	     */
-	    if (_cairo_matrix_is_identity (&attr->matrix)) {
-		sampled_area.x = x;
-		sampled_area.y = y;
-		sampled_area.width  = width;
-		sampled_area.height = height;
-	    } else {
-		double x1 = x;
-		double y1 = y;
-		double x2 = x + (int) width;
-		double y2 = y + (int) height;
-
-		_cairo_matrix_transform_bounding_box  (&attr->matrix,
-						       &x1, &y1, &x2, &y2,
-						       NULL);
-
-		sampled_area.x = floor (x1 - pad);
-		sampled_area.y = floor (y1 - pad);
-		sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
-		sampled_area.height = ceil (y2 + pad) - sampled_area.y;
+	is_empty = extents.width == 0 || extents.height == 0;
+    }
 
-	    }
+    /* XXX can we use is_empty? */
 
-	    sampled_area.x += tx;
-	    sampled_area.y += ty;
+    status = _cairo_surface_clone_similar (dst, surface,
+					   extents.x, extents.y,
+					   extents.width, extents.height,
+					   &x, &y, out);
+    if (status)
+	goto BAIL;
 
-	    /* Never acquire a larger area than the source itself */
-	    is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
-	}
+    if (x != 0 || y != 0) {
+	if (is_identity) {
+	    attr->x_offset -= x;
+	    attr->y_offset -= y;
+	} else {
+	    cairo_matrix_t m;
 
-	/* XXX can we use is_empty? */
+	    x -= attr->x_offset;
+	    y -= attr->y_offset;
+	    attr->x_offset = 0;
+	    attr->y_offset = 0;
 
-	status = _cairo_surface_clone_similar (dst, pattern->surface,
-					       extents.x, extents.y,
-					       extents.width, extents.height,
-					       &x, &y, out);
-	if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) {
-	    if (_cairo_matrix_is_identity (&attr->matrix)) {
-		attr->x_offset -= x;
-		attr->y_offset -= y;
-	    } else {
-		cairo_matrix_t m;
-
-		x -= attr->x_offset;
-		y -= attr->y_offset;
-		attr->x_offset = 0;
-		attr->y_offset = 0;
-
-		cairo_matrix_init_translate (&m, -x, -y);
-		cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
-	    }
+	    cairo_matrix_init_translate (&m, -x, -y);
+	    cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
 	}
     }
 
+  BAIL:
+    cairo_surface_destroy (surface);
     return status;
 }
 
@@ -2020,7 +2028,6 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 
     if (pattern->status) {
 	*surface_out = NULL;
-	attributes->acquired = FALSE;
 	return pattern->status;
     }
 
@@ -2103,21 +2110,7 @@ _cairo_pattern_release_surface (const cairo_pattern_t *pattern,
 				cairo_surface_t		   *surface,
 				cairo_surface_attributes_t *attributes)
 {
-    if (attributes->acquired)
-    {
-	const cairo_surface_pattern_t *surface_pattern;
-
-	assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
-	surface_pattern = (const cairo_surface_pattern_t *) pattern;
-
-	_cairo_surface_release_source_image (surface_pattern->surface,
-					     (cairo_image_surface_t *) surface,
-					     attributes->extra);
-    }
-    else
-    {
-	cairo_surface_destroy (surface);
-    }
+    cairo_surface_destroy (surface);
 }
 
 cairo_int_status_t
diff --git a/src/cairoint.h b/src/cairoint.h
index 4340dbd..2810348 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -915,7 +915,6 @@ typedef struct _cairo_surface_attributes {
     cairo_filter_t filter;
     int		   x_offset;
     int		   y_offset;
-    cairo_bool_t   acquired;
     void	   *extra;
 } cairo_surface_attributes_t;
 
commit 234623b3d5884b02a0619de8ddd57bbed36ef4fd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 14:55:26 2008 +0100

    [pattern] Support unbounded surfaces.
    
    An unbounded surface should just report an infinite pattern extent and not
    return UNSUPPORTED from _cairo_pattern_get_extents().

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 5399fea..8113ff9 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2220,6 +2220,8 @@ _cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
 	double pad;
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	    goto UNBOUNDED;
 	if (status)
 	    return status;
 
@@ -2266,6 +2268,7 @@ _cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
      * horizontal/vertical linear gradients).
      */
 
+  UNBOUNDED:
     /* unbounded patterns -> 'infinite' extents */
     extents->x = CAIRO_RECT_INT_MIN;
     extents->y = CAIRO_RECT_INT_MIN;
commit 2836be6f7565684e86b3cc8a3d2db4ba690b3718
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 14:42:47 2008 +0100

    Cleanup 'status && status != UNSUPPORTED'
    
    Replace instances of 'status && status != UNSUPPORTED' with the more
    readable _cairo_status_is_error().

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 940c8a8..4337e92 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -116,7 +116,7 @@ _analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
     old_height = surface->height;
     old_clip = surface->current_clip;
     status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     surface->width = meta_extents.width;
@@ -339,7 +339,7 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -406,7 +406,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
     }
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -465,7 +465,7 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -534,7 +534,7 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -612,7 +612,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
@@ -695,7 +695,7 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 8a0d4db..93bc151 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -656,7 +656,7 @@ _cairo_clip_path_reapply_clip_path (cairo_clip_t      *clip,
 
     if (clip_path->prev) {
         status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev);
-	if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	if (_cairo_status_is_error (status))
 	    return status;
     }
 
@@ -709,7 +709,7 @@ _cairo_clip_init_deep_copy (cairo_clip_t    *clip,
 
         if (other->path) {
             status = _cairo_clip_path_reapply_clip_path (clip, other->path);
-	    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    if (_cairo_status_is_error (status))
 		goto BAIL;
         }
     }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 0154acd..4cad470 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3027,7 +3027,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t		*surface,
     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 	                                                font_subset, TRUE,
 							&to_unicode_stream);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     descriptor = _cairo_pdf_surface_new_object (surface);
@@ -3199,7 +3199,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 	                                                font_subset, FALSE,
 							&to_unicode_stream);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     descriptor = _cairo_pdf_surface_new_object (surface);
@@ -3356,7 +3356,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 	                                                font_subset, TRUE,
 							&to_unicode_stream);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
+    if (_cairo_status_is_error (status)) {
 	_cairo_truetype_subset_fini (&subset);
 	return status;
     }
@@ -3658,7 +3658,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 	                                                font_subset, FALSE,
 							&to_unicode_stream);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
+    if (_cairo_status_is_error (status)) {
 	free (widths);
 	return status;
     }
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3d7afb6..9e55e9f 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -577,7 +577,7 @@ _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t	*font_su
 
 
     status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
 #if CAIRO_HAS_FT_FONT
@@ -606,7 +606,7 @@ _cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subs
     cairo_status_t status;
 
     status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 066f637..815c4d8 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -342,7 +342,7 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
     status = _cairo_truetype_index_to_ucs4 (scaled_font,
 					    scaled_font_glyph_index,
 					    &unicode);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4) {
@@ -722,7 +722,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 					     &scaled_glyph);
 	_cairo_scaled_font_thaw_cache (scaled_font);
     }
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
         return status;
 
     if (status == CAIRO_STATUS_SUCCESS &&
commit 13ba43eb8ffc3bb6c8881d91824102a8df86d928
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 12:28:25 2008 +0100

    [matrix] Optimize finding the bounding box under an orthogonal matrix.
    
    We frequently need to find the bounds of a pattern under an identity
    matrix, or a simple scale+translation. For these cases we do not need to
    transform each corner and search for the bounds as the matrix is x/y
    separable and so allows us to inspect the results for the extreme x/y
    points independently.

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index f01353e..643c986 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -371,6 +371,46 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
     double min_x, max_x;
     double min_y, max_y;
 
+    if (_cairo_matrix_is_identity (matrix)) {
+	if (is_tight)
+	    *is_tight = TRUE;
+
+	return;
+    }
+
+    if (matrix->xy == 0. && matrix->yx == 0.) {
+	/* non-rotation/skew matrix, just map the two extreme points */
+	quad_x[0] = *x1;
+	quad_y[0] = *y1;
+	cairo_matrix_transform_distance (matrix, &quad_x[0], &quad_y[0]);
+
+	quad_x[1] = *x2;
+	quad_y[1] = *y2;
+	cairo_matrix_transform_distance (matrix, &quad_x[1], &quad_y[1]);
+
+	if (quad_x[0] < quad_x[1]) {
+	    *x1 = quad_x[0] + matrix->x0;
+	    *x2 = quad_x[1] + matrix->x0;
+	} else {
+	    *x1 = quad_x[1] + matrix->x0;
+	    *x2 = quad_x[0] + matrix->x0;
+	}
+
+	if (quad_y[0] < quad_y[1]) {
+	    *y1 = quad_y[0] + matrix->y0;
+	    *y2 = quad_y[1] + matrix->y0;
+	} else {
+	    *y1 = quad_y[1] + matrix->y0;
+	    *y2 = quad_y[0] + matrix->y0;
+	}
+
+	if (is_tight)
+	    *is_tight = TRUE;
+
+	return;
+    }
+
+    /* general matrix */
     quad_x[0] = *x1;
     quad_y[0] = *y1;
     cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
@@ -406,7 +446,7 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
     *y1 = min_y;
     *x2 = max_x;
     *y2 = max_y;
-    
+
     if (is_tight) {
         /* it's tight if and only if the four corner points form an axis-aligned
            rectangle.
commit 6ed957fc242d7890117f4dea121c03ec2523470c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 22:02:05 2008 +0100

    [gstate] Use _cairo_pattern_black for the default source.
    
    Avoid allocating a default source pattern by using the static black pattern
    object. The one complication is that we need to ensure that the static
    pattern does leak to the application, so we replace it with an allocated
    solid pattern within _cairo_gstate_get_source().

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 051353f..7e56a77 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -103,8 +103,7 @@ _cairo_gstate_init (cairo_gstate_t  *gstate,
     gstate->ctm_inverse = gstate->ctm;
     gstate->source_ctm_inverse = gstate->ctm;
 
-    gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
-						  CAIRO_CONTENT_COLOR);
+    gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base;
 
     /* Now that the gstate is fully initialized and ready for the eventual
      * _cairo_gstate_fini(), we can check for errors (and not worry about
@@ -402,6 +401,12 @@ _cairo_gstate_set_source (cairo_gstate_t  *gstate,
 cairo_pattern_t *
 _cairo_gstate_get_source (cairo_gstate_t *gstate)
 {
+    if (gstate->source == &_cairo_pattern_black.base) {
+	/* do not expose the static object to the user */
+	gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
+						      CAIRO_CONTENT_COLOR);
+    }
+
     return gstate->source;
 }
 
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 516eec7..5399fea 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -31,7 +31,7 @@
 #include "cairoint.h"
 
 const cairo_solid_pattern_t _cairo_pattern_nil = {
-    { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
+    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
       CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
       CAIRO_STATUS_NO_MEMORY,		/* status */
       { 0, 0, 0, NULL },		/* user_data */
@@ -41,7 +41,7 @@ const cairo_solid_pattern_t _cairo_pattern_nil = {
 };
 
 static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
-    { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
+    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
       CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
       CAIRO_STATUS_NULL_POINTER,	/* status */
       { 0, 0, 0, NULL },		/* user_data */
@@ -50,14 +50,16 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
-const cairo_solid_pattern_t _cairo_pattern_none = {
-    { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
+const cairo_solid_pattern_t _cairo_pattern_black = {
+    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
       CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
       CAIRO_STATUS_SUCCESS,		/* status */
       { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       CAIRO_FILTER_DEFAULT,		/* filter */
-      CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
+      CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
+    { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
+    CAIRO_CONTENT_COLOR,                /* content */
 };
 
 /**
diff --git a/src/cairo.c b/src/cairo.c
index cefc925..2a9f746 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -651,7 +651,7 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
 	return;
 
     /* push the current pattern to the freed lists */
-    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none);
+    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
 
     pattern = cairo_pattern_create_rgb (red, green, blue);
     cairo_set_source (cr, pattern);
@@ -688,7 +688,7 @@ cairo_set_source_rgba (cairo_t *cr,
 	return;
 
     /* push the current pattern to the freed lists */
-    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none);
+    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
 
     pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
     cairo_set_source (cr, pattern);
@@ -731,7 +731,7 @@ cairo_set_source_surface (cairo_t	  *cr,
 	return;
 
     /* push the current pattern to the freed lists */
-    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none);
+    cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
 
     pattern = cairo_pattern_create_for_surface (surface);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 9e1cd7d..4340dbd 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -856,7 +856,7 @@ struct _cairo_solid_pattern {
 };
 
 extern const cairo_private cairo_solid_pattern_t _cairo_pattern_nil;
-extern const cairo_private cairo_solid_pattern_t _cairo_pattern_none;
+extern const cairo_private cairo_solid_pattern_t _cairo_pattern_black;
 
 typedef struct _cairo_surface_pattern {
     cairo_pattern_t base;
commit 794460186459981cd43ca38f3eba07e3f6bf8908
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 19:24:44 2008 +0100

    [pattern] Avoid needless copying of patterns.
    
    Only copy the pattern if we need to modify it, e.g. preserve a copy in a
    snapshot or a soft-mask, or to modify the matrix. Otherwise we can
    continue to use the original pattern and mark it as const in order to
    generate compiler warnings if we do attempt to write to it.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 057be52..940c8a8 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -96,10 +96,10 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
 
 static cairo_int_status_t
 _analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
-			       cairo_pattern_t		*pattern)
+			       const cairo_pattern_t *pattern)
 {
     cairo_surface_t *analysis = &surface->base;
-    cairo_surface_pattern_t *surface_pattern;
+    const cairo_surface_pattern_t *surface_pattern;
     cairo_status_t status;
     cairo_bool_t old_has_ctm;
     cairo_matrix_t old_ctm, p2d;
@@ -109,7 +109,7 @@ _analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
     int old_height;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
-    surface_pattern = (cairo_surface_pattern_t *) pattern;
+    surface_pattern = (const cairo_surface_pattern_t *) pattern;
     assert (_cairo_surface_is_meta (surface_pattern->surface));
 
     old_width = surface->width;
@@ -321,8 +321,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,
-			      cairo_pattern_t		*source)
+			       cairo_operator_t		op,
+			       const cairo_pattern_t		*source)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -362,8 +362,8 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_analysis_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
-			      cairo_pattern_t	*source,
-			      cairo_pattern_t	*mask)
+			      const cairo_pattern_t	*source,
+			      const cairo_pattern_t	*mask)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_int_status_t	      status, backend_status;
@@ -381,7 +381,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 	cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
 
 	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+	    const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source;
 	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
 		backend_source_status =
 		    _analyze_meta_surface_pattern (surface, source);
@@ -411,6 +411,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
@@ -438,7 +439,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 static cairo_int_status_t
 _cairo_analysis_surface_stroke (void			*abstract_surface,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
+				const cairo_pattern_t	*source,
 				cairo_path_fixed_t	*path,
 				cairo_stroke_style_t	*style,
 				cairo_matrix_t		*ctm,
@@ -510,7 +511,7 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_analysis_surface_fill (void			*abstract_surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
+			      const cairo_pattern_t	*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
@@ -578,7 +579,7 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_operator_t	   op,
-				     cairo_pattern_t	  *source,
+				     const cairo_pattern_t *source,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
 				     cairo_scaled_font_t  *scaled_font,
@@ -653,7 +654,7 @@ _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
 static cairo_int_status_t
 _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 					  cairo_operator_t	     op,
-					  cairo_pattern_t	    *source,
+					  const cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
@@ -897,18 +898,18 @@ typedef cairo_int_status_t
 typedef cairo_int_status_t
 (*_paint_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source);
+				 const cairo_pattern_t	*source);
 
 typedef cairo_int_status_t
 (*_mask_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
-				 cairo_pattern_t	*mask);
+				 const cairo_pattern_t	*source,
+				 const cairo_pattern_t	*mask);
 
 typedef cairo_int_status_t
 (*_stroke_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_stroke_style_t	*style,
 				 cairo_matrix_t		*ctm,
@@ -919,7 +920,7 @@ typedef cairo_int_status_t
 typedef cairo_int_status_t
 (*_fill_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
@@ -928,7 +929,7 @@ typedef cairo_int_status_t
 typedef cairo_int_status_t
 (*_show_glyphs_func)		(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index aa67b02..351e00d 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -702,8 +702,8 @@ _cairo_directfb_surface_clone_similar (void             *abstract_surface,
 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
-                             cairo_pattern_t             *src_pattern,
-                             cairo_pattern_t             *mask_pattern,
+                             const cairo_pattern_t       *src_pattern,
+                             const cairo_pattern_t       *mask_pattern,
                              cairo_operator_t             op,
                              int *src_x,             int *src_y,
                              int *mask_x,            int *mask_y,
@@ -732,7 +732,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
 
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
-	    cairo_pattern_t *tmp;
+	    const cairo_pattern_t *tmp;
 	    int              tmp_x, tmp_y;
 
 	    if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
@@ -761,11 +761,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
 	color = _cairo_stock_color (CAIRO_STOCK_WHITE);
     }
 
-    /* XXX DirectFB currently does not support filtering, so force NEAREST
-     * in order to hit optimisations inside core.
-    */
-    src_pattern->filter = CAIRO_FILTER_NEAREST;
-
     status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
 					     *src_x, *src_y, width, height,
 					     (cairo_surface_t **) &src,
@@ -842,7 +837,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
 
 static void
 _directfb_finish_composite (cairo_directfb_surface_t   *dst,
-                            cairo_pattern_t            *src_pattern,
+                            const cairo_pattern_t      *src_pattern,
                             cairo_surface_t            *src,
                             cairo_surface_attributes_t *src_attr)
 {
@@ -892,8 +887,8 @@ _directfb_categorize_operation (cairo_surface_attributes_t *src_attr)
 
 static cairo_int_status_t
 _cairo_directfb_surface_composite (cairo_operator_t  op,
-                                   cairo_pattern_t  *src_pattern,
-                                   cairo_pattern_t  *mask_pattern,
+                                   const cairo_pattern_t  *src_pattern,
+                                   const cairo_pattern_t  *mask_pattern,
                                    void             *abstract_dst,
                                    int  src_x,  int  src_y,
                                    int  mask_x, int  mask_y,
@@ -1160,7 +1155,7 @@ _cairo_directfb_surface_fill_rectangles (void                  *abstract_surface
 #if DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t   op,
-                                              cairo_pattern_t   *pattern,
+                                              const cairo_pattern_t   *pattern,
                                               void              *abstract_dst,
                                               cairo_antialias_t  antialias,
                                               int  src_x,   int  src_y,
@@ -1686,13 +1681,13 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
 }
 
 static cairo_int_status_t
-_cairo_directfb_surface_show_glyphs (void                *abstract_dst,
-                                     cairo_operator_t     op,
-                                     cairo_pattern_t     *pattern,
-                                     cairo_glyph_t       *glyphs,
-                                     int                  num_glyphs,
-                                     cairo_scaled_font_t *scaled_font,
-				     int		 *remaining_glyphs)
+_cairo_directfb_surface_show_glyphs (void		    *abstract_dst,
+                                     cairo_operator_t	     op,
+                                     const cairo_pattern_t  *pattern,
+                                     cairo_glyph_t	    *glyphs,
+                                     int		     num_glyphs,
+                                     cairo_scaled_font_t    *scaled_font,
+				     int		    *remaining_glyphs)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 784bff9..5bdfa70 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -718,7 +718,7 @@ typedef struct _cairo_glitz_surface_attributes {
 } cairo_glitz_surface_attributes_t;
 
 static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surface (cairo_pattern_t	              *pattern,
+_cairo_glitz_pattern_acquire_surface (const cairo_pattern_t	       *pattern,
 				      cairo_glitz_surface_t	       *dst,
 				      int			       x,
 				      int			       y,
@@ -937,7 +937,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t	              *pattern,
 }
 
 static void
-_cairo_glitz_pattern_release_surface (cairo_pattern_t		      *pattern,
+_cairo_glitz_pattern_release_surface (const cairo_pattern_t	      *pattern,
 				      cairo_glitz_surface_t	      *surface,
 				      cairo_glitz_surface_attributes_t *attr)
 {
@@ -948,8 +948,8 @@ _cairo_glitz_pattern_release_surface (cairo_pattern_t		      *pattern,
 }
 
 static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t	                *src,
-				       cairo_pattern_t	                *mask,
+_cairo_glitz_pattern_acquire_surfaces (const cairo_pattern_t	       *src,
+				       const cairo_pattern_t	       *mask,
 				       cairo_glitz_surface_t	        *dst,
 				       int			        src_x,
 				       int			        src_y,
@@ -985,37 +985,31 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t	                *src,
 	_cairo_pattern_init_solid (&tmp, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
 	mask = NULL;
-    } else {
-	status = _cairo_pattern_init_copy (&tmp.base, src);
-	if (status)
-	    return status;
+	src = &tmp.base;
     }
 
-    status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+    status = _cairo_glitz_pattern_acquire_surface (src, dst,
 						   src_x, src_y,
 						   width, height,
 						   src_out, sattr);
 
-    _cairo_pattern_fini (&tmp.base);
+    if (src == &tmp.base)
+	_cairo_pattern_fini (&tmp.base);
 
     if (status)
 	return status;
 
     if (mask)
     {
-	status = _cairo_pattern_init_copy (&tmp.base, mask);
-	if (status)
-	    return status;
-
-	status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+	status = _cairo_glitz_pattern_acquire_surface (mask, dst,
 						       mask_x, mask_y,
 						       width, height,
 						       mask_out, mattr);
 
-	if (status)
-	    _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr);
-
-	_cairo_pattern_fini (&tmp.base);
+	if (status) {
+	    /* XXX src == &tmp.base -> invalid (currently inconsequential) */
+	    _cairo_glitz_pattern_release_surface (src, *src_out, sattr);
+	}
 
 	return status;
     }
@@ -1039,8 +1033,8 @@ _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t	      *surface,
 
 static cairo_int_status_t
 _cairo_glitz_surface_composite (cairo_operator_t op,
-				cairo_pattern_t  *src_pattern,
-				cairo_pattern_t  *mask_pattern,
+				const cairo_pattern_t *src_pattern,
+				const cairo_pattern_t *mask_pattern,
 				void		 *abstract_dst,
 				int		 src_x,
 				int		 src_y,
@@ -1197,7 +1191,7 @@ _cairo_glitz_surface_fill_rectangles (void		      *abstract_dst,
 
 static cairo_int_status_t
 _cairo_glitz_surface_composite_trapezoids (cairo_operator_t  op,
-					   cairo_pattern_t   *pattern,
+					   const cairo_pattern_t *pattern,
 					   void		     *abstract_dst,
 					   cairo_antialias_t antialias,
 					   int		     src_x,
@@ -1210,7 +1204,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t  op,
 					   int		     n_traps)
 {
     cairo_pattern_union_t	     tmp_src_pattern;
-    cairo_pattern_t		     *src_pattern;
+    const cairo_pattern_t	    *src_pattern;
     cairo_glitz_surface_attributes_t attributes;
     cairo_glitz_surface_t	     *dst = abstract_dst;
     cairo_glitz_surface_t	     *src;
@@ -2101,7 +2095,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
 static cairo_int_status_t
 _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
 				      cairo_operator_t     op,
-				      cairo_pattern_t     *pattern,
+				      const cairo_pattern_t *pattern,
 				      void		  *abstract_surface,
 				      int		   src_x,
 				      int		   src_y,
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index fe8d279..051353f 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -810,34 +810,53 @@ _cairo_gstate_path_extents (cairo_gstate_t     *gstate,
 
 static cairo_status_t
 _cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
-					cairo_pattern_t *pattern,
+					cairo_pattern_t **pattern,
 					cairo_pattern_t *original,
 					cairo_matrix_t  *ctm_inverse)
 {
-    cairo_surface_pattern_t *surface_pattern;
-    cairo_surface_t *surface;
     cairo_status_t status;
-
-    status = _cairo_pattern_init_copy (pattern, original);
-    if (status)
-	return status;
+    cairo_bool_t have_copy = FALSE;
 
     /* apply device_transform first so that it is transformed by ctm_inverse */
-    if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
+    if (original->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern;
+	cairo_surface_t *surface;
+
         surface_pattern = (cairo_surface_pattern_t *) original;
         surface = surface_pattern->surface;
-        if (_cairo_surface_has_device_transform (surface))
-            _cairo_pattern_transform (pattern, &surface->device_transform);
+
+	if (_cairo_surface_has_device_transform (surface)) {
+	    status = _cairo_pattern_init_copy (*pattern, original);
+	    if (status)
+		return status;
+
+	    have_copy = TRUE;
+
+	    _cairo_pattern_transform (*pattern, &surface->device_transform);
+	}
     }
 
-    _cairo_pattern_transform (pattern, ctm_inverse);
+    if (! _cairo_matrix_is_identity (ctm_inverse)) {
+	if (! have_copy) {
+	    status = _cairo_pattern_init_copy (*pattern, original);
+	    if (status)
+		return status;
+
+	    have_copy = TRUE;
+	}
+
+	_cairo_pattern_transform (*pattern, ctm_inverse);
+    }
+
+    if (! have_copy)
+	*pattern = original;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_gstate_copy_transformed_source (cairo_gstate_t  *gstate,
-				       cairo_pattern_t *pattern)
+_cairo_gstate_copy_transformed_source (cairo_gstate_t   *gstate,
+				       cairo_pattern_t **pattern)
 {
     return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
 					           gstate->source,
@@ -845,9 +864,9 @@ _cairo_gstate_copy_transformed_source (cairo_gstate_t  *gstate,
 }
 
 static cairo_status_t
-_cairo_gstate_copy_transformed_mask (cairo_gstate_t  *gstate,
-				     cairo_pattern_t *pattern,
-				     cairo_pattern_t *mask)
+_cairo_gstate_copy_transformed_mask (cairo_gstate_t   *gstate,
+				     cairo_pattern_t **pattern,
+				     cairo_pattern_t  *mask)
 {
     return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
 					           mask,
@@ -858,7 +877,8 @@ cairo_status_t
 _cairo_gstate_paint (cairo_gstate_t *gstate)
 {
     cairo_status_t status;
-    cairo_pattern_union_t pattern;
+    cairo_pattern_t *pattern;
+    cairo_pattern_union_t pattern_stack;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -867,15 +887,17 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
     if (status)
 	return status;
 
-    status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    pattern = &pattern_stack.base;
+    status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
     if (status)
 	return status;
 
     status = _cairo_surface_paint (gstate->target,
 				   gstate->op,
-				   &pattern.base);
+				   pattern);
 
-    _cairo_pattern_fini (&pattern.base);
+    if (pattern == &pattern_stack.base)
+	_cairo_pattern_fini (pattern);
 
     return status;
 }
@@ -885,7 +907,8 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
 		    cairo_pattern_t *mask)
 {
     cairo_status_t status;
-    cairo_pattern_union_t source_pattern, mask_pattern;
+    cairo_pattern_union_t source_pattern_stack, mask_pattern_stack;
+    cairo_pattern_t *source_pattern, *mask_pattern;
 
     if (mask->status)
 	return mask->status;
@@ -897,22 +920,26 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
     if (status)
 	return status;
 
-    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    source_pattern = &source_pattern_stack.base;
+    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
     if (status)
 	return status;
 
-    status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
+    mask_pattern = &mask_pattern_stack.base;
+    status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern, mask);
     if (status)
 	goto CLEANUP_SOURCE;
 
     status = _cairo_surface_mask (gstate->target,
 				  gstate->op,
-				  &source_pattern.base,
-				  &mask_pattern.base);
+				  source_pattern,
+				  mask_pattern);
 
-    _cairo_pattern_fini (&mask_pattern.base);
+    if (mask_pattern == &mask_pattern_stack.base)
+	_cairo_pattern_fini (&mask_pattern_stack.base);
 CLEANUP_SOURCE:
-    _cairo_pattern_fini (&source_pattern.base);
+    if (source_pattern == &source_pattern_stack.base)
+	_cairo_pattern_fini (&source_pattern_stack.base);
 
     return status;
 }
@@ -921,7 +948,8 @@ cairo_status_t
 _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
-    cairo_pattern_union_t source_pattern;
+    cairo_pattern_union_t source_pattern_stack;
+    cairo_pattern_t *source_pattern;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -933,14 +961,15 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
     if (status)
 	return status;
 
+    source_pattern = &source_pattern_stack.base;
     status = _cairo_gstate_copy_transformed_source (gstate,
-	                                            &source_pattern.base);
+	                                            &source_pattern);
     if (status)
 	return status;
 
     status = _cairo_surface_stroke (gstate->target,
 				    gstate->op,
-				    &source_pattern.base,
+				    source_pattern,
 				    path,
 				    &gstate->stroke_style,
 				    &gstate->ctm,
@@ -948,10 +977,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 				    gstate->tolerance,
 				    gstate->antialias);
 
-    _cairo_pattern_fini (&source_pattern.base);
+    if (source_pattern == &source_pattern_stack.base)
+	_cairo_pattern_fini (&source_pattern_stack.base);
 
     return status;
-
 }
 
 cairo_status_t
@@ -1001,7 +1030,8 @@ cairo_status_t
 _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
-    cairo_pattern_union_t pattern;
+    cairo_pattern_union_t pattern_stack;
+    cairo_pattern_t *pattern;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1010,19 +1040,21 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
     if (status)
 	return status;
 
-    status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    pattern = &pattern_stack.base;
+    status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
     if (status)
 	return status;
 
     status = _cairo_surface_fill (gstate->target,
 				  gstate->op,
-				  &pattern.base,
+				  pattern,
 				  path,
 				  gstate->fill_rule,
 				  gstate->tolerance,
 				  gstate->antialias);
 
-    _cairo_pattern_fini (&pattern.base);
+    if (pattern == &pattern_stack.base)
+	_cairo_pattern_fini (&pattern_stack.base);
 
     return status;
 }
@@ -1582,7 +1614,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				cairo_text_cluster_flags_t  cluster_flags)
 {
     cairo_status_t status;
-    cairo_pattern_union_t source_pattern;
+    cairo_pattern_union_t source_pattern_stack;
+    cairo_pattern_t *source_pattern;
     cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
@@ -1613,7 +1646,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
 
-    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    source_pattern = &source_pattern_stack.base;
+    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
     if (status)
 	goto CLEANUP_GLYPHS;
 
@@ -1635,7 +1669,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
 	status = _cairo_surface_show_text_glyphs (gstate->target,
 						  gstate->op,
-						  &source_pattern.base,
+						  source_pattern,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
 						  clusters, num_clusters,
@@ -1653,7 +1687,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	if (status == CAIRO_STATUS_SUCCESS)
 	  status = _cairo_surface_fill (gstate->target,
 					gstate->op,
-					&source_pattern.base,
+					source_pattern,
 					&path,
 					CAIRO_FILL_RULE_WINDING,
 					gstate->tolerance,
@@ -1662,7 +1696,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 	_cairo_path_fixed_fini (&path);
     }
 
-    _cairo_pattern_fini (&source_pattern.base);
+    if (source_pattern == &source_pattern_stack.base)
+	_cairo_pattern_fini (&source_pattern_stack.base);
 
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 4aad77f..12614c1 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -939,8 +939,8 @@ _pixman_operator (cairo_operator_t op)
 
 static cairo_int_status_t
 _cairo_image_surface_composite (cairo_operator_t	op,
-				cairo_pattern_t		*src_pattern,
-				cairo_pattern_t		*mask_pattern,
+				const cairo_pattern_t	*src_pattern,
+				const cairo_pattern_t	*mask_pattern,
 				void			*abstract_dst,
 				int			src_x,
 				int			src_y,
@@ -1072,7 +1072,7 @@ _cairo_image_surface_fill_rectangles (void		      *abstract_surface,
 
 static cairo_int_status_t
 _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
-					   cairo_pattern_t	*pattern,
+					   const cairo_pattern_t *pattern,
 					   void			*abstract_dst,
 					   cairo_antialias_t	antialias,
 					   int			src_x,
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index b86cb51..faf4855 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -219,7 +219,7 @@ _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,
-			   cairo_pattern_t	*source)
+			   const cairo_pattern_t	*source)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -259,8 +259,8 @@ _cairo_meta_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_meta_surface_mask (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  cairo_pattern_t	*source,
-			  cairo_pattern_t	*mask)
+			  const cairo_pattern_t	*source,
+			  const cairo_pattern_t	*mask)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
@@ -300,7 +300,7 @@ _cairo_meta_surface_mask (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_meta_surface_stroke (void			*abstract_surface,
 			    cairo_operator_t		 op,
-			    cairo_pattern_t		*source,
+			    const cairo_pattern_t	*source,
 			    cairo_path_fixed_t		*path,
 			    cairo_stroke_style_t	*style,
 			    cairo_matrix_t		*ctm,
@@ -357,7 +357,7 @@ _cairo_meta_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_meta_surface_fill (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  cairo_pattern_t	*source,
+			  const cairo_pattern_t	*source,
 			  cairo_path_fixed_t	*path,
 			  cairo_fill_rule_t	 fill_rule,
 			  double		 tolerance,
@@ -411,7 +411,7 @@ _cairo_meta_surface_has_show_text_glyphs (void *abstract_surface)
 static cairo_int_status_t
 _cairo_meta_surface_show_text_glyphs (void			    *abstract_surface,
 				      cairo_operator_t		     op,
-				      cairo_pattern_t		    *source,
+				      const cairo_pattern_t	    *source,
 				      const char		    *utf8,
 				      int			     utf8_len,
 				      cairo_glyph_t		    *glyphs,
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index a94ca80..e50820c 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -526,7 +526,7 @@ _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,
-				cairo_pattern_t		*source)
+				const cairo_pattern_t	*source)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -542,8 +542,8 @@ _cairo_paginated_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_paginated_surface_mask (void		*abstract_surface,
 			       cairo_operator_t	 op,
-			       cairo_pattern_t	*source,
-			       cairo_pattern_t	*mask)
+			       const cairo_pattern_t	*source,
+			       const cairo_pattern_t	*mask)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -553,7 +553,7 @@ _cairo_paginated_surface_mask (void		*abstract_surface,
 static cairo_int_status_t
 _cairo_paginated_surface_stroke (void			*abstract_surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_stroke_style_t	*style,
 				 cairo_matrix_t		*ctm,
@@ -578,7 +578,7 @@ _cairo_paginated_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_paginated_surface_fill (void			*abstract_surface,
 			       cairo_operator_t		 op,
-			       cairo_pattern_t		*source,
+			       const cairo_pattern_t	*source,
 			       cairo_path_fixed_t	*path,
 			       cairo_fill_rule_t	 fill_rule,
 			       double			 tolerance,
@@ -608,7 +608,7 @@ _cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
 static cairo_int_status_t
 _cairo_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					  cairo_operator_t	     op,
-					  cairo_pattern_t	    *source,
+					  const cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 064eeb6..516eec7 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1232,7 +1232,7 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
 }
 
 static cairo_int_status_t
-_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
+_cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pattern,
 					     cairo_surface_t	        *dst,
 					     int			x,
 					     int			y,
@@ -1496,7 +1496,7 @@ _cairo_pattern_solid_surface_matches_color (
 }
 
 static cairo_int_status_t
-_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t	     *pattern,
+_cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t	     *pattern,
 					  cairo_surface_t	     *dst,
 					  int			     x,
 					  int			     y,
@@ -1716,8 +1716,8 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
  *      backends do currently (see bug #10508)
  */
 static cairo_filter_t
-_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern,
-			       double                  *pad_out)
+_cairo_pattern_analyze_filter (const cairo_surface_pattern_t *pattern,
+			       double                        *pad_out)
 {
     double pad;
     cairo_filter_t optimized_filter;
@@ -1767,7 +1767,7 @@ _pixman_nearest_sample (double d)
 }
 
 static cairo_int_status_t
-_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
+_cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pattern,
 					    cairo_surface_t	       *dst,
 					    int			       x,
 					    int			       y,
@@ -2005,7 +2005,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
  * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
  **/
 cairo_int_status_t
-_cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
+_cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 				cairo_surface_t		   *dst,
 				int			   x,
 				int			   y,
@@ -2097,16 +2097,16 @@ _cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
  * Releases resources obtained by _cairo_pattern_acquire_surface.
  **/
 void
-_cairo_pattern_release_surface (cairo_pattern_t		   *pattern,
+_cairo_pattern_release_surface (const cairo_pattern_t *pattern,
 				cairo_surface_t		   *surface,
 				cairo_surface_attributes_t *attributes)
 {
     if (attributes->acquired)
     {
-	cairo_surface_pattern_t *surface_pattern;
+	const cairo_surface_pattern_t *surface_pattern;
 
 	assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
-	surface_pattern = (cairo_surface_pattern_t *) pattern;
+	surface_pattern = (const cairo_surface_pattern_t *) pattern;
 
 	_cairo_surface_release_source_image (surface_pattern->surface,
 					     (cairo_image_surface_t *) surface,
@@ -2119,8 +2119,8 @@ _cairo_pattern_release_surface (cairo_pattern_t		   *pattern,
 }
 
 cairo_int_status_t
-_cairo_pattern_acquire_surfaces (cairo_pattern_t	    *src,
-				 cairo_pattern_t	    *mask,
+_cairo_pattern_acquire_surfaces (const cairo_pattern_t	    *src,
+				 const cairo_pattern_t	    *mask,
 				 cairo_surface_t	    *dst,
 				 int			    src_x,
 				 int			    src_y,
@@ -2134,7 +2134,7 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t	    *src,
 				 cairo_surface_attributes_t *mask_attributes)
 {
     cairo_int_status_t	  status;
-    cairo_pattern_union_t src_tmp, mask_tmp;
+    cairo_pattern_union_t src_tmp;
 
     if (src->status)
 	return src->status;
@@ -2159,48 +2159,32 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t	    *src,
 
 	_cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
+	src = &src_tmp.base;
 	mask = NULL;
     }
-    else
-    {
-	status = _cairo_pattern_init_copy (&src_tmp.base, src);
-	if (status)
-	    return status;
-    }
 
-    status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
+    status = _cairo_pattern_acquire_surface (src, dst,
 					     src_x, src_y,
 					     width, height,
 					     src_out, src_attributes);
-    if (status) {
-	_cairo_pattern_fini (&src_tmp.base);
-	return status;
-    }
+    if (status)
+	goto BAIL;
 
-    if (mask == NULL)
-    {
-	_cairo_pattern_fini (&src_tmp.base);
+    if (mask == NULL) {
 	*mask_out = NULL;
-	return CAIRO_STATUS_SUCCESS;
+	goto BAIL;
     }
 
-    status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
-    if (status)
-	goto CLEANUP_SOURCE;
-
-    status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
+    status = _cairo_pattern_acquire_surface (mask, dst,
 					     mask_x, mask_y,
 					     width, height,
 					     mask_out, mask_attributes);
-
-    _cairo_pattern_fini (&mask_tmp.base);
-
-CLEANUP_SOURCE:
     if (status)
-	_cairo_pattern_release_surface (&src_tmp.base,
-					*src_out, src_attributes);
+	_cairo_pattern_release_surface (src, *src_out, src_attributes);
 
-    _cairo_pattern_fini (&src_tmp.base);
+  BAIL:
+    if (src == &src_tmp.base)
+	_cairo_pattern_fini (&src_tmp.base);
 
     return status;
 }
@@ -2218,16 +2202,16 @@ CLEANUP_SOURCE:
  * with a little more work.
  **/
 cairo_status_t
-_cairo_pattern_get_extents (cairo_pattern_t         *pattern,
-			    cairo_rectangle_int_t   *extents)
+_cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
+			    cairo_rectangle_int_t         *extents)
 {
     if (pattern->extend == CAIRO_EXTEND_NONE &&
 	pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
     {
 	cairo_status_t status;
 	cairo_rectangle_int_t surface_extents;
-	cairo_surface_pattern_t *surface_pattern =
-	    (cairo_surface_pattern_t *) pattern;
+	const cairo_surface_pattern_t *surface_pattern =
+	    (const cairo_surface_pattern_t *) pattern;
 	cairo_surface_t *surface = surface_pattern->surface;
 	cairo_matrix_t imatrix;
 	double x1, y1, x2, y2;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 44f0ed8..0154acd 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -774,7 +774,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,
-				    cairo_pattern_t		*pattern,
+				    const cairo_pattern_t	*pattern,
 				    cairo_pdf_resource_t	*pattern_res,
 				    cairo_pdf_resource_t	*gstate_res)
 {
@@ -807,10 +807,13 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 	}
     }
 
-    pdf_pattern.pattern = cairo_pattern_reference (pattern);
+    status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
+    if (status)
+	return status;
+
     pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
     if (pdf_pattern.pattern_res.id == 0) {
-	cairo_pattern_destroy (pattern);
+	cairo_pattern_destroy (pdf_pattern.pattern);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
@@ -822,7 +825,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
         if (_cairo_pattern_is_opaque (pattern) == FALSE) {
             pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
 	    if (pdf_pattern.gstate_res.id == 0) {
-		cairo_pattern_destroy (pattern);
+		cairo_pattern_destroy (pdf_pattern.pattern);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
         }
@@ -835,7 +838,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 
     status = _cairo_array_append (&surface->patterns, &pdf_pattern);
     if (status) {
-	cairo_pattern_destroy (pattern);
+	cairo_pattern_destroy (pdf_pattern.pattern);
 	return status;
     }
 
@@ -2616,16 +2619,16 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
 
 static cairo_status_t
 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
-				   cairo_pattern_t     *pattern,
+				   const cairo_pattern_t     *pattern,
 				   cairo_pdf_resource_t pattern_res,
 				   cairo_bool_t         is_stroke)
 {
     cairo_status_t status;
     int alpha;
-    cairo_color_t *solid_color = NULL;
+    const cairo_color_t *solid_color = NULL;
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
+	const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
 
 	solid_color = &solid->color;
     }
@@ -4257,11 +4260,11 @@ _surface_pattern_supported (cairo_surface_pattern_t *pattern)
 }
 
 static cairo_bool_t
-_gradient_pattern_supported (cairo_pattern_t *pattern)
+_gradient_pattern_supported (const cairo_pattern_t *pattern)
 {
     cairo_extend_t extend;
 
-    extend = cairo_pattern_get_extend (pattern);
+    extend = cairo_pattern_get_extend ((cairo_pattern_t *) pattern);
 
 
     /* Radial gradients are currently only supported with EXTEND_NONE
@@ -4292,7 +4295,7 @@ _gradient_pattern_supported (cairo_pattern_t *pattern)
 }
 
 static cairo_bool_t
-_pattern_supported (cairo_pattern_t *pattern)
+_pattern_supported (const cairo_pattern_t *pattern)
 {
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 	return TRUE;
@@ -4310,10 +4313,13 @@ _pattern_supported (cairo_pattern_t *pattern)
 static cairo_int_status_t
 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
 				      cairo_operator_t      op,
-				      cairo_pattern_t      *pattern)
+				      const cairo_pattern_t      *pattern)
 {
-    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    if (surface->force_fallbacks &&
+	surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     if (! _pattern_supported (pattern))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -4368,7 +4374,7 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
 static cairo_bool_t
 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t  *surface,
 					cairo_operator_t      op,
-					cairo_pattern_t      *pattern)
+					const cairo_pattern_t      *pattern)
 {
     if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
 	return TRUE;
@@ -4396,7 +4402,7 @@ _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,
-			  cairo_pattern_t	*source)
+			  const cairo_pattern_t	*source)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4427,7 +4433,11 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_PAINT;
-	group->source = cairo_pattern_reference (source);
+	status = _cairo_pattern_create_copy (&group->source, source);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
 	group->source_res = pattern_res;
 	status = _cairo_pdf_surface_add_smask_group (surface, group);
 	if (status) {
@@ -4471,8 +4481,8 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_pdf_surface_mask	(void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*source,
-			 cairo_pattern_t	*mask)
+			 const cairo_pattern_t	*source,
+			 const cairo_pattern_t	*mask)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_pdf_smask_group_t *group;
@@ -4505,8 +4515,16 @@ _cairo_pdf_surface_mask	(void			*abstract_surface,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     group->operation = PDF_MASK;
-    group->source = cairo_pattern_reference (source);
-    group->mask = cairo_pattern_reference (mask);
+    status = _cairo_pattern_create_copy (&group->source, source);
+    if (status) {
+	_cairo_pdf_smask_group_destroy (group);
+	return status;
+    }
+    status = _cairo_pattern_create_copy (&group->mask, mask);
+    if (status) {
+	_cairo_pdf_smask_group_destroy (group);
+	return status;
+    }
     group->source_res = _cairo_pdf_surface_new_object (surface);
     if (group->source_res.id == 0) {
 	_cairo_pdf_smask_group_destroy (group);
@@ -4542,7 +4560,7 @@ _cairo_pdf_surface_mask	(void			*abstract_surface,
 static cairo_int_status_t
 _cairo_pdf_surface_stroke (void			*abstract_surface,
 			   cairo_operator_t	 op,
-			   cairo_pattern_t	*source,
+			   const cairo_pattern_t *source,
 			   cairo_path_fixed_t	*path,
 			   cairo_stroke_style_t	*style,
 			   cairo_matrix_t	*ctm,
@@ -4574,7 +4592,11 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_STROKE;
-	group->source = cairo_pattern_reference (source);
+	status = _cairo_pattern_create_copy (&group->source, source);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
 	group->source_res = pattern_res;
 	status = _cairo_path_fixed_init_copy (&group->path, path);
 	if (status) {
@@ -4631,7 +4653,7 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_pdf_surface_fill (void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*source,
+			 const cairo_pattern_t	*source,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
@@ -4666,7 +4688,11 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_FILL;
-	group->source = cairo_pattern_reference (source);
+	status = _cairo_pattern_create_copy (&group->source, source);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
 	group->source_res = pattern_res;
 	status = _cairo_path_fixed_init_copy (&group->path, path);
 	if (status) {
@@ -4719,13 +4745,13 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
 				cairo_operator_t      fill_op,
-				cairo_pattern_t	     *fill_source,
+				const cairo_pattern_t *fill_source,
 				cairo_fill_rule_t     fill_rule,
 				double		      fill_tolerance,
 				cairo_antialias_t     fill_antialias,
 				cairo_path_fixed_t   *path,
 				cairo_operator_t      stroke_op,
-				cairo_pattern_t	     *stroke_source,
+				const cairo_pattern_t *stroke_source,
 				cairo_stroke_style_t *stroke_style,
 				cairo_matrix_t	     *stroke_ctm,
 				cairo_matrix_t	     *stroke_ctm_inverse,
@@ -4812,8 +4838,8 @@ _cairo_pdf_surface_has_show_text_glyphs	(void			*abstract_surface)
 
 static cairo_int_status_t
 _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
-				     cairo_operator_t	 	 op,
-				     cairo_pattern_t	       	*source,
+				     cairo_operator_t		 op,
+				     const cairo_pattern_t	*source,
 				     const char                 *utf8,
 				     int                         utf8_len,
 				     cairo_glyph_t		*glyphs,
@@ -4847,7 +4873,11 @@ _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_SHOW_GLYPHS;
-	group->source = cairo_pattern_reference (source);
+	status = _cairo_pattern_create_copy (&group->source, source);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
 	group->source_res = pattern_res;
 
 	if (utf8_len) {
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index bfe424d..3d7afb6 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1437,7 +1437,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
 }
 
 static cairo_bool_t
-surface_pattern_supported (cairo_surface_pattern_t *pattern)
+surface_pattern_supported (const cairo_surface_pattern_t *pattern)
 {
     cairo_extend_t extend;
 
@@ -1478,9 +1478,9 @@ surface_pattern_supported (cairo_surface_pattern_t *pattern)
 
 static cairo_bool_t
 _gradient_pattern_supported (cairo_ps_surface_t    *surface,
-			     cairo_pattern_t *pattern)
+			     const cairo_pattern_t *pattern)
 {
-    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
+    const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *) pattern;
     uint16_t alpha;
     cairo_extend_t extend;
     unsigned int i;
@@ -1499,7 +1499,7 @@ _gradient_pattern_supported (cairo_ps_surface_t    *surface,
 	    return FALSE;
     }
 
-    extend = cairo_pattern_get_extend (pattern);
+    extend = cairo_pattern_get_extend ((cairo_pattern_t *) pattern);
 
     /* Radial gradients are currently only supported when one circle
      * is inside the other. */
@@ -1531,7 +1531,7 @@ _gradient_pattern_supported (cairo_ps_surface_t    *surface,
 }
 
 static cairo_bool_t
-pattern_supported (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
+pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
 {
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 	return TRUE;
@@ -1549,10 +1549,13 @@ pattern_supported (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
 static cairo_int_status_t
 _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
 				     cairo_operator_t       op,
-				     cairo_pattern_t       *pattern)
+				     const cairo_pattern_t       *pattern)
 {
-    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    if (surface->force_fallbacks &&
+	surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     if (! pattern_supported (surface, pattern))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1597,7 +1600,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
 static cairo_bool_t
 _cairo_ps_surface_operation_supported (cairo_ps_surface_t    *surface,
 				       cairo_operator_t       op,
-				       cairo_pattern_t       *pattern)
+				       const cairo_pattern_t       *pattern)
 {
     if (_cairo_ps_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
 	return TRUE;
@@ -2888,7 +2891,7 @@ _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,
-				cairo_pattern_t *pattern,
+				const cairo_pattern_t *pattern,
 				cairo_operator_t op)
 {
     cairo_status_t status;
@@ -3018,7 +3021,7 @@ _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,
-			 cairo_pattern_t	*source)
+			 const cairo_pattern_t	*source)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
@@ -3077,7 +3080,7 @@ _cairo_ps_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_ps_surface_stroke (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  cairo_pattern_t	*source,
+			  const cairo_pattern_t	*source,
 			  cairo_path_fixed_t	*path,
 			  cairo_stroke_style_t	*style,
 			  cairo_matrix_t	*ctm,
@@ -3111,12 +3114,12 @@ _cairo_ps_surface_stroke (void			*abstract_surface,
 
 static cairo_int_status_t
 _cairo_ps_surface_fill (void		*abstract_surface,
-		 cairo_operator_t	 op,
-		 cairo_pattern_t	*source,
-		 cairo_path_fixed_t	*path,
-		 cairo_fill_rule_t	 fill_rule,
-		 double			 tolerance,
-		 cairo_antialias_t	 antialias)
+			cairo_operator_t	 op,
+			const cairo_pattern_t	*source,
+			cairo_path_fixed_t	*path,
+			cairo_fill_rule_t	 fill_rule,
+			double			 tolerance,
+			cairo_antialias_t	 antialias)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -3174,7 +3177,7 @@ _cairo_ps_surface_fill (void		*abstract_surface,
 static cairo_int_status_t
 _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
 			       cairo_operator_t	      op,
-			       cairo_pattern_t	     *source,
+			       const cairo_pattern_t *source,
 			       cairo_glyph_t         *glyphs,
 			       int		      num_glyphs,
 			       cairo_scaled_font_t   *scaled_font,
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 41fde0b..fc9439e 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -688,7 +688,7 @@ CreateGradientFunction (cairo_gradient_pattern_t *gpat)
 	0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
     };
 
-    return CGFunctionCreate (gpat,
+    return CGFunctionCreate (_cairo_pattern_create_copy (&gpat->base),
 			     1,
 			     input_value_range,
 			     4,
@@ -766,7 +766,7 @@ CreateRepeatingGradientFunction (cairo_quartz_surface_t *surface,
     input_value_range[0] = 0.0 - 1.0 * rep_start;
     input_value_range[1] = 1.0 + 1.0 * rep_end;
 
-    return CGFunctionCreate (gpat,
+    return CGFunctionCreate (_cairo_pattern_create_copy (&gpat->base),
 			     1,
 			     input_value_range,
 			     4,
@@ -1096,9 +1096,6 @@ _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
     end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x),
 		       _cairo_fixed_to_double (lpat->p2.y));
 
-    // ref will be released by the CGShading's destructor
-    cairo_pattern_reference ((cairo_pattern_t*) lpat);
-
     if (abspat->extend == CAIRO_EXTEND_NONE ||
 	abspat->extend == CAIRO_EXTEND_PAD)
     {
@@ -1159,9 +1156,6 @@ _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
     end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x),
 		       _cairo_fixed_to_double (rpat->c2.y));
 
-    // ref will be released by the CGShading's destructor
-    cairo_pattern_reference ((cairo_pattern_t*) rpat);
-
     gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
 
     surface->sourceShading = CGShadingCreateRadial (rgb,
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 3ec07d5..32fd62a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1785,7 +1785,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
 cairo_status_t
 _cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
 				cairo_operator_t        op,
-				cairo_pattern_t        *pattern,
+				const cairo_pattern_t	*pattern,
 				cairo_surface_t        *surface,
 				int                     source_x,
 				int                     source_y,
diff --git a/src/cairo-sdl-surface.c b/src/cairo-sdl-surface.c
index 411573e..b9d604e 100644
--- a/src/cairo-sdl-surface.c
+++ b/src/cairo-sdl-surface.c
@@ -208,18 +208,18 @@ _cairo_sdl_surface_clone_similar (void		*abstract_surface,
 }
 
 static cairo_int_status_t
-_cairo_sdl_surface_composite (cairo_operator_t		op,
-			      cairo_pattern_t		*src_pattern,
-			      cairo_pattern_t		*mask_pattern,
+_cairo_sdl_surface_composite (cairo_operator_t		 op,
+			      const cairo_pattern_t	*src_pattern,
+			      const cairo_pattern_t	*mask_pattern,
 			      void			*abstract_dst,
-			      int			src_x,
-			      int			src_y,
-			      int			mask_x,
-			      int			mask_y,
-			      int			dst_x,
-			      int			dst_y,
-			      unsigned int		width,
-			      unsigned int		height)
+			      int			 src_x,
+			      int			 src_y,
+			      int			 mask_x,
+			      int			 mask_y,
+			      int			 dst_x,
+			      int			 dst_y,
+			      unsigned int		 width,
+			      unsigned int		 height)
 {
     cairo_sdl_surface_t *dst = abstract_dst;
     cairo_sdl_surface_t *src;
diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
index 2e10241..61e5b90 100644
--- a/src/cairo-surface-fallback-private.h
+++ b/src/cairo-surface-fallback-private.h
@@ -42,19 +42,20 @@
 #include "cairoint.h"
 
 cairo_private cairo_status_t
-_cairo_surface_fallback_paint (cairo_surface_t	*surface,
-			       cairo_operator_t	 op,
-			       cairo_pattern_t	*source);
+_cairo_surface_fallback_paint (cairo_surface_t		*surface,
+			       cairo_operator_t		 op,
+			       const cairo_pattern_t	*source);
+
 cairo_private cairo_status_t
 _cairo_surface_fallback_mask (cairo_surface_t		*surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
-			      cairo_pattern_t		*mask);
+			      const cairo_pattern_t	*source,
+			      const cairo_pattern_t	*mask);
 
 cairo_private cairo_status_t
 _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
+				const cairo_pattern_t	*source,
 				cairo_path_fixed_t	*path,
 				cairo_stroke_style_t	*stroke_style,
 				cairo_matrix_t		*ctm,
@@ -65,16 +66,16 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 cairo_private cairo_status_t
 _cairo_surface_fallback_fill (cairo_surface_t		*surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
+			      const cairo_pattern_t	*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
-			      double		 	 tolerance,
+			      double			 tolerance,
 			      cairo_antialias_t		 antialias);
 
 cairo_private cairo_status_t
 _cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
 				     cairo_operator_t		 op,
-				     cairo_pattern_t		*source,
+				     const cairo_pattern_t	*source,
 				     cairo_glyph_t		*glyphs,
 				     int			 num_glyphs,
 				     cairo_scaled_font_t	*scaled_font);
@@ -83,18 +84,18 @@ cairo_private cairo_surface_t *
 _cairo_surface_fallback_snapshot (cairo_surface_t *surface);
 
 cairo_private cairo_status_t
-_cairo_surface_fallback_composite (cairo_operator_t	op,
-				   cairo_pattern_t	*src,
-				   cairo_pattern_t	*mask,
-				   cairo_surface_t	*dst,
-				   int			src_x,
-				   int			src_y,
-				   int			mask_x,
-				   int			mask_y,
-				   int			dst_x,
-				   int			dst_y,
-				   unsigned int		width,
-				   unsigned int		height);
+_cairo_surface_fallback_composite (cairo_operator_t		 op,
+				   const cairo_pattern_t	*src,
+				   const cairo_pattern_t	*mask,
+				   cairo_surface_t		*dst,
+				   int				 src_x,
+				   int				 src_y,
+				   int				 mask_x,
+				   int				 mask_y,
+				   int				 dst_x,
+				   int				 dst_y,
+				   unsigned int			 width,
+				   unsigned int			 height);
 
 cairo_private cairo_status_t
 _cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
@@ -105,7 +106,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
 
 cairo_private cairo_status_t
 _cairo_surface_fallback_composite_trapezoids (cairo_operator_t		op,
-					      cairo_pattern_t	       *pattern,
+					      const cairo_pattern_t    *pattern,
 					      cairo_surface_t	       *dst,
 					      cairo_antialias_t		antialias,
 					      int			src_x,
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 5b9c99a..a5dcd57 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -103,7 +103,7 @@ _fallback_fini (fallback_state_t *state)
 
 typedef cairo_status_t (*cairo_draw_func_t) (void                          *closure,
 					     cairo_operator_t               op,
-					     cairo_pattern_t               *src,
+					     const cairo_pattern_t         *src,
 					     cairo_surface_t               *dst,
 					     int                            dst_x,
 					     int                            dst_y,
@@ -156,7 +156,7 @@ _create_composite_mask_pattern (cairo_surface_pattern_t       *mask_pattern,
 static cairo_status_t
 _clip_and_composite_with_mask (cairo_clip_t                  *clip,
 			       cairo_operator_t               op,
-			       cairo_pattern_t               *src,
+			       const cairo_pattern_t         *src,
 			       cairo_draw_func_t              draw_func,
 			       void                          *draw_closure,
 			       cairo_surface_t               *dst,
@@ -190,7 +190,7 @@ _clip_and_composite_with_mask (cairo_clip_t                  *clip,
 static cairo_status_t
 _clip_and_composite_combine (cairo_clip_t                  *clip,
 			     cairo_operator_t               op,
-			     cairo_pattern_t               *src,
+			     const cairo_pattern_t         *src,
 			     cairo_draw_func_t              draw_func,
 			     void                          *draw_closure,
 			     cairo_surface_t               *dst,
@@ -278,7 +278,7 @@ _clip_and_composite_combine (cairo_clip_t                  *clip,
  */
 static cairo_status_t
 _clip_and_composite_source (cairo_clip_t                  *clip,
-			    cairo_pattern_t               *src,
+			    const cairo_pattern_t         *src,
 			    cairo_draw_func_t              draw_func,
 			    void                          *draw_closure,
 			    cairo_surface_t               *dst,
@@ -352,7 +352,7 @@ _cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
 static cairo_status_t
 _clip_and_composite (cairo_clip_t                  *clip,
 		     cairo_operator_t               op,
-		     cairo_pattern_t               *src,
+		     const cairo_pattern_t         *src,
 		     cairo_draw_func_t              draw_func,
 		     void                          *draw_closure,
 		     cairo_surface_t               *dst,
@@ -408,7 +408,7 @@ _clip_and_composite (cairo_clip_t                  *clip,
  */
 static cairo_status_t
 _composite_trap_region (cairo_clip_t            *clip,
-			cairo_pattern_t         *src,
+			const cairo_pattern_t	*src,
 			cairo_operator_t         op,
 			cairo_surface_t         *dst,
 			cairo_region_t          *trap_region,
@@ -480,7 +480,7 @@ typedef struct {
 static cairo_status_t
 _composite_traps_draw_func (void                          *closure,
 			    cairo_operator_t               op,
-			    cairo_pattern_t               *src,
+			    const cairo_pattern_t         *src,
 			    cairo_surface_t               *dst,
 			    int                            dst_x,
 			    int                            dst_y,
@@ -512,7 +512,7 @@ _composite_traps_draw_func (void                          *closure,
 
 /* Warning: This call modifies the coordinates of traps */
 static cairo_status_t
-_clip_and_composite_trapezoids (cairo_pattern_t *src,
+_clip_and_composite_trapezoids (const cairo_pattern_t *src,
 				cairo_operator_t op,
 				cairo_surface_t *dst,
 				cairo_traps_t *traps,
@@ -671,9 +671,9 @@ out:
 }
 
 cairo_status_t
-_cairo_surface_fallback_paint (cairo_surface_t	*surface,
-			       cairo_operator_t	 op,
-			       cairo_pattern_t	*source)
+_cairo_surface_fallback_paint (cairo_surface_t		*surface,
+			       cairo_operator_t		 op,
+			       const cairo_pattern_t	*source)
 {
     cairo_status_t status;
     cairo_rectangle_int_t extents;
@@ -686,6 +686,7 @@ _cairo_surface_fallback_paint (cairo_surface_t	*surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
@@ -717,7 +718,7 @@ _cairo_surface_fallback_paint (cairo_surface_t	*surface,
 static cairo_status_t
 _cairo_surface_mask_draw_func (void                          *closure,
 			       cairo_operator_t               op,
-			       cairo_pattern_t               *src,
+			       const cairo_pattern_t         *src,
 			       cairo_surface_t               *dst,
 			       int                            dst_x,
 			       int                            dst_y,
@@ -744,8 +745,8 @@ _cairo_surface_mask_draw_func (void                          *closure,
 cairo_status_t
 _cairo_surface_fallback_mask (cairo_surface_t		*surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
-			      cairo_pattern_t		*mask)
+			      const cairo_pattern_t	*source,
+			      const cairo_pattern_t	*mask)
 {
     cairo_status_t status;
     cairo_rectangle_int_t extents, source_extents, mask_extents;
@@ -779,7 +780,7 @@ _cairo_surface_fallback_mask (cairo_surface_t		*surface,
     status = _clip_and_composite (surface->clip, op,
 				  source,
 				  _cairo_surface_mask_draw_func,
-				  mask,
+				  (void *) mask,
 				  surface,
 				  &extents);
 
@@ -789,7 +790,7 @@ _cairo_surface_fallback_mask (cairo_surface_t		*surface,
 cairo_status_t
 _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
+				const cairo_pattern_t	*source,
 				cairo_path_fixed_t	*path,
 				cairo_stroke_style_t	*stroke_style,
 				cairo_matrix_t		*ctm,
@@ -852,7 +853,7 @@ FAIL:
 cairo_status_t
 _cairo_surface_fallback_fill (cairo_surface_t		*surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
+			      const cairo_pattern_t	*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
@@ -920,7 +921,7 @@ typedef struct {
 static cairo_status_t
 _cairo_surface_old_show_glyphs_draw_func (void                          *closure,
 					  cairo_operator_t               op,
-					  cairo_pattern_t               *src,
+					  const cairo_pattern_t         *src,
 					  cairo_surface_t               *dst,
 					  int                            dst_x,
 					  int                            dst_y,
@@ -981,7 +982,7 @@ _cairo_surface_old_show_glyphs_draw_func (void                          *closure
 cairo_status_t
 _cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
 				     cairo_operator_t		 op,
-				     cairo_pattern_t		*source,
+				     const cairo_pattern_t	*source,
 				     cairo_glyph_t		*glyphs,
 				     int			 num_glyphs,
 				     cairo_scaled_font_t	*scaled_font)
@@ -1080,18 +1081,18 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
 }
 
 cairo_status_t
-_cairo_surface_fallback_composite (cairo_operator_t	op,
-				   cairo_pattern_t	*src,
-				   cairo_pattern_t	*mask,
-				   cairo_surface_t	*dst,
-				   int			src_x,
-				   int			src_y,
-				   int			mask_x,
-				   int			mask_y,
-				   int			dst_x,
-				   int			dst_y,
-				   unsigned int		width,
-				   unsigned int		height)
+_cairo_surface_fallback_composite (cairo_operator_t		 op,
+				   const cairo_pattern_t	*src,
+				   const cairo_pattern_t	*mask,
+				   cairo_surface_t		*dst,
+				   int				 src_x,
+				   int				 src_y,
+				   int				 mask_x,
+				   int				 mask_y,
+				   int				 dst_x,
+				   int				 dst_y,
+				   unsigned int			 width,
+				   unsigned int			 height)
 {
     fallback_state_t state;
     cairo_status_t status;
@@ -1197,7 +1198,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
 
 cairo_status_t
 _cairo_surface_fallback_composite_trapezoids (cairo_operator_t		op,
-					      cairo_pattern_t	       *pattern,
+					      const cairo_pattern_t    *pattern,
 					      cairo_surface_t	       *dst,
 					      cairo_antialias_t		antialias,
 					      int			src_x,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 609a0e0..4041790 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -89,9 +89,9 @@ static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_err
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
 
 static cairo_status_t
-_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
+_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t **pattern,
 					     cairo_surface_t *destination,
-					     cairo_pattern_t **pattern_out);
+					     cairo_pattern_t *pattern_copy);
 
 /**
  * _cairo_surface_set_error:
@@ -337,7 +337,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
 
 cairo_surface_t *
 _cairo_surface_create_solid_pattern_surface (cairo_surface_t	   *other,
-					     cairo_solid_pattern_t *solid_pattern)
+					     const cairo_solid_pattern_t *solid_pattern)
 {
     cairo_surface_t *surface;
 
@@ -357,7 +357,7 @@ _cairo_surface_create_solid_pattern_surface (cairo_surface_t	   *other,
 cairo_int_status_t
 _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t	    *other,
 					      cairo_surface_t       *solid_surface,
-					      cairo_solid_pattern_t *solid_pattern)
+					      const cairo_solid_pattern_t *solid_pattern)
 {
     if (other->backend->create_solid_pattern_surface)
 	/* Solid pattern surface for this backend are not trivial to make.
@@ -1254,8 +1254,8 @@ _cairo_surface_is_similar (cairo_surface_t *surface_a,
 
 cairo_status_t
 _cairo_surface_composite (cairo_operator_t	op,
-			  cairo_pattern_t	*src,
-			  cairo_pattern_t	*mask,
+			  const cairo_pattern_t	*src,
+			  const cairo_pattern_t	*mask,
 			  cairo_surface_t	*dst,
 			  int			src_x,
 			  int			src_y,
@@ -1469,69 +1469,78 @@ _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 cairo_status_t
 _cairo_surface_paint (cairo_surface_t	*surface,
 		      cairo_operator_t	 op,
-		      cairo_pattern_t	*source)
+		      const cairo_pattern_t *source)
 {
     cairo_status_t status;
-    cairo_pattern_t *dev_source;
+    cairo_pattern_union_t dev_source;
 
     if (surface->status)
 	return surface->status;
 
     assert (! surface->is_snapshot);
 
-    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
+    status = _cairo_surface_copy_pattern_for_destination (&source,
+							  surface,
+							  &dev_source.base);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
     if (surface->backend->paint) {
-	status = surface->backend->paint (surface, op, dev_source);
+	status = surface->backend->paint (surface, op, source);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto FINISH;
     }
 
-    status = _cairo_surface_fallback_paint (surface, op, dev_source);
+    status = _cairo_surface_fallback_paint (surface, op, source);
 
  FINISH:
-    cairo_pattern_destroy (dev_source);
+    if (source == &dev_source.base)
+	_cairo_pattern_fini (&dev_source.base);
 
     return _cairo_surface_set_error (surface, status);
 }
 
 cairo_status_t
-_cairo_surface_mask (cairo_surface_t	*surface,
-		     cairo_operator_t	 op,
-		     cairo_pattern_t	*source,
-		     cairo_pattern_t	*mask)
+_cairo_surface_mask (cairo_surface_t		*surface,
+		     cairo_operator_t		 op,
+		     const cairo_pattern_t	*source,
+		     const cairo_pattern_t	*mask)
 {
     cairo_status_t status;
-    cairo_pattern_t *dev_source;
-    cairo_pattern_t *dev_mask;
+    cairo_pattern_union_t dev_source;
+    cairo_pattern_union_t dev_mask;
 
     if (surface->status)
 	return surface->status;
 
     assert (! surface->is_snapshot);
 
-    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
+    status = _cairo_surface_copy_pattern_for_destination (&source,
+							  surface,
+							  &dev_source.base);
     if (status)
 	goto FINISH;
 
-    status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask);
+    status = _cairo_surface_copy_pattern_for_destination (&mask,
+							  surface,
+							  &dev_mask.base);
     if (status)
 	goto CLEANUP_SOURCE;
 
     if (surface->backend->mask) {
-	status = surface->backend->mask (surface, op, dev_source, dev_mask);
+	status = surface->backend->mask (surface, op, source, mask);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             goto CLEANUP_MASK;
     }
 
-    status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask);
+    status = _cairo_surface_fallback_mask (surface, op, source, mask);
 
  CLEANUP_MASK:
-    cairo_pattern_destroy (dev_mask);
+    if (mask == &dev_mask.base)
+	_cairo_pattern_fini (&dev_mask.base);
  CLEANUP_SOURCE:
-    cairo_pattern_destroy (dev_source);
+    if (source == &dev_source.base)
+	_cairo_pattern_fini (&dev_source.base);
  FINISH:
 
     return _cairo_surface_set_error (surface, status);
@@ -1540,13 +1549,13 @@ _cairo_surface_mask (cairo_surface_t	*surface,
 cairo_status_t
 _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 			    cairo_operator_t	     fill_op,
-			    cairo_pattern_t	    *fill_source,
+			    const cairo_pattern_t   *fill_source,
 			    cairo_fill_rule_t	     fill_rule,
 			    double		     fill_tolerance,
 			    cairo_antialias_t	     fill_antialias,
 			    cairo_path_fixed_t	    *path,
 			    cairo_operator_t	     stroke_op,
-			    cairo_pattern_t	    *stroke_source,
+			    const cairo_pattern_t   *stroke_source,
 			    cairo_stroke_style_t    *stroke_style,
 			    cairo_matrix_t	    *stroke_ctm,
 			    cairo_matrix_t	    *stroke_ctm_inverse,
@@ -1559,29 +1568,41 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 	return surface->status;
 
     if (surface->backend->fill_stroke) {
-	cairo_pattern_t *dev_stroke_source;
-	cairo_pattern_t *dev_fill_source;
+	cairo_pattern_union_t dev_stroke_source;
+	cairo_pattern_union_t dev_fill_source;
 	cairo_matrix_t dev_ctm = *stroke_ctm;
 	cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
 
-	status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source);
+	status = _cairo_surface_copy_pattern_for_destination (&stroke_source,
+							      surface,
+							      &dev_stroke_source.base);
 	if (status)
 	    return _cairo_surface_set_error (surface, status);
 
-	status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source);
+	status = _cairo_surface_copy_pattern_for_destination (&fill_source,
+							      surface,
+							      &dev_fill_source.base);
 	if (status) {
-	    cairo_pattern_destroy (dev_stroke_source);
+	    if (stroke_source == &dev_stroke_source.base)
+		_cairo_pattern_fini (&dev_stroke_source.base);
+
 	    return _cairo_surface_set_error (surface, status);
 	}
 
-	status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source,
-						fill_rule, fill_tolerance, fill_antialias,
-						path, stroke_op, dev_stroke_source, stroke_style,
-						&dev_ctm, &dev_ctm_inverse, stroke_tolerance,
-						stroke_antialias);
+	status = surface->backend->fill_stroke (surface,
+						fill_op, fill_source, fill_rule,
+						fill_tolerance, fill_antialias,
+						path,
+						stroke_op, stroke_source,
+						stroke_style,
+						&dev_ctm, &dev_ctm_inverse,
+						stroke_tolerance, stroke_antialias);
+
+	if (stroke_source == &dev_stroke_source.base)
+	    _cairo_pattern_fini (&dev_stroke_source.base);
 
-	cairo_pattern_destroy (dev_stroke_source);
-	cairo_pattern_destroy (dev_fill_source);
+	if (fill_source == &dev_fill_source.base)
+	    _cairo_pattern_fini (&dev_fill_source.base);
 
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	    return _cairo_surface_set_error (surface, status);
@@ -1604,7 +1625,7 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 cairo_status_t
 _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_operator_t		 op,
-		       cairo_pattern_t		*source,
+		       const cairo_pattern_t	*source,
 		       cairo_path_fixed_t	*path,
 		       cairo_stroke_style_t	*stroke_style,
 		       cairo_matrix_t		*ctm,
@@ -1613,7 +1634,7 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_antialias_t	 antialias)
 {
     cairo_status_t status;
-    cairo_pattern_t *dev_source;
+    cairo_pattern_union_t dev_source;
     cairo_path_fixed_t *dev_path = path;
     cairo_path_fixed_t real_dev_path;
     cairo_matrix_t dev_ctm = *ctm;
@@ -1624,12 +1645,14 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 
     assert (! surface->is_snapshot);
 
-    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
+    status = _cairo_surface_copy_pattern_for_destination (&source,
+							  surface,
+							  &dev_source.base);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
     if (surface->backend->stroke) {
-	status = surface->backend->stroke (surface, op, dev_source,
+	status = surface->backend->stroke (surface, op, source,
 					   path, stroke_style,
 					   &dev_ctm, &dev_ctm_inverse,
 					   tolerance, antialias);
@@ -1638,7 +1661,7 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
             goto FINISH;
     }
 
-    status = _cairo_surface_fallback_stroke (surface, op, dev_source,
+    status = _cairo_surface_fallback_stroke (surface, op, source,
                                              path, stroke_style,
                                              &dev_ctm, &dev_ctm_inverse,
                                              tolerance, antialias);
@@ -1646,7 +1669,9 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
  FINISH:
     if (dev_path == &real_dev_path)
         _cairo_path_fixed_fini (&real_dev_path);
-    cairo_pattern_destroy (dev_source);
+
+    if (source == &dev_source.base)
+	_cairo_pattern_fini (&dev_source.base);
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -1654,26 +1679,28 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 cairo_status_t
 _cairo_surface_fill (cairo_surface_t	*surface,
 		     cairo_operator_t	 op,
-		     cairo_pattern_t	*source,
+		     const cairo_pattern_t *source,
 		     cairo_path_fixed_t	*path,
 		     cairo_fill_rule_t	 fill_rule,
 		     double		 tolerance,
 		     cairo_antialias_t	 antialias)
 {
     cairo_status_t status;
-    cairo_pattern_t *dev_source;
+    cairo_pattern_union_t dev_source;
 
     if (surface->status)
 	return surface->status;
 
     assert (! surface->is_snapshot);
 
-    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
+    status = _cairo_surface_copy_pattern_for_destination (&source,
+							  surface,
+							  &dev_source.base);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
     if (surface->backend->fill) {
-	status = surface->backend->fill (surface, op, dev_source,
+	status = surface->backend->fill (surface, op, source,
 					 path, fill_rule,
 					 tolerance, antialias);
 
@@ -1681,19 +1708,20 @@ _cairo_surface_fill (cairo_surface_t	*surface,
             goto FINISH;
     }
 
-    status = _cairo_surface_fallback_fill (surface, op, dev_source,
+    status = _cairo_surface_fallback_fill (surface, op, source,
                                            path, fill_rule,
                                            tolerance, antialias);
 
  FINISH:
-    cairo_pattern_destroy (dev_source);
+    if (source == &dev_source.base)
+	_cairo_pattern_fini (&dev_source.base);
 
     return _cairo_surface_set_error (surface, status);
 }
 
 cairo_status_t
 _cairo_surface_composite_trapezoids (cairo_operator_t		op,
-				     cairo_pattern_t		*pattern,
+				     const cairo_pattern_t	*pattern,
 				     cairo_surface_t		*dst,
 				     cairo_antialias_t		antialias,
 				     int			src_x,
@@ -2218,7 +2246,7 @@ slim_hidden_def (cairo_surface_has_show_text_glyphs);
 cairo_status_t
 _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 cairo_operator_t	     op,
-				 cairo_pattern_t	    *source,
+				 const cairo_pattern_t	    *source,
 				 const char		    *utf8,
 				 int			     utf8_len,
 				 cairo_glyph_t		    *glyphs,
@@ -2230,7 +2258,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 {
     cairo_status_t status;
     cairo_scaled_font_t *dev_scaled_font = scaled_font;
-    cairo_pattern_t *dev_source;
+    cairo_pattern_union_t dev_source;
 
     if (surface->status)
 	return surface->status;
@@ -2240,9 +2268,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     if (!num_glyphs && !utf8_len)
 	return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_surface_copy_pattern_for_destination (source,
+    status = _cairo_surface_copy_pattern_for_destination (&source,
 						          surface,
-							  &dev_source);
+							  &dev_source.base);
     if (status)
 	return _cairo_surface_set_error (surface, status);
 
@@ -2263,7 +2291,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     }
     status = cairo_scaled_font_status (dev_scaled_font);
     if (status) {
-	cairo_pattern_destroy (dev_source);
+	if (source == &dev_source.base)
+	    _cairo_pattern_fini (&dev_source.base);
+
 	return _cairo_surface_set_error (surface, status);
     }
 
@@ -2275,7 +2305,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 	/* A real show_text_glyphs call.  Try show_text_glyphs backend
 	 * method first */
 	if (surface->backend->show_text_glyphs) {
-	    status = surface->backend->show_text_glyphs (surface, op, dev_source,
+	    status = surface->backend->show_text_glyphs (surface, op,
+							 source,
 							 utf8, utf8_len,
 							 glyphs, num_glyphs,
 							 clusters, num_clusters, cluster_flags,
@@ -2283,7 +2314,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 	}
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
 	    int remaining_glyphs = num_glyphs;
-	    status = surface->backend->show_glyphs (surface, op, dev_source,
+	    status = surface->backend->show_glyphs (surface, op,
+						    source,
 						    glyphs, num_glyphs,
 						    dev_scaled_font,
 						    &remaining_glyphs);
@@ -2296,7 +2328,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 	/* A mere show_glyphs call.  Try show_glyphs backend method first */
 	if (surface->backend->show_glyphs) {
 	    int remaining_glyphs = num_glyphs;
-	    status = surface->backend->show_glyphs (surface, op, dev_source,
+	    status = surface->backend->show_glyphs (surface, op,
+						    source,
 						    glyphs, num_glyphs,
 						    dev_scaled_font,
 						    &remaining_glyphs);
@@ -2313,7 +2346,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 	     * implies that UTF-8 is not NULL, unless the text is
 	     * zero-length).
 	     */
-	    status = surface->backend->show_text_glyphs (surface, op, dev_source,
+	    status = surface->backend->show_text_glyphs (surface, op,
+							 source,
 							 utf8, utf8_len,
 							 glyphs, num_glyphs,
 							 clusters, num_clusters, cluster_flags,
@@ -2322,14 +2356,16 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     }
 
     if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
+	status = _cairo_surface_fallback_show_glyphs (surface, op,
+						      source,
 						      glyphs, num_glyphs,
 						      dev_scaled_font);
 
     if (dev_scaled_font != scaled_font)
 	cairo_scaled_font_destroy (dev_scaled_font);
 
-    cairo_pattern_destroy (dev_source);
+    if (source == &dev_source.base)
+	_cairo_pattern_fini (&dev_source.base);
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -2342,7 +2378,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 cairo_status_t
 _cairo_surface_old_show_glyphs (cairo_scaled_font_t	*scaled_font,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*pattern,
+				const cairo_pattern_t	*pattern,
 				cairo_surface_t		*dst,
 				int			 source_x,
 				int			 source_y,
@@ -2594,27 +2630,30 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
  * _cairo_surface_copy_pattern_for_destination
  * @pattern: the pattern to copy
  * @destination: the destination surface for which the pattern is being copied
- * @pattern_out: the location to hold the copy
+ * @pattern_copy: the location to hold the copy
  *
  * Copies the given pattern, taking into account device scale and offsets
  * of the destination surface.
  */
 static cairo_status_t
-_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
+_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t **pattern,
                                              cairo_surface_t *destination,
-                                             cairo_pattern_t **pattern_out)
+                                             cairo_pattern_t *pattern_copy)
 {
     cairo_status_t status;
 
-    status = _cairo_pattern_create_copy (pattern_out, pattern);
+    if (! _cairo_surface_has_device_transform (destination))
+	return CAIRO_STATUS_SUCCESS;
+
+    status = _cairo_pattern_init_copy (pattern_copy, *pattern);
     if (status)
 	return status;
 
-    if (_cairo_surface_has_device_transform (destination)) {
-	_cairo_pattern_transform (*pattern_out,
-		                  &destination->device_transform_inverse);
-    }
+    _cairo_pattern_transform (pattern_copy,
+			      &destination->device_transform_inverse);
+
 
+    *pattern = pattern_copy;
     return CAIRO_STATUS_SUCCESS;
 }
 
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index f392c8e..a50f13b 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1757,7 +1757,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t    *surface,
 
 static cairo_status_t
 _cairo_svg_surface_emit_pattern (cairo_svg_surface_t   *surface,
-				 cairo_pattern_t       *pattern,
+				 const cairo_pattern_t       *pattern,
 				 cairo_output_stream_t *output,
 				 cairo_bool_t		is_stroke,
 				 const cairo_matrix_t  *parent_matrix)
@@ -1783,12 +1783,12 @@ _cairo_svg_surface_emit_pattern (cairo_svg_surface_t   *surface,
 }
 
 static cairo_status_t
-_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
-				    cairo_svg_surface_t   *surface,
-				    cairo_operator_t       op,
-				    cairo_pattern_t	  *source,
-				    cairo_fill_rule_t	   fill_rule,
-				    cairo_matrix_t	  *parent_matrix)
+_cairo_svg_surface_emit_fill_style (cairo_output_stream_t	*output,
+				    cairo_svg_surface_t		*surface,
+				    cairo_operator_t		 op,
+				    const cairo_pattern_t	*source,
+				    cairo_fill_rule_t		 fill_rule,
+				    cairo_matrix_t		*parent_matrix)
 {
     _cairo_output_stream_printf (output,
 				 "fill-rule:%s;",
@@ -1799,12 +1799,12 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
 }
 
 static cairo_status_t
-_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
-				      cairo_svg_surface_t   *surface,
-				      cairo_operator_t	     op,
-				      cairo_pattern_t	    *source,
-				      cairo_stroke_style_t  *stroke_style,
-				      cairo_matrix_t	    *parent_matrix)
+_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t	    *output,
+				      cairo_svg_surface_t	    *surface,
+				      cairo_operator_t		     op,
+				      const cairo_pattern_t	    *source,
+				      cairo_stroke_style_t	    *stroke_style,
+				      cairo_matrix_t		    *parent_matrix)
 {
     cairo_status_t status;
     const char *line_cap, *line_join;
@@ -1879,13 +1879,13 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
 static cairo_int_status_t
 _cairo_svg_surface_fill_stroke (void			*abstract_surface,
 				cairo_operator_t	 fill_op,
-				cairo_pattern_t		*fill_source,
+				const cairo_pattern_t	*fill_source,
 				cairo_fill_rule_t	 fill_rule,
 				double			 fill_tolerance,
 				cairo_antialias_t	 fill_antialias,
 				cairo_path_fixed_t	*path,
 				cairo_operator_t	 stroke_op,
-				cairo_pattern_t		*stroke_source,
+				const cairo_pattern_t	*stroke_source,
 				cairo_stroke_style_t	*stroke_style,
 				cairo_matrix_t		*stroke_ctm,
 				cairo_matrix_t		*stroke_ctm_inverse,
@@ -1921,7 +1921,7 @@ _cairo_svg_surface_fill_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_svg_surface_fill (void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*source,
+			 const cairo_pattern_t	*source,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
@@ -1974,8 +1974,8 @@ static cairo_status_t
 _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
 			       cairo_svg_surface_t   *surface,
 			       cairo_operator_t	      op,
-			       cairo_pattern_t	     *source,
-			       cairo_pattern_t	     *mask_source,
+			       const cairo_pattern_t	     *source,
+			       const cairo_pattern_t	     *mask_source,
 			       const char	     *extra_attributes)
 {
     cairo_status_t status;
@@ -2013,7 +2013,7 @@ _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,
-			  cairo_pattern_t   *source)
+			  const cairo_pattern_t   *source)
 {
     cairo_status_t status;
     cairo_svg_surface_t *surface = abstract_surface;
@@ -2066,8 +2066,8 @@ _cairo_svg_surface_paint (void		    *abstract_surface,
 static cairo_int_status_t
 _cairo_svg_surface_mask (void		    *abstract_surface,
 			cairo_operator_t     op,
-			cairo_pattern_t	    *source,
-			cairo_pattern_t	    *mask)
+			const cairo_pattern_t	    *source,
+			const cairo_pattern_t	    *mask)
 {
     cairo_status_t status;
     cairo_svg_surface_t *surface = abstract_surface;
@@ -2095,8 +2095,8 @@ _cairo_svg_surface_mask (void		    *abstract_surface,
     assert (_cairo_svg_surface_operation_supported (surface, op, source));
     assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask));
 
-    if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask;
+    if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t*) mask;
 	cairo_content_t content = cairo_surface_get_content (surface_pattern->surface);
 	if (content == CAIRO_CONTENT_ALPHA)
 	    discard_filter = TRUE;
@@ -2148,7 +2148,7 @@ _cairo_svg_surface_mask (void		    *abstract_surface,
 static cairo_int_status_t
 _cairo_svg_surface_stroke (void			*abstract_dst,
 			   cairo_operator_t      op,
-			   cairo_pattern_t	*source,
+			   const cairo_pattern_t *source,
 			   cairo_path_fixed_t	*path,
 			   cairo_stroke_style_t *stroke_style,
 			   cairo_matrix_t	*ctm,
@@ -2185,7 +2185,7 @@ _cairo_svg_surface_stroke (void			*abstract_dst,
 static cairo_int_status_t
 _cairo_svg_surface_show_glyphs (void			*abstract_surface,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*pattern,
+				const cairo_pattern_t	*pattern,
 				cairo_glyph_t		*glyphs,
 				int			 num_glyphs,
 				cairo_scaled_font_t	*scaled_font,
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index c84f5f0..ee516f5 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -123,7 +123,7 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 static cairo_status_t
 _cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface,
 					       cairo_image_surface_t       *image,
-					       cairo_matrix_t              *pattern_matrix)
+					       const cairo_matrix_t              *pattern_matrix)
 {
     cairo_matrix_t mat, upside_down;
     cairo_status_t status;
@@ -182,10 +182,10 @@ _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,
-				  cairo_pattern_t	*source)
+				  const cairo_pattern_t	*source)
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
-    cairo_surface_pattern_t *pattern;
+    const cairo_surface_pattern_t *pattern;
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_status_t status;
@@ -193,7 +193,7 @@ _cairo_type3_glyph_surface_paint (void			*abstract_surface,
     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
 	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 
-    pattern = (cairo_surface_pattern_t *) source;
+    pattern = (const cairo_surface_pattern_t *) source;
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
 	goto fail;
@@ -211,8 +211,8 @@ fail:
 static cairo_int_status_t
 _cairo_type3_glyph_surface_mask (void			*abstract_surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
-				 cairo_pattern_t	*mask)
+				 const cairo_pattern_t	*source,
+				 const cairo_pattern_t	*mask)
 {
     return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask);
 }
@@ -220,7 +220,7 @@ _cairo_type3_glyph_surface_mask (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_type3_glyph_surface_stroke (void			*abstract_surface,
 				   cairo_operator_t	 op,
-				   cairo_pattern_t	*source,
+				   const cairo_pattern_t *source,
 				   cairo_path_fixed_t	*path,
 				   cairo_stroke_style_t	*style,
 				   cairo_matrix_t	*ctm,
@@ -240,7 +240,7 @@ _cairo_type3_glyph_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_type3_glyph_surface_fill (void			*abstract_surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
@@ -259,7 +259,7 @@ _cairo_type3_glyph_surface_fill (void			*abstract_surface,
 static cairo_int_status_t
 _cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
 					cairo_operator_t      op,
-					cairo_pattern_t	     *source,
+					const cairo_pattern_t *source,
 					cairo_glyph_t        *glyphs,
 					int		      num_glyphs,
 					cairo_scaled_font_t  *scaled_font,
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 879cfac..3da64a6 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1359,19 +1359,19 @@ _cairo_win32_scaled_font_glyph_init (void		       *abstract_font,
 }
 
 static cairo_int_status_t
-_cairo_win32_scaled_font_show_glyphs (void		       *abstract_font,
-				      cairo_operator_t    	op,
-				      cairo_pattern_t          *pattern,
-				      cairo_surface_t          *generic_surface,
-				      int                 	source_x,
-				      int                 	source_y,
-				      int			dest_x,
-				      int			dest_y,
-				      unsigned int		width,
-				      unsigned int		height,
-				      cairo_glyph_t	       *glyphs,
-				      int                 	num_glyphs,
-				      int		       *remaining_glyphs)
+_cairo_win32_scaled_font_show_glyphs (void			*abstract_font,
+				      cairo_operator_t		 op,
+				      const cairo_pattern_t	*pattern,
+				      cairo_surface_t		*generic_surface,
+				      int			 source_x,
+				      int			 source_y,
+				      int			 dest_x,
+				      int			 dest_y,
+				      unsigned int		 width,
+				      unsigned int		 height,
+				      cairo_glyph_t		*glyphs,
+				      int			 num_glyphs,
+				      int			*remaining_glyphs)
 {
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 2c2f061..553ef40 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -294,7 +294,7 @@ _cairo_win32_printing_surface_flatten_transparency (cairo_win32_surface_t *surfa
 
 static cairo_status_t
 _cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface,
-                                                  cairo_pattern_t       *source)
+                                                  const cairo_pattern_t *source)
 {
     cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source;
     COLORREF color;
@@ -337,7 +337,7 @@ _cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface,
 
 static cairo_status_t
 _cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface,
-                                                   cairo_pattern_t       *pattern)
+                                                   const cairo_pattern_t *pattern)
 {
     RECT clip;
     cairo_status_t status;
@@ -350,7 +350,7 @@ _cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surfac
     FillRect (surface->dc, &clip, surface->brush);
     _cairo_win32_printing_surface_done_solid_brush (surface);
 
-    return 0;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -411,7 +411,9 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t   *surfa
 	surface->content = CAIRO_CONTENT_COLOR;
 	_cairo_pattern_init_solid (&black, CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
 	source = (cairo_pattern_t*) &black;
-	_cairo_win32_printing_surface_paint_solid_pattern (surface, source);
+	status = _cairo_win32_printing_surface_paint_solid_pattern (surface, source);
+	if (status)
+	    return status;
     }
 
     for (y_tile = top; y_tile < bottom; y_tile++) {
@@ -490,7 +492,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 {
     cairo_status_t status;
     cairo_extend_t extend;
-    cairo_surface_attributes_t pat_attr;
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_surface_t *opaque_surface;
@@ -820,7 +821,7 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
 
 static cairo_int_status_t
 _cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
-                                             cairo_pattern_t       *pattern)
+                                             const cairo_pattern_t *pattern)
 {
     cairo_status_t status;
 
@@ -1034,9 +1035,9 @@ _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,
-                                     cairo_pattern_t  *source)
+_cairo_win32_printing_surface_paint (void			*abstract_surface,
+                                     cairo_operator_t		 op,
+                                     const cairo_pattern_t	*source)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_solid_pattern_t clear;
@@ -1105,15 +1106,15 @@ _cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_stroke (void                 *abstract_surface,
-                                      cairo_operator_t	    op,
-                                      cairo_pattern_t	   *source,
-                                      cairo_path_fixed_t   *path,
-                                      cairo_stroke_style_t *style,
-                                      cairo_matrix_t       *stroke_ctm,
-                                      cairo_matrix_t       *stroke_ctm_inverse,
-                                      double       	    tolerance,
-                                      cairo_antialias_t     antialias)
+_cairo_win32_printing_surface_stroke (void			*abstract_surface,
+                                      cairo_operator_t		 op,
+                                      const cairo_pattern_t	*source,
+                                      cairo_path_fixed_t	*path,
+                                      cairo_stroke_style_t	*style,
+                                      cairo_matrix_t		*stroke_ctm,
+                                      cairo_matrix_t		*stroke_ctm_inverse,
+                                      double			tolerance,
+                                      cairo_antialias_t		antialias)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -1229,12 +1230,12 @@ _cairo_win32_printing_surface_stroke (void                 *abstract_surface,
 
 static cairo_int_status_t
 _cairo_win32_printing_surface_fill (void		        *abstract_surface,
-				    cairo_operator_t	 op,
-				    cairo_pattern_t	*source,
-				    cairo_path_fixed_t	*path,
-				    cairo_fill_rule_t	 fill_rule,
-				    double		 tolerance,
-				    cairo_antialias_t	 antialias)
+				    cairo_operator_t		 op,
+				    const cairo_pattern_t	*source,
+				    cairo_path_fixed_t		*path,
+				    cairo_fill_rule_t		 fill_rule,
+				    double			 tolerance,
+				    cairo_antialias_t		 antialias)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
@@ -1289,7 +1290,7 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
 static cairo_int_status_t
 _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surface,
                                            cairo_operator_t	 op,
-                                           cairo_pattern_t	*source,
+                                           const cairo_pattern_t *source,
                                            cairo_glyph_t        *glyphs,
                                            int			 num_glyphs,
                                            cairo_scaled_font_t  *scaled_font,
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 21b04be..09f6328 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -141,7 +141,7 @@ _cairo_win32_flags_for_dc (HDC dc);
 cairo_int_status_t
 _cairo_win32_surface_show_glyphs (void			*surface,
 				  cairo_operator_t	 op,
-				  cairo_pattern_t	*source,
+				  const cairo_pattern_t	*source,
 				  cairo_glyph_t		*glyphs,
 				  int			 num_glyphs,
 				  cairo_scaled_font_t	*scaled_font,
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 5787e26..05f5188 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -874,8 +874,8 @@ _cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
 
 static cairo_int_status_t
 _cairo_win32_surface_composite (cairo_operator_t	op,
-				cairo_pattern_t       	*pattern,
-				cairo_pattern_t		*mask_pattern,
+				const cairo_pattern_t	*pattern,
+				const cairo_pattern_t	*mask_pattern,
 				void			*abstract_dst,
 				int			src_x,
 				int			src_y,
@@ -1562,7 +1562,7 @@ _cairo_win32_surface_flush (void *abstract_surface)
 cairo_int_status_t
 _cairo_win32_surface_show_glyphs (void			*surface,
 				  cairo_operator_t	 op,
-				  cairo_pattern_t	*source,
+				  const cairo_pattern_t	*source,
 				  cairo_glyph_t		*glyphs,
 				  int			 num_glyphs,
 				  cairo_scaled_font_t	*scaled_font,
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index dede00f..d514659 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -948,10 +948,10 @@ typedef enum {
  * hit the bug and won't be able to use a core protocol fallback.
  */
 static composite_operation_t
-_categorize_composite_operation (cairo_xcb_surface_t *dst,
-				 cairo_operator_t      op,
-				 cairo_pattern_t      *src_pattern,
-				 cairo_bool_t	       have_mask)
+_categorize_composite_operation (cairo_xcb_surface_t	    *dst,
+				 cairo_operator_t	     op,
+				 const cairo_pattern_t	    *src_pattern,
+				 cairo_bool_t		     have_mask)
 
 {
 #if XXX_BUGGY_REPEAT
@@ -1088,8 +1088,8 @@ _render_operator (cairo_operator_t op)
 
 static cairo_int_status_t
 _cairo_xcb_surface_composite (cairo_operator_t		op,
-			      cairo_pattern_t		*src_pattern,
-			      cairo_pattern_t		*mask_pattern,
+			      const cairo_pattern_t	*src_pattern,
+			      const cairo_pattern_t	*mask_pattern,
 			      void			*abstract_dst,
 			      int			src_x,
 			      int			src_y,
@@ -1377,7 +1377,7 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
 
 static cairo_int_status_t
 _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
-					 cairo_pattern_t	*pattern,
+					 const cairo_pattern_t	*pattern,
 					 void			*abstract_dst,
 					 cairo_antialias_t	antialias,
 					 int			src_x,
@@ -1622,13 +1622,13 @@ _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
 				       cairo_scaled_font_t  *scaled_font);
 
 static cairo_int_status_t
-_cairo_xcb_surface_show_glyphs (void                *abstract_dst,
-				 cairo_operator_t     op,
-				 cairo_pattern_t     *src_pattern,
-				 cairo_glyph_t       *glyphs,
-				 int		      num_glyphs,
-				 cairo_scaled_font_t *scaled_font,
-				 int		     *remaining_glyphs);
+_cairo_xcb_surface_show_glyphs (void			*abstract_dst,
+				cairo_operator_t	 op,
+				const cairo_pattern_t	*src_pattern,
+				cairo_glyph_t		*glyphs,
+				int			 num_glyphs,
+				cairo_scaled_font_t	*scaled_font,
+				int			*remaining_glyphs);
 
 static cairo_bool_t
 _cairo_xcb_surface_is_similar (void *surface_a,
@@ -2420,13 +2420,13 @@ _cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
 }
 
 static cairo_int_status_t
-_cairo_xcb_surface_show_glyphs (void                *abstract_dst,
-				cairo_operator_t     op,
-				cairo_pattern_t     *src_pattern,
-				cairo_glyph_t       *glyphs,
-				int		      num_glyphs,
-				cairo_scaled_font_t *scaled_font,
-				int		     *remaining_glyphs)
+_cairo_xcb_surface_show_glyphs (void			*abstract_dst,
+				cairo_operator_t	 op,
+				const cairo_pattern_t	*src_pattern,
+				cairo_glyph_t		*glyphs,
+				int			 num_glyphs,
+				cairo_scaled_font_t	*scaled_font,
+				int			*remaining_glyphs)
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xcb_surface_t *dst = abstract_dst;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index ba38f5d..1d35843 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -82,7 +82,7 @@ _native_byte_order_lsb (void);
 static cairo_int_status_t
 _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_operator_t     op,
-				 cairo_pattern_t     *src_pattern,
+				 const cairo_pattern_t  *src_pattern,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
 				 cairo_scaled_font_t *scaled_font,
@@ -1229,7 +1229,7 @@ _cairo_xlib_surface_clone_similar (void			*abstract_surface,
 
 static cairo_surface_t *
 _cairo_xlib_surface_create_solid_pattern_surface (void                  *abstract_surface,
-						  cairo_solid_pattern_t *solid_pattern)
+						  const cairo_solid_pattern_t *solid_pattern)
 {
     /* This function's only responsibility is to create a proper surface
      * for when XRender is not available.  The proper surface is a xlib
@@ -1531,7 +1531,7 @@ typedef enum {
 static composite_operation_t
 _categorize_composite_operation (cairo_xlib_surface_t *dst,
 				 cairo_operator_t      op,
-				 cairo_pattern_t      *src_pattern,
+				 const cairo_pattern_t *src_pattern,
 				 cairo_bool_t	       have_mask)
 
 {
@@ -1680,8 +1680,8 @@ _render_operator (cairo_operator_t op)
 
 static cairo_int_status_t
 _cairo_xlib_surface_composite (cairo_operator_t		op,
-			       cairo_pattern_t		*src_pattern,
-			       cairo_pattern_t		*mask_pattern,
+			       const cairo_pattern_t	*src_pattern,
+			       const cairo_pattern_t	*mask_pattern,
 			       void			*abstract_dst,
 			       int			src_x,
 			       int			src_y,
@@ -2071,7 +2071,7 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst,
 
 static cairo_int_status_t
 _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	op,
-					  cairo_pattern_t	*pattern,
+					  const cairo_pattern_t	*pattern,
 					  void			*abstract_dst,
 					  cairo_antialias_t	antialias,
 					  int			src_x,
@@ -3945,7 +3945,7 @@ _cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst,
 static cairo_int_status_t
 _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_operator_t     op,
-				 cairo_pattern_t     *src_pattern,
+				 const cairo_pattern_t *src_pattern,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
 				 cairo_scaled_font_t *scaled_font,
diff --git a/src/cairoint.h b/src/cairoint.h
index baa0cb5..9e1cd7d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -453,7 +453,7 @@ struct _cairo_scaled_font_backend {
     cairo_warn cairo_int_status_t
     (*show_glyphs)	(void			*scaled_font,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*pattern,
+			 const cairo_pattern_t	*pattern,
 			 cairo_surface_t	*surface,
 			 int			 source_x,
 			 int			 source_y,
@@ -584,8 +584,8 @@ struct _cairo_surface_backend {
     /* XXX: dst should be the first argument for consistency */
     cairo_warn cairo_int_status_t
     (*composite)		(cairo_operator_t	 op,
-				 cairo_pattern_t       	*src,
-				 cairo_pattern_t	*mask,
+				 const cairo_pattern_t	*src,
+				 const cairo_pattern_t	*mask,
 				 void			*dst,
 				 int			 src_x,
 				 int			 src_y,
@@ -606,7 +606,7 @@ struct _cairo_surface_backend {
     /* XXX: dst should be the first argument for consistency */
     cairo_warn cairo_int_status_t
     (*composite_trapezoids)	(cairo_operator_t	 op,
-				 cairo_pattern_t	*pattern,
+				 const cairo_pattern_t	*pattern,
 				 void			*dst,
 				 cairo_antialias_t	 antialias,
 				 int			 src_x,
@@ -688,7 +688,7 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*old_show_glyphs)		(cairo_scaled_font_t	        *font,
 				 cairo_operator_t		 op,
-				 cairo_pattern_t		*pattern,
+				 const cairo_pattern_t		*pattern,
 				 void				*surface,
 				 int				 source_x,
 				 int				 source_y,
@@ -726,18 +726,18 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*paint)			(void			*surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source);
+				 const cairo_pattern_t	*source);
 
     cairo_warn cairo_int_status_t
     (*mask)			(void			*surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
-				 cairo_pattern_t	*mask);
+				 const cairo_pattern_t	*source,
+				 const cairo_pattern_t	*mask);
 
     cairo_warn cairo_int_status_t
     (*stroke)			(void			*surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_stroke_style_t	*style,
 				 cairo_matrix_t		*ctm,
@@ -748,7 +748,7 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*fill)			(void			*surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
@@ -757,7 +757,7 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*show_glyphs)		(void			*surface,
 				 cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
@@ -777,13 +777,13 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*fill_stroke)		(void			*surface,
 				 cairo_operator_t	 fill_op,
-				 cairo_pattern_t	*fill_source,
+				 const cairo_pattern_t	*fill_source,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 fill_tolerance,
 				 cairo_antialias_t	 fill_antialias,
 				 cairo_path_fixed_t	*path,
 				 cairo_operator_t	 stroke_op,
-				 cairo_pattern_t	*stroke_source,
+				 const cairo_pattern_t	*stroke_source,
 				 cairo_stroke_style_t	*stroke_style,
 				 cairo_matrix_t		*stroke_ctm,
 				 cairo_matrix_t		*stroke_ctm_inverse,
@@ -792,8 +792,8 @@ struct _cairo_surface_backend {
 
     cairo_surface_t *
     (*create_solid_pattern_surface)
-			        (void			*surface,
-				 cairo_solid_pattern_t  *solid_pattern);
+			        (void			      *surface,
+				 const cairo_solid_pattern_t  *solid_pattern);
 
     cairo_bool_t
     (*has_show_text_glyphs)	(void			    *surface);
@@ -801,7 +801,7 @@ struct _cairo_surface_backend {
     cairo_warn cairo_int_status_t
     (*show_text_glyphs)		(void			    *surface,
 				 cairo_operator_t	     op,
-				 cairo_pattern_t	    *source,
+				 const cairo_pattern_t	    *source,
 				 const char		    *utf8,
 				 int			     utf8_len,
 				 cairo_glyph_t		    *glyphs,
@@ -1581,7 +1581,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
 cairo_private cairo_status_t
 _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
 				cairo_operator_t     op,
-				cairo_pattern_t	    *source,
+				const cairo_pattern_t *source,
 				cairo_surface_t	    *surface,
 				int		     source_x,
 				int		     source_y,
@@ -1676,12 +1676,12 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
 
 cairo_private cairo_surface_t *
 _cairo_surface_create_solid_pattern_surface (cairo_surface_t	   *other,
-					     cairo_solid_pattern_t *solid_pattern);
+					     const cairo_solid_pattern_t *solid_pattern);
 
 cairo_private cairo_int_status_t
 _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t	    *other,
 					      cairo_surface_t       *solid_surface,
-					      cairo_solid_pattern_t *solid_pattern);
+					      const cairo_solid_pattern_t *solid_pattern);
 
 cairo_private void
 _cairo_surface_init (cairo_surface_t			*surface,
@@ -1697,8 +1697,8 @@ _cairo_surface_get_clip_mode (cairo_surface_t *surface);
 
 cairo_private cairo_status_t
 _cairo_surface_composite (cairo_operator_t	op,
-			  cairo_pattern_t	*src,
-			  cairo_pattern_t	*mask,
+			  const cairo_pattern_t	*src,
+			  const cairo_pattern_t	*mask,
 			  cairo_surface_t	*dst,
 			  int			src_x,
 			  int			src_y,
@@ -1734,24 +1734,24 @@ _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 cairo_private cairo_status_t
 _cairo_surface_paint (cairo_surface_t	*surface,
 		      cairo_operator_t	 op,
-		      cairo_pattern_t	*source);
+		      const cairo_pattern_t *source);
 
 cairo_private cairo_status_t
 _cairo_surface_mask (cairo_surface_t	*surface,
 		     cairo_operator_t	 op,
-		     cairo_pattern_t	*source,
-		     cairo_pattern_t	*mask);
+		     const cairo_pattern_t	*source,
+		     const cairo_pattern_t	*mask);
 
 cairo_private cairo_status_t
 _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 			    cairo_operator_t	     fill_op,
-			    cairo_pattern_t	    *fill_source,
+			    const cairo_pattern_t   *fill_source,
 			    cairo_fill_rule_t	     fill_rule,
 			    double		     fill_tolerance,
 			    cairo_antialias_t	     fill_antialias,
 			    cairo_path_fixed_t	    *path,
 			    cairo_operator_t	     stroke_op,
-			    cairo_pattern_t	    *stroke_source,
+			    const cairo_pattern_t   *stroke_source,
 			    cairo_stroke_style_t    *stroke_style,
 			    cairo_matrix_t	    *stroke_ctm,
 			    cairo_matrix_t	    *stroke_ctm_inverse,
@@ -1761,7 +1761,7 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 cairo_private cairo_status_t
 _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_operator_t		 op,
-		       cairo_pattern_t		*source,
+		       const cairo_pattern_t	*source,
 		       cairo_path_fixed_t	*path,
 		       cairo_stroke_style_t	*style,
 		       cairo_matrix_t		*ctm,
@@ -1772,7 +1772,7 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 cairo_private cairo_status_t
 _cairo_surface_fill (cairo_surface_t	*surface,
 		     cairo_operator_t	 op,
-		     cairo_pattern_t	*source,
+		     const cairo_pattern_t *source,
 		     cairo_path_fixed_t	*path,
 		     cairo_fill_rule_t	 fill_rule,
 		     double		 tolerance,
@@ -1781,7 +1781,7 @@ _cairo_surface_fill (cairo_surface_t	*surface,
 cairo_private cairo_status_t
 _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 cairo_operator_t	     op,
-				 cairo_pattern_t	    *source,
+				 const cairo_pattern_t	    *source,
 				 const char		    *utf8,
 				 int			     utf8_len,
 				 cairo_glyph_t		    *glyphs,
@@ -1793,7 +1793,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 
 cairo_private cairo_status_t
 _cairo_surface_composite_trapezoids (cairo_operator_t	op,
-				     cairo_pattern_t	*pattern,
+				     const cairo_pattern_t *pattern,
 				     cairo_surface_t	*dst,
 				     cairo_antialias_t	antialias,
 				     int		src_x,
@@ -1885,7 +1885,7 @@ _cairo_surface_get_extents (cairo_surface_t         *surface,
 cairo_private cairo_status_t
 _cairo_surface_old_show_glyphs (cairo_scaled_font_t	*scaled_font,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*pattern,
+				const cairo_pattern_t	*pattern,
 				cairo_surface_t		*surface,
 				int			 source_x,
 				int			 source_y,
@@ -2318,7 +2318,7 @@ cairo_private cairo_bool_t
 _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
 
 cairo_private cairo_int_status_t
-_cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
+_cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 				cairo_surface_t		   *dst,
 				int			   x,
 				int			   y,
@@ -2328,13 +2328,13 @@ _cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
 				cairo_surface_attributes_t *attributes);
 
 cairo_private void
-_cairo_pattern_release_surface (cairo_pattern_t		   *pattern,
+_cairo_pattern_release_surface (const cairo_pattern_t	   *pattern,
 				cairo_surface_t		   *surface,
 				cairo_surface_attributes_t *attributes);
 
 cairo_private cairo_int_status_t
-_cairo_pattern_acquire_surfaces (cairo_pattern_t	    *src,
-				 cairo_pattern_t	    *mask,
+_cairo_pattern_acquire_surfaces (const cairo_pattern_t	    *src,
+				 const cairo_pattern_t	    *mask,
 				 cairo_surface_t	    *dst,
 				 int			    src_x,
 				 int			    src_y,
@@ -2348,8 +2348,8 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t	    *src,
 				 cairo_surface_attributes_t *mask_attributes);
 
 cairo_private cairo_status_t
-_cairo_pattern_get_extents (cairo_pattern_t	    *pattern,
-			    cairo_rectangle_int_t   *extents);
+_cairo_pattern_get_extents (const cairo_pattern_t	    *pattern,
+			    cairo_rectangle_int_t           *extents);
 
 cairo_private void
 _cairo_pattern_reset_static_data (void);
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 6038430..f19cbd6 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -194,7 +194,7 @@ _test_meta_surface_get_extents (void			*abstract_surface,
 static cairo_int_status_t
 _test_meta_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
-			  cairo_pattern_t	*source)
+			  const cairo_pattern_t	*source)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -206,8 +206,8 @@ _test_meta_surface_paint (void			*abstract_surface,
 static cairo_int_status_t
 _test_meta_surface_mask (void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*source,
-			 cairo_pattern_t	*mask)
+			 const cairo_pattern_t	*source,
+			 const cairo_pattern_t	*mask)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -217,15 +217,15 @@ _test_meta_surface_mask (void			*abstract_surface,
 }
 
 static cairo_int_status_t
-_test_meta_surface_stroke (void			*abstract_surface,
-			   cairo_operator_t	 op,
-			   cairo_pattern_t	*source,
-			   cairo_path_fixed_t	*path,
-			   cairo_stroke_style_t	*style,
-			   cairo_matrix_t	*ctm,
-			   cairo_matrix_t	*ctm_inverse,
-			   double		 tolerance,
-			   cairo_antialias_t	 antialias)
+_test_meta_surface_stroke (void				*abstract_surface,
+			   cairo_operator_t		 op,
+			   const cairo_pattern_t	*source,
+			   cairo_path_fixed_t		*path,
+			   cairo_stroke_style_t		*style,
+			   cairo_matrix_t		*ctm,
+			   cairo_matrix_t		*ctm_inverse,
+			   double			 tolerance,
+			   cairo_antialias_t		 antialias)
 {
     test_meta_surface_t *surface = abstract_surface;
 
@@ -240,7 +240,7 @@ _test_meta_surface_stroke (void			*abstract_surface,
 static cairo_int_status_t
 _test_meta_surface_fill (void			*abstract_surface,
 			 cairo_operator_t	 op,
-			 cairo_pattern_t	*source,
+			 const cairo_pattern_t	*source,
 			 cairo_path_fixed_t	*path,
 			 cairo_fill_rule_t	 fill_rule,
 			 double			 tolerance,
@@ -266,7 +266,7 @@ _test_meta_surface_has_show_text_glyphs (void *abstract_surface)
 static cairo_int_status_t
 _test_meta_surface_show_text_glyphs (void		    *abstract_surface,
 				     cairo_operator_t	     op,
-				     cairo_pattern_t	    *source,
+				     const cairo_pattern_t  *source,
 				     const char		    *utf8,
 				     int		     utf8_len,
 				     cairo_glyph_t	    *glyphs,
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 354f95d..ba80a10 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -169,7 +169,7 @@ _test_paginated_surface_get_extents (void			*abstract_surface,
 static cairo_int_status_t
 _test_paginated_surface_paint (void		*abstract_surface,
 			       cairo_operator_t	 op,
-			       cairo_pattern_t	*source)
+			       const cairo_pattern_t	*source)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -182,8 +182,8 @@ _test_paginated_surface_paint (void		*abstract_surface,
 static cairo_int_status_t
 _test_paginated_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
-			      cairo_pattern_t	*source,
-			      cairo_pattern_t	*mask)
+			      const cairo_pattern_t	*source,
+			      const cairo_pattern_t	*mask)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -194,15 +194,15 @@ _test_paginated_surface_mask (void		*abstract_surface,
 }
 
 static cairo_int_status_t
-_test_paginated_surface_stroke (void			*abstract_surface,
-				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
-				cairo_path_fixed_t	*path,
-				cairo_stroke_style_t	*style,
-				cairo_matrix_t		*ctm,
-				cairo_matrix_t		*ctm_inverse,
-				double			 tolerance,
-				cairo_antialias_t	 antialias)
+_test_paginated_surface_stroke (void				*abstract_surface,
+				cairo_operator_t		 op,
+				const cairo_pattern_t		*source,
+				cairo_path_fixed_t		*path,
+				cairo_stroke_style_t		*style,
+				cairo_matrix_t			*ctm,
+				cairo_matrix_t			*ctm_inverse,
+				double				 tolerance,
+				cairo_antialias_t		 antialias)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -216,13 +216,13 @@ _test_paginated_surface_stroke (void			*abstract_surface,
 }
 
 static cairo_int_status_t
-_test_paginated_surface_fill (void			*abstract_surface,
-			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
-			      cairo_path_fixed_t	*path,
-			      cairo_fill_rule_t		 fill_rule,
-			      double			 tolerance,
-			      cairo_antialias_t		 antialias)
+_test_paginated_surface_fill (void				*abstract_surface,
+			      cairo_operator_t			 op,
+			      const cairo_pattern_t		*source,
+			      cairo_path_fixed_t		*path,
+			      cairo_fill_rule_t			 fill_rule,
+			      double				 tolerance,
+			      cairo_antialias_t			 antialias)
 {
     test_paginated_surface_t *surface = abstract_surface;
 
@@ -245,7 +245,7 @@ _test_paginated_surface_has_show_text_glyphs (void *abstract_surface)
 static cairo_int_status_t
 _test_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					  cairo_operator_t	     op,
-					  cairo_pattern_t	    *source,
+					  const cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
commit 9d2189afbd2aa1413f620a4d35016ef3be3fc0e9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 18:29:02 2008 +0100

    [pattern] Do not recompute the inverse if setting an identical matrix.
    
    More micro-optimisation.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 81fa62a..064eeb6 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1055,6 +1055,9 @@ cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
     if (pattern->status)
 	return;
 
+    if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
+	return;
+
     pattern->matrix = *matrix;
 
     inverse = *matrix;
commit 2c277ddbea42222130b8b1c2a2b4934503b40188
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 18:17:49 2008 +0100

    [matrix] Avoid error correction overhead for translation matrices.
    
    We can only correct rounding errors between cairo and pixman matrices for
    scaled matrices - so skip the inversion and point transformation overhead
    for simple translation matrices.

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index ca18323..f01353e 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -813,8 +813,8 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
         *pixman_transform = pixman_identity_transform;
     }
     else {
-        cairo_matrix_t inv = *matrix;
-        double x = 0, y = 0;
+        cairo_matrix_t inv;
+        double x,y;
         pixman_vector_t vector;
 
         pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
@@ -839,11 +839,16 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
          * space and adjust pixman's transform to agree with cairo's at
          * that point. */
 
+	if (_cairo_matrix_is_translation (matrix))
+	    return;
+
         /* Note: If we can't invert the transformation, skip the adjustment. */
+        inv = *matrix;
         if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
             return;
 
         /* find the device space coordinate that maps to (0, 0) */
+        x = 0, y = 0;
         cairo_matrix_transform_point (&inv, &x, &y);
 
         /* transform the resulting device space coordinate back
@@ -852,7 +857,7 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
         vector.vector[1] = _cairo_fixed_16_16_from_double (y);
         vector.vector[2] = 1 << 16;
 
-        if (!pixman_transform_point_3d (pixman_transform, &vector))
+        if (! pixman_transform_point_3d (pixman_transform, &vector))
             return;
 
         /* Ideally, the vector should now be (0, 0). We can now compensate
commit 57a1d932f3e9d79f3259a536ec2f45f020d46de5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 18:12:10 2008 +0100

    [array] Rearrange user_data_fini() to optimize common case.
    
    Micro-optimisation to avoid the _cairo_array_index() for the common case
    of 0 elements.

diff --git a/src/cairo-array.c b/src/cairo-array.c
index b2790c8..f38cfe3 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -382,14 +382,18 @@ _cairo_user_data_array_init (cairo_user_data_array_t *array)
 void
 _cairo_user_data_array_fini (cairo_user_data_array_t *array)
 {
-    int i, num_slots;
-    cairo_user_data_slot_t *slots;
+    unsigned int num_slots;
 
     num_slots = array->num_elements;
-    slots = _cairo_array_index (array, 0);
-    for (i = 0; i < num_slots; i++) {
-	if (slots[i].user_data != NULL && slots[i].destroy != NULL)
-	    slots[i].destroy (slots[i].user_data);
+    if (num_slots) {
+	cairo_user_data_slot_t *slots;
+
+	slots = _cairo_array_index (array, 0);
+	do {
+	    if (slots->user_data != NULL && slots->destroy != NULL)
+		slots->destroy (slots->user_data);
+	    slots++;
+	} while (--num_slots);
     }
 
     _cairo_array_fini (array);
commit 2852127c72fa6cfe246e6ece0433be6c3f2a93ab
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 18:04:30 2008 +0100

    [cairoint] Add a few cairo_pure.
    
    Start marking up the prototypes with function attributes - first the
    obvious pure functions.

diff --git a/src/cairoint.h b/src/cairoint.h
index 43c5ae8..baa0cb5 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1274,10 +1274,10 @@ _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
 			  cairo_path_fixed_t  *path);
 
 cairo_private cairo_bool_t
-_cairo_operator_bounded_by_mask (cairo_operator_t op);
+_cairo_operator_bounded_by_mask (cairo_operator_t op) cairo_pure;
 
 cairo_private cairo_bool_t
-_cairo_operator_bounded_by_source (cairo_operator_t op);
+_cairo_operator_bounded_by_source (cairo_operator_t op) cairo_pure;
 
 /* cairo-color.c */
 cairo_private const cairo_color_t *
@@ -1288,7 +1288,7 @@ _cairo_stock_color (cairo_stock_t stock);
 #define CAIRO_COLOR_TRANSPARENT _cairo_stock_color (CAIRO_STOCK_TRANSPARENT)
 
 cairo_private uint16_t
-_cairo_color_double_to_short (double d);
+_cairo_color_double_to_short (double d) cairo_pure;
 
 cairo_private void
 _cairo_color_init (cairo_color_t *color);
@@ -1987,13 +1987,13 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
 				       == 0))
 
 cairo_private int
-_cairo_format_bits_per_pixel (cairo_format_t format);
+_cairo_format_bits_per_pixel (cairo_format_t format) cairo_pure;
 
 cairo_private cairo_format_t
-_cairo_format_from_content (cairo_content_t content);
+_cairo_format_from_content (cairo_content_t content) cairo_pure;
 
 cairo_private cairo_content_t
-_cairo_content_from_format (cairo_format_t format);
+_cairo_content_from_format (cairo_format_t format) cairo_pure;
 
 cairo_private cairo_surface_t *
 _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,


More information about the cairo-commit mailing list