[cairo-commit] 3 commits - src/cairo-compositor.c src/cairo-damage.c src/cairo-damage-private.h src/cairo.h src/cairo-image-compositor.c src/cairo-image-source.c src/cairo-image-surface.c src/cairo-image-surface-private.h src/cairoint.h src/cairo-region.c src/cairo-region-private.h src/cairo-surface-backend-private.h src/cairo-surface.c src/cairo-surface-private.h src/cairo-system.c src/cairo-traps-compositor.c src/cairo-types-private.h src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c src/Makefile.sources src/win32

Chris Wilson ickle at kemper.freedesktop.org
Wed Feb 15 06:43:24 PST 2012


 src/Makefile.sources                     |   20 
 src/cairo-compositor.c                   |   21 
 src/cairo-damage-private.h               |   82 +
 src/cairo-damage.c                       |  214 ++
 src/cairo-image-compositor.c             |   39 
 src/cairo-image-source.c                 |   25 
 src/cairo-image-surface-private.h        |    9 
 src/cairo-image-surface.c                |   31 
 src/cairo-region-private.h               |    6 
 src/cairo-region.c                       |   32 
 src/cairo-surface-backend-private.h      |   10 
 src/cairo-surface-private.h              |   11 
 src/cairo-surface.c                      |   37 
 src/cairo-system.c                       |   97 -
 src/cairo-traps-compositor.c             |   62 
 src/cairo-types-private.h                |    1 
 src/cairo-win32-font.c                   | 2437 ------------------------------
 src/cairo-win32-printing-surface.c       | 1915 ------------------------
 src/cairo-win32-private.h                |  219 --
 src/cairo-win32-surface.c                | 2098 --------------------------
 src/cairo.h                              |    2 
 src/cairoint.h                           |    6 
 src/win32/cairo-win32-debug.c            |   87 +
 src/win32/cairo-win32-device.c           |  189 ++
 src/win32/cairo-win32-display-surface.c  | 1031 +++++++++++++
 src/win32/cairo-win32-font.c             | 2444 +++++++++++++++++++++++++++++++
 src/win32/cairo-win32-gdi-compositor.c   |  646 ++++++++
 src/win32/cairo-win32-printing-surface.c | 1917 ++++++++++++++++++++++++
 src/win32/cairo-win32-private.h          |  226 ++
 src/win32/cairo-win32-surface.c          |  319 ++++
 src/win32/cairo-win32-system.c           |   89 +
 31 files changed, 7547 insertions(+), 6775 deletions(-)

New commits:
commit ae3319890eacd1c8282ca6df7b263ac74abb5f8d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 12 11:25:07 2012 +0000

    win32: Rebase on the new compositor infrastructure
    
    Try and undo all the damage that has acrued over the years by plugging
    into the compositor pipeline.
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=42739
    References: https://bugs.freedesktop.org/show_bug.cgi?id=42821
    References: https://bugs.freedesktop.org/show_bug.cgi?id=33081
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 22a7b47..19a14a7 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -209,7 +209,6 @@ cairo_sources = \
 	cairo-surface-snapshot.c \
 	cairo-surface-subsurface.c \
 	cairo-surface-wrapper.c \
-	cairo-system.c \
 	cairo-time.c \
 	cairo-tor-scan-converter.c \
 	cairo-tor22-scan-converter.c \
@@ -336,7 +335,12 @@ cairo_quartz_font_sources = cairo-quartz-font.c
 cairo_win32_headers = cairo-win32.h
 cairo_win32_private = win32/cairo-win32-private.h
 cairo_win32_sources = \
+	win32/cairo-win32-debug.c \
+	win32/cairo-win32-device.c \
+	win32/cairo-win32-gdi-compositor.c \
+	win32/cairo-win32-system.c \
 	win32/cairo-win32-surface.c \
+	win32/cairo-win32-display-surface.c \
 	win32/cairo-win32-printing-surface.c \
 	$(NULL)
 cairo_win32_font_sources = \
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 6c409e9..7c044c4 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -93,6 +93,8 @@ draw_image_boxes (void *_dst,
     struct _cairo_boxes_chunk *chunk;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
 	for (i = 0; i < chunk->count; i++) {
 	    cairo_box_t *b = &chunk->base[i];
@@ -279,6 +281,8 @@ fill_rectangles (void			*_dst,
     uint32_t pixel;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (fill_reduces_to_source (op, color, dst) &&
 	color_to_pixel (color, dst->pixman_format, &pixel))
     {
@@ -321,6 +325,8 @@ fill_boxes (void		*_dst,
     uint32_t pixel;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (fill_reduces_to_source (op, color, dst) &&
 	color_to_pixel (color, dst->pixman_format, &pixel))
     {
@@ -379,6 +385,9 @@ composite (void			*_dst,
 {
     cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
     cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (mask) {
 	pixman_image_composite32 (_pixman_operator (op),
 				  src->pixman_image, mask->pixman_image, to_pixman_image (_dst),
@@ -415,6 +424,8 @@ lerp (void			*_dst,
     cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
     cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
 #if PIXMAN_HAS_OP_LERP
     pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
 			      src->pixman_image, mask->pixman_image, dst->pixman_image,
@@ -424,6 +435,10 @@ lerp (void			*_dst,
 			      width,  height);
 #else
     /* Punch the clip out of the destination */
+    TRACE ((stderr, "%s - OUT_REVERSE (mask=%d/%p, dst=%d/%p)\n",
+	    __FUNCTION__,
+	    mask->base.unique_id, mask->pixman_image,
+	    dst->base.unique_id, dst->pixman_image));
     pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
 			      mask->pixman_image, NULL, dst->pixman_image,
 			      mask_x, mask_y,
@@ -432,6 +447,11 @@ lerp (void			*_dst,
 			      width,  height);
 
     /* Now add the two results together */
+    TRACE ((stderr, "%s - ADD (src=%d/%p, mask=%d/%p, dst=%d/%p)\n",
+	    __FUNCTION__,
+	    src->base.unique_id, src->pixman_image,
+	    mask->base.unique_id, mask->pixman_image,
+	    dst->base.unique_id, dst->pixman_image));
     pixman_image_composite32 (PIXMAN_OP_ADD,
 			      src->pixman_image, mask->pixman_image, dst->pixman_image,
 			      src_x,  src_y,
@@ -464,6 +484,7 @@ composite_boxes (void			*_dst,
     int i;
 
     /* XXX consider using a region? saves multiple prepare-composite */
+    TRACE ((stderr, "%s\n", __FUNCTION__));
 
     if (((cairo_surface_t *)_dst)->is_clear &&
 	(op == CAIRO_OPERATOR_SOURCE ||
@@ -612,6 +633,8 @@ composite_traps (void			*_dst,
     pixman_image_t *mask;
     pixman_format_code_t format;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     /* Special case adding trapezoids onto a mask surface; we want to avoid
      * creating an intermediate temporary mask unnecessarily.
      *
@@ -690,6 +713,8 @@ composite_tristrip (void			*_dst,
     pixman_image_t *mask;
     pixman_format_code_t format;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (strip->num_points < 3)
 	return CAIRO_STATUS_SUCCESS;
 
@@ -745,6 +770,8 @@ composite_one_glyph (void				*_dst,
     cairo_status_t status;
     int x, y;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = _cairo_scaled_glyph_lookup (info->font,
 					 info->glyphs[0].index,
 					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
@@ -794,6 +821,8 @@ composite_glyphs_via_mask (void				*_dst,
     cairo_status_t status;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     /* XXX convert the glyphs to common formats a8/a8r8g8b8 to hit
      * optimised paths through pixman. Should we increase the bit
      * depth of the target surface, we should reconsider the appropriate
@@ -916,6 +945,8 @@ composite_glyphs (void				*_dst,
     cairo_status_t status;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (info->num_glyphs == 1)
 	return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
 
@@ -1196,6 +1227,8 @@ span_renderer_init (cairo_abstract_span_renderer_t	*_r,
     int src_x, src_y;
     int mask_x, mask_y;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (op == CAIRO_OPERATOR_CLEAR) {
 	op = PIXMAN_OP_LERP_CLEAR;
     } else if (dst->base.is_clear &&
@@ -1281,6 +1314,8 @@ span_renderer_fini (cairo_abstract_span_renderer_t *_r,
 {
     cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (status == CAIRO_INT_STATUS_SUCCESS && r->base.finish)
 	r->base.finish (r);
 
@@ -1426,6 +1461,8 @@ span_renderer_init (cairo_abstract_span_renderer_t	*_r,
     const cairo_pattern_t *source = &composite->source_pattern.base;
     cairo_operator_t op = composite->op;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     r->composite = composite;
     r->mask = NULL;
     r->src = NULL;
@@ -1531,6 +1568,8 @@ span_renderer_fini (cairo_abstract_span_renderer_t *_r,
 {
     cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
 	const cairo_composite_rectangles_t *composite = r->composite;
 
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index 2c94379..58a18e3 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -71,6 +71,8 @@ _pixman_transparent_image (void)
 {
     pixman_image_t *image;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     image = __pixman_transparent_image;
     if (unlikely (image == NULL)) {
 	pixman_color_t color;
@@ -101,6 +103,8 @@ _pixman_black_image (void)
 {
     pixman_image_t *image;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     image = __pixman_black_image;
     if (unlikely (image == NULL)) {
 	pixman_color_t color;
@@ -131,6 +135,8 @@ _pixman_white_image (void)
 {
     pixman_image_t *image;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     image = __pixman_white_image;
     if (unlikely (image == NULL)) {
 	pixman_color_t color;
@@ -175,18 +181,21 @@ static int n_cached;
 static pixman_image_t *
 _pixman_transparent_image (void)
 {
+    TRACE ((stderr, "%s\n", __FUNCTION__));
     return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
 }
 
 static pixman_image_t *
 _pixman_black_image (void)
 {
+    TRACE ((stderr, "%s\n", __FUNCTION__));
     return _pixman_image_for_color (CAIRO_COLOR_BLACK);
 }
 
 static pixman_image_t *
 _pixman_white_image (void)
 {
+    TRACE ((stderr, "%s\n", __FUNCTION__));
     return _pixman_image_for_color (CAIRO_COLOR_WHITE);
 }
 #endif /* !PIXMAN_HAS_ATOMIC_OPS */
@@ -294,6 +303,8 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
     unsigned int i;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
 	pixman_stops = _cairo_malloc_ab (pattern->n_stops,
 					 sizeof(pixman_gradient_stop_t));
@@ -384,6 +395,8 @@ _pixman_image_for_mesh (const cairo_mesh_pattern_t *pattern,
     pixman_image_t *image;
     int width, height;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     *tx = -extents->x;
     *ty = -extents->y;
     width = extents->width;
@@ -437,6 +450,8 @@ _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
     uint32_t pixel;
     pixman_color_t color;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     switch (image->format) {
     default:
     case CAIRO_FORMAT_INVALID:
@@ -607,6 +622,8 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
     cairo_matrix_t *m, matrix;
     int tx = 0, ty = 0;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     *ix = *iy = 0;
 
     source = _cairo_pattern_get_source (pattern, &limit);
@@ -707,6 +724,8 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
     cairo_extend_t extend = pattern->base.extend;
     pixman_image_t *pixman_image;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     *ix = *iy = 0;
     pixman_image = NULL;
     if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
@@ -915,6 +934,8 @@ _pixman_image_for_raster (cairo_image_surface_t *dst,
     cairo_status_t status;
     cairo_surface_t *surface;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     *ix = *iy = 0;
 
     surface = _cairo_raster_source_pattern_acquire (&pattern->base,
@@ -977,6 +998,8 @@ _pixman_image_for_pattern (cairo_image_surface_t *dst,
 {
     *tx = *ty = 0;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (pattern == NULL)
 	return _pixman_white_image ();
 
@@ -1034,6 +1057,8 @@ _cairo_image_source_create_for_pattern (cairo_surface_t *dst,
 {
     cairo_image_source_t *source;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     source = malloc (sizeof (cairo_image_source_t));
     if (unlikely (source == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 30713a8..3951793 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -50,6 +50,7 @@ struct _cairo_image_surface {
 
     pixman_image_t *pixman_image;
     const cairo_compositor_t *compositor;
+    cairo_surface_t *parent;
 
     pixman_format_code_t pixman_format;
     cairo_format_t format;
@@ -64,6 +65,7 @@ struct _cairo_image_surface {
     unsigned transparency : 2;
     unsigned color : 2;
 };
+#define to_image_surface(S) ((cairo_image_surface_t *)(S))
 
 /* A wrapper for holding pixman images returned by create_for_pattern */
 typedef struct _cairo_image_source {
@@ -201,6 +203,13 @@ _pixman_image_add_tristrip (pixman_image_t *image,
 			    int dst_x, int dst_y,
 			    cairo_tristrip_t *strip);
 
+static inline void
+_cairo_image_surface_set_parent (cairo_image_surface_t *image,
+				 cairo_surface_t *parent)
+{
+    image->parent = parent;
+}
+
 /**
  * _cairo_surface_is_image:
  * @surface: a #cairo_surface_t
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index fede14c..66f024c 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -147,6 +147,7 @@ _cairo_image_surface_init (cairo_image_surface_t *surface,
 			   pixman_image_t	*pixman_image,
 			   pixman_format_code_t	 pixman_format)
 {
+    surface->parent = NULL;
     surface->pixman_image = pixman_image;
 
     surface->pixman_format = pixman_format;
@@ -714,7 +715,7 @@ _cairo_format_bits_per_pixel (cairo_format_t format)
     }
 }
 
-    static cairo_surface_t *
+static cairo_surface_t *
 _cairo_image_surface_create_similar (void	       *abstract_other,
 				     cairo_content_t	content,
 				     int		width,
@@ -722,6 +723,8 @@ _cairo_image_surface_create_similar (void	       *abstract_other,
 {
     cairo_image_surface_t *other = abstract_other;
 
+    TRACE ((stderr, "%s (other=%u)\n", __FUNCTION__, other->base.unique_id));
+
     if (! _cairo_image_surface_is_size_valid (width, height))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
@@ -872,6 +875,10 @@ _cairo_image_surface_paint (void			*abstract_surface,
 			    const cairo_clip_t		*clip)
 {
     cairo_image_surface_t *surface = abstract_surface;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->base.unique_id));
+
     return _cairo_compositor_paint (surface->compositor,
 				    &surface->base, op, source, clip);
 }
@@ -884,6 +891,10 @@ _cairo_image_surface_mask (void				*abstract_surface,
 			   const cairo_clip_t		*clip)
 {
     cairo_image_surface_t *surface = abstract_surface;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->base.unique_id));
+
     return _cairo_compositor_mask (surface->compositor,
 				   &surface->base, op, source, mask, clip);
 }
@@ -901,6 +912,10 @@ _cairo_image_surface_stroke (void			*abstract_surface,
 			     const cairo_clip_t		*clip)
 {
     cairo_image_surface_t *surface = abstract_surface;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->base.unique_id));
+
     return _cairo_compositor_stroke (surface->compositor, &surface->base,
 				     op, source, path,
 				     style, ctm, ctm_inverse,
@@ -918,6 +933,10 @@ _cairo_image_surface_fill (void				*abstract_surface,
 			   const cairo_clip_t		*clip)
 {
     cairo_image_surface_t *surface = abstract_surface;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->base.unique_id));
+
     return _cairo_compositor_fill (surface->compositor, &surface->base,
 				   op, source, path,
 				   fill_rule, tolerance, antialias,
@@ -934,6 +953,10 @@ _cairo_image_surface_glyphs (void			*abstract_surface,
 			     const cairo_clip_t		*clip)
 {
     cairo_image_surface_t *surface = abstract_surface;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->base.unique_id));
+
     return _cairo_compositor_glyphs (surface->compositor, &surface->base,
 				     op, source,
 				     glyphs, num_glyphs, scaled_font,
diff --git a/src/cairo-surface-backend-private.h b/src/cairo-surface-backend-private.h
index f7bfbd7..fbaa912 100644
--- a/src/cairo-surface-backend-private.h
+++ b/src/cairo-surface-backend-private.h
@@ -201,6 +201,16 @@ struct _cairo_surface_backend {
     (*get_supported_mime_types)	(void			    *surface);
 };
 
+cairo_private cairo_status_t
+_cairo_surface_default_acquire_source_image (void                    *surface,
+					     cairo_image_surface_t  **image_out,
+					     void                   **image_extra);
+
+cairo_private void
+_cairo_surface_default_release_source_image (void                   *surface,
+					     cairo_image_surface_t  *image,
+					     void                   *image_extra);
+
 cairo_private cairo_surface_t *
 _cairo_surface_default_source (void *surface,
 			       cairo_rectangle_int_t *extents);
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index 657592d..f6ebf22 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -44,6 +44,7 @@
 #include "cairo-list-private.h"
 #include "cairo-reference-count-private.h"
 #include "cairo-clip-private.h"
+#include "cairo-surface-backend-private.h"
 
 typedef void (*cairo_surface_func_t) (cairo_surface_t *);
 
@@ -110,4 +111,13 @@ cairo_private cairo_surface_t *
 _cairo_surface_get_source (cairo_surface_t *surface,
 			   cairo_rectangle_int_t *extents);
 
+static inline cairo_status_t
+_cairo_surface_flush (cairo_surface_t *surface)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    if (surface->backend->flush)
+	status = surface->backend->flush (surface);
+    return status;
+}
+
 #endif /* CAIRO_SURFACE_PRIVATE_H */
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 13f0909..78346c9 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1713,6 +1713,17 @@ _cairo_surface_acquire_source_image (cairo_surface_t         *surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
+cairo_status_t
+_cairo_surface_default_acquire_source_image (void                    *surface,
+					     cairo_image_surface_t  **image_out,
+					     void                   **image_extra)
+{
+    *image_out = (cairo_image_surface_t *)
+	cairo_surface_map_to_image (surface, NULL);
+    *image_extra = NULL;
+    return (*image_out)->base.status;
+}
+
 /**
  * _cairo_surface_release_source_image:
  * @surface: a #cairo_surface_t
@@ -1731,6 +1742,15 @@ _cairo_surface_release_source_image (cairo_surface_t        *surface,
 	surface->backend->release_source_image (surface, image, image_extra);
 }
 
+void
+_cairo_surface_default_release_source_image (void                   *surface,
+					     cairo_image_surface_t  *image,
+					     void                   *image_extra)
+{
+    cairo_surface_unmap_image (surface, &image->base);
+}
+
+
 cairo_surface_t *
 _cairo_surface_get_source (cairo_surface_t *surface,
 			   cairo_rectangle_int_t *extents)
diff --git a/src/cairo-system.c b/src/cairo-system.c
deleted file mode 100644
index 1ff4d07..0000000
--- a/src/cairo-system.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- *	Owen Taylor <otaylor at redhat.com>
- *	Stuart Parmenter <stuart at mozilla.com>
- *	Vladimir Vukicevic <vladimir at pobox.com>
- */
-
-/* This file should include code that is system-specific, not
- * feature-specific.  For example, the DLL initialization/finalization
- * code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c).
- * Same about possible ELF-specific code.
- *
- * And no other function should live here.
- */
-
-
-#include "cairoint.h"
-
-
-
-#if CAIRO_MUTEX_IMPL_WIN32
-#if !CAIRO_WIN32_STATIC_BUILD
-
-#define WIN32_LEAN_AND_MEAN
-/* We require Windows 2000 features such as ETO_PDY */
-#if !defined(WINVER) || (WINVER < 0x0500)
-# define WINVER 0x0500
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-# define _WIN32_WINNT 0x0500
-#endif
-
-#include "cairo-clip-private.h"
-#include "cairo-paginated-private.h"
-#include "cairo-win32-private.h"
-#include "cairo-scaled-font-subsets-private.h"
-
-#include <windows.h>
-
-/* declare to avoid "no previous prototype for 'DllMain'" warning */
-BOOL WINAPI
-DllMain (HINSTANCE hinstDLL,
-         DWORD     fdwReason,
-         LPVOID    lpvReserved);
-
-BOOL WINAPI
-DllMain (HINSTANCE hinstDLL,
-         DWORD     fdwReason,
-         LPVOID    lpvReserved)
-{
-    switch (fdwReason) {
-        case DLL_PROCESS_ATTACH:
-            CAIRO_MUTEX_INITIALIZE ();
-            break;
-
-        case DLL_PROCESS_DETACH:
-            CAIRO_MUTEX_FINALIZE ();
-            break;
-    }
-
-    return TRUE;
-}
-
-#endif
-#endif
-
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index b435180..a9f8c75 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -167,6 +167,8 @@ combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
     int src_x, src_y;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = _cairo_clip_get_polygon (clip, &polygon,
 				      &fill_rule, &antialias);
     if (status)
@@ -209,6 +211,8 @@ traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
     cairo_surface_t *surface;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     surface = _cairo_surface_create_similar_solid (target,
 						   CAIRO_CONTENT_ALPHA,
 						   extents->width,
@@ -247,6 +251,8 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
     int src_x, src_y;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     surface = _cairo_surface_create_similar_solid (dst,
 						   CAIRO_CONTENT_ALPHA,
 						   extents->bounded.width,
@@ -351,6 +357,8 @@ clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
     cairo_surface_t *dst = extents->surface;
     cairo_surface_t *mask;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     mask = create_composite_mask (compositor, dst, draw_closure,
 				  draw_func, mask_func,
 				  extents);
@@ -396,6 +404,8 @@ clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
     cairo_surface_t *tmp, *clip;
     cairo_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
 						 extents->bounded.width,
 						 extents->bounded.height);
@@ -467,6 +477,8 @@ clip_and_composite_source (const cairo_traps_compositor_t	*compositor,
 {
     cairo_surface_t *mask;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     /* Create a surface that is mask IN clip */
     mask = create_composite_mask (compositor, dst, draw_closure,
 				  draw_func, mask_func,
@@ -531,6 +543,8 @@ fixup_unbounded_with_mask (const cairo_traps_compositor_t *compositor,
     cairo_clip_t *clip = extents->clip;
     cairo_surface_t *mask;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     /* XXX can we avoid querying the clip surface again? */
     mask = traps_get_clip_surface (compositor, dst, clip, &extents->unbounded);
     if (unlikely (mask->status))
@@ -622,6 +636,8 @@ fixup_unbounded (const cairo_traps_compositor_t *compositor,
     cairo_box_t box;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (extents->bounded.width  == extents->unbounded.width &&
 	extents->bounded.height == extents->unbounded.height)
     {
@@ -772,6 +788,8 @@ clip_and_composite (const cairo_traps_compositor_t *compositor,
     cairo_region_t *clip_region = NULL;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (reduce_alpha_op (extents)) {
 	op = CAIRO_OPERATOR_ADD;
 	source = NULL;
@@ -882,6 +900,8 @@ composite_traps (const cairo_traps_compositor_t *compositor,
 {
     composite_traps_info_t *info = closure;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     return compositor->composite_traps (dst, op, src,
 					src_x - dst_x, src_y - dst_y,
 					dst_x, dst_y,
@@ -907,6 +927,8 @@ composite_tristrip (const cairo_traps_compositor_t *compositor,
 {
     composite_tristrip_info_t *info = closure;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     return compositor->composite_tristrip (dst, op, src,
 					   src_x - dst_x, src_y - dst_y,
 					   dst_x, dst_y,
@@ -985,6 +1007,8 @@ composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
     cairo_bool_t op_is_source;
     cairo_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (need_clip_mask &&
 	(! extents->is_bounded || extents->op == CAIRO_OPERATOR_SOURCE))
     {
@@ -1107,6 +1131,8 @@ upload_boxes (const cairo_traps_compositor_t *compositor,
     cairo_int_status_t status;
     int tx, ty;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     src = _cairo_pattern_get_source((cairo_surface_pattern_t *)source,
 				    &limit);
     if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
@@ -1258,6 +1284,8 @@ clip_and_composite_polygon (const cairo_traps_compositor_t *compositor,
     cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (polygon->num_edges == 0) {
 	status = CAIRO_INT_STATUS_SUCCESS;
 
@@ -1426,6 +1454,8 @@ composite_opacity_boxes (const cairo_traps_compositor_t *compositor,
     struct composite_opacity_info info;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     info.compositor = compositor;
     info.op = op;
     info.dst = dst;
@@ -1460,6 +1490,8 @@ composite_boxes (const cairo_traps_compositor_t *compositor,
     cairo_traps_t traps;
     cairo_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = _cairo_traps_init_boxes (&traps, closure);
     if (unlikely (status))
 	return status;
@@ -1481,6 +1513,8 @@ clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
 {
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (boxes->num_boxes == 0 && extents->is_bounded)
 	return CAIRO_STATUS_SUCCESS;
 
@@ -1549,6 +1583,8 @@ composite_traps_as_boxes (const cairo_traps_compositor_t *compositor,
 {
     cairo_boxes_t boxes;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (! _cairo_traps_to_boxes (&info->traps, info->antialias, &boxes))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -1562,6 +1598,8 @@ clip_and_composite_traps (const cairo_traps_compositor_t *compositor,
 {
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = trim_extents_to_traps (extents, &info->traps);
     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
 	return status;
@@ -1596,6 +1634,8 @@ clip_and_composite_tristrip (const cairo_traps_compositor_t *compositor,
     cairo_int_status_t status;
     unsigned int flags = 0;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = trim_extents_to_tristrip (extents, &info->strip);
     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
 	return status;
@@ -1630,6 +1670,8 @@ composite_mask (const cairo_traps_compositor_t *compositor,
 {
     struct composite_mask *data = closure;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (src != NULL) {
 	compositor->composite (dst, op, src, data->mask,
 			       extents->x + src_x, extents->y + src_y,
@@ -1663,6 +1705,8 @@ static void composite_box(void *closure,
     struct composite_box_info *info = closure;
     const cairo_traps_compositor_t *compositor = info->compositor;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage)) {
 	cairo_surface_t *mask;
 	cairo_color_t color;
@@ -1712,6 +1756,8 @@ composite_mask_clip_boxes (const cairo_traps_compositor_t *compositor,
     struct composite_box_info info;
     int i;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     info.compositor = compositor;
     info.op = CAIRO_OPERATOR_SOURCE;
     info.dst = dst;
@@ -1747,6 +1793,8 @@ composite_mask_clip (const cairo_traps_compositor_t *compositor,
     composite_traps_info_t info;
     cairo_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = _cairo_clip_get_polygon (clip, &polygon,
 				      &fill_rule, &info.antialias);
     if (unlikely (status))
@@ -1781,6 +1829,8 @@ _cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
     cairo_boxes_t boxes;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = compositor->check_composite (extents);
     if (unlikely (status))
 	return status;
@@ -1799,6 +1849,8 @@ _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = compositor->check_composite (extents);
     if (unlikely (status))
 	return status;
@@ -1820,6 +1872,8 @@ _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
 						    &extents->mask_sample_area,
 						    &data.mask_x,
 						    &data.mask_y);
+	if (unlikely (data.mask->status))
+	    return data.mask->status;
 
 	status = clip_and_composite (compositor, extents,
 				     composite_mask,
@@ -1845,6 +1899,8 @@ _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = compositor->check_composite (extents);
     if (unlikely (status))
 	return status;
@@ -1908,6 +1964,8 @@ _cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = compositor->check_composite (extents);
     if (unlikely (status))
 	return status;
@@ -1975,6 +2033,8 @@ composite_glyphs (const cairo_traps_compositor_t *compositor,
 {
     cairo_composite_glyphs_info_t *info = closure;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (op == CAIRO_OPERATOR_ADD && (dst->content & CAIRO_CONTENT_COLOR) == 0)
 	info->use_mask = 0;
 
@@ -1995,6 +2055,8 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t	*_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     status = compositor->check_composite (extents);
     if (unlikely (status))
 	return status;
diff --git a/src/cairo.h b/src/cairo.h
index 0a004f3..1c1d2d2 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -2047,6 +2047,7 @@ cairo_device_reference (cairo_device_t *device);
  * @CAIRO_DEVICE_TYPE_XLIB: The device is of type xlib
  * @CAIRO_DEVICE_TYPE_XML: The device is of type XML
  * @CAIRO_DEVICE_TYPE_COGL: The device is of type cogl, since 1.12
+ * @CAIRO_DEVICE_TYPE_WIN32: The device is of type cogl, since 1.12
  * @CAIRO_DEVICE_TYPE_INVALID: The device is invalid
  *
  * #cairo_device_type_t is used to describe the type of a given
@@ -2076,6 +2077,7 @@ typedef enum _cairo_device_type {
     CAIRO_DEVICE_TYPE_XLIB,
     CAIRO_DEVICE_TYPE_XML,
     CAIRO_DEVICE_TYPE_COGL,
+    CAIRO_DEVICE_TYPE_WIN32,
 
     CAIRO_DEVICE_TYPE_INVALID = -1
 } cairo_device_type_t;
diff --git a/src/cairoint.h b/src/cairoint.h
index d3ad903..6656d4b 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1984,4 +1984,10 @@ _cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps);
 cairo_private void
 _cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip);
 
+#if 0
+#define TRACE(x) fprintf x
+#else
+#define TRACE(x)
+#endif
+
 #endif
diff --git a/src/win32/cairo-win32-debug.c b/src/win32/cairo-win32-debug.c
new file mode 100644
index 0000000..ff7aeaf
--- /dev/null
+++ b/src/win32/cairo-win32-debug.c
@@ -0,0 +1,87 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+#include "cairo-win32-private.h"
+
+#include <wchar.h>
+#include <windows.h>
+
+void
+_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
+{
+    RGNDATA *rd;
+    unsigned int z;
+
+    if (header)
+	fprintf (stderr, "%s\n", header);
+
+    if (rgn == NULL) {
+	fprintf (stderr, " NULL\n");
+    }
+
+    z = GetRegionData(rgn, 0, NULL);
+    rd = (RGNDATA*) malloc(z);
+    z = GetRegionData(rgn, z, rd);
+
+    fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n",
+	     rd->rdh.nCount,
+	     rd->rdh.rcBound.left,
+	     rd->rdh.rcBound.top,
+	     rd->rdh.rcBound.right - rd->rdh.rcBound.left,
+	     rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
+
+    for (z = 0; z < rd->rdh.nCount; z++) {
+	RECT r = ((RECT*)rd->Buffer)[z];
+	fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n",
+		 z, r.left, r.top, r.right - r.left, r.bottom - r.top);
+    }
+
+    free(rd);
+    fflush (stderr);
+}
diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c
new file mode 100644
index 0000000..b3ee573
--- /dev/null
+++ b/src/win32/cairo-win32-device.c
@@ -0,0 +1,189 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-atomic-private.h"
+#include "cairo-device-private.h"
+#include "cairo-win32-private.h"
+
+#include <wchar.h>
+#include <windows.h>
+
+static cairo_device_t *__cairo_win32_device;
+
+static cairo_status_t
+_cairo_win32_device_flush (void *device)
+{
+    GdiFlush ();
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_device_finish (void *device)
+{
+}
+
+static void
+_cairo_win32_device_destroy (void *device)
+{
+    free (device);
+}
+
+static const cairo_device_backend_t _cairo_win32_device_backend = {
+    CAIRO_DEVICE_TYPE_WIN32,
+
+    NULL, NULL, /* lock, unlock */
+
+    _cairo_win32_device_flush,
+    _cairo_win32_device_finish,
+    _cairo_win32_device_destroy,
+};
+
+#if 0
+D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+								   D2D1::PixelFormat(
+										     DXGI_FORMAT_B8G8R8A8_UNORM,
+										     D2D1_ALPHA_MODE_IGNORE),
+								   0,
+								   0,
+								   D2D1_RENDER_TARGET_USAGE_NONE,
+								   D2D1_FEATURE_LEVEL_DEFAULT
+								  );
+
+hr = m_pD2DFactory->CreateDCRenderTarget(&props, &device->d2d);
+#endif
+
+static cairo_bool_t is_win98 (void)
+{
+    OSVERSIONINFO os;
+
+    os.dwOSVersionInfoSize = sizeof (os);
+    GetVersionEx (&os);
+
+    return (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId &&
+	    os.dwMajorVersion != 4 &&
+	    os.dwMinorVersion != 10);
+}
+
+static void *
+_cairo_win32_device_get_alpha_blend (cairo_win32_device_t *device)
+{
+    void *func = NULL;
+
+    if (is_win98 ())
+	return NULL;
+
+    device->msimg32_dll = LoadLibraryW (L"msimg32");
+    if (device->msimg32_dll)
+	func = GetProcAddress (device->msimg32_dll, "AlphaBlend");
+
+    return func;
+}
+
+cairo_device_t *
+_cairo_win32_device_get (void)
+{
+    cairo_win32_device_t *device;
+
+    if (__cairo_win32_device)
+	return cairo_device_reference (__cairo_win32_device);
+
+    device = malloc (sizeof (*device));
+
+    _cairo_device_init (&device->base, &_cairo_win32_device_backend);
+
+    device->compositor = _cairo_win32_gdi_compositor_get ();
+
+    device->msimg32_dll = NULL;
+    device->alpha_blend = _cairo_win32_device_get_alpha_blend (device);
+
+    if (_cairo_atomic_ptr_cmpxchg ((void **)&__cairo_win32_device, NULL, device))
+	return cairo_device_reference(&device->base);
+
+    _cairo_win32_device_destroy (device);
+    return cairo_device_reference (__cairo_win32_device);
+}
+
+unsigned
+_cairo_win32_flags_for_dc (HDC dc)
+{
+    uint32_t flags = 0;
+    int cap;
+
+    cap = GetDeviceCaps(dc, RASTERCAPS);
+    if (cap & RC_BITBLT)
+	flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
+    if (cap & RC_STRETCHBLT)
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+    if (cap & RC_STRETCHDIB)
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
+
+    if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
+	flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY;
+
+	/* These will always be possible, but the actual GetDeviceCaps
+	 * calls will return whether they're accelerated or not.
+	 * We may want to use our own (pixman) routines sometimes
+	 * if they're eventually faster, but for now have GDI do
+	 * everything.
+	 */
+#if 0
+	flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
+	flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
+#endif
+    } else {
+	cap = GetDeviceCaps(dc, SHADEBLENDCAPS);
+	if (cap != SB_NONE)
+	    flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
+    }
+
+    return flags;
+}
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
new file mode 100644
index 0000000..1b5d47e
--- /dev/null
+++ b/src/win32/cairo-win32-display-surface.c
@@ -0,0 +1,1031 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-clip-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-compositor-private.h"
+#include "cairo-damage-private.h"
+#include "cairo-default-context-private.h"
+#include "cairo-error-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-paginated-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-win32-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+#include "cairo-surface-fallback-private.h"
+#include "cairo-surface-backend-private.h"
+
+#include <wchar.h>
+#include <windows.h>
+
+#if defined(__MINGW32__) && !defined(ETO_PDY)
+# define ETO_PDY 0x2000
+#endif
+
+#define PELS_72DPI  ((LONG)(72. / 0.0254))
+
+/**
+ * SECTION:cairo-win32
+ * @Title: Win32 Surfaces
+ * @Short_Description: Microsoft Windows surface support
+ * @See_Also: #cairo_surface_t
+ *
+ * The Microsoft Windows surface is used to render cairo graphics to
+ * Microsoft Windows windows, bitmaps, and printing device contexts.
+ *
+ * The surface returned by cairo_win32_printing_surface_create() is of surface
+ * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface
+ * type.
+ *
+ * The surface returned by the other win32 constructors is of surface type
+ * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type.
+ */
+
+/**
+ * CAIRO_HAS_WIN32_SURFACE:
+ *
+ * Defined if the Microsoft Windows surface backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ */
+
+static const cairo_surface_backend_t cairo_win32_display_surface_backend;
+
+static cairo_status_t
+_create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
+		       HDC                    original_dc,
+		       cairo_format_t         format,
+		       int                    width,
+		       int                    height,
+		       unsigned char        **bits_out,
+		       int                   *rowstride_out)
+{
+    cairo_status_t status;
+
+    BITMAPINFO *bitmap_info = NULL;
+    struct {
+	BITMAPINFOHEADER bmiHeader;
+	RGBQUAD bmiColors[2];
+    } bmi_stack;
+    void *bits;
+
+    int num_palette = 0;	/* Quiet GCC */
+    int i;
+
+    surface->win32.dc = NULL;
+    surface->bitmap = NULL;
+    surface->is_dib = FALSE;
+
+    switch (format) {
+    default:
+    case CAIRO_FORMAT_INVALID:
+    case CAIRO_FORMAT_RGB16_565:
+    case CAIRO_FORMAT_RGB30:
+	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
+    case CAIRO_FORMAT_ARGB32:
+    case CAIRO_FORMAT_RGB24:
+	num_palette = 0;
+	break;
+
+    case CAIRO_FORMAT_A8:
+	num_palette = 256;
+	break;
+
+    case CAIRO_FORMAT_A1:
+	num_palette = 2;
+	break;
+    }
+
+    if (num_palette > 2) {
+	bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
+	if (!bitmap_info)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else {
+	bitmap_info = (BITMAPINFO *)&bmi_stack;
+    }
+
+    bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+    bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
+    bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
+    bitmap_info->bmiHeader.biSizeImage = 0;
+    bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
+    bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
+    bitmap_info->bmiHeader.biPlanes = 1;
+
+    switch (format) {
+    case CAIRO_FORMAT_INVALID:
+    case CAIRO_FORMAT_RGB16_565:
+    case CAIRO_FORMAT_RGB30:
+	ASSERT_NOT_REACHED;
+    /* We can't create real RGB24 bitmaps because something seems to
+     * break if we do, especially if we don't set up an image
+     * fallback.  It could be a bug with using a 24bpp pixman image
+     * (and creating one with masks).  So treat them like 32bpp.
+     * Note: This causes problems when using BitBlt/AlphaBlend/etc!
+     * see end of file.
+     */
+    case CAIRO_FORMAT_RGB24:
+    case CAIRO_FORMAT_ARGB32:
+	bitmap_info->bmiHeader.biBitCount = 32;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 0;	/* unused */
+	bitmap_info->bmiHeader.biClrImportant = 0;
+	break;
+
+    case CAIRO_FORMAT_A8:
+	bitmap_info->bmiHeader.biBitCount = 8;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 256;
+	bitmap_info->bmiHeader.biClrImportant = 0;
+
+	for (i = 0; i < 256; i++) {
+	    bitmap_info->bmiColors[i].rgbBlue = i;
+	    bitmap_info->bmiColors[i].rgbGreen = i;
+	    bitmap_info->bmiColors[i].rgbRed = i;
+	    bitmap_info->bmiColors[i].rgbReserved = 0;
+	}
+	break;
+
+    case CAIRO_FORMAT_A1:
+	bitmap_info->bmiHeader.biBitCount = 1;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 2;
+	bitmap_info->bmiHeader.biClrImportant = 0;
+
+	for (i = 0; i < 2; i++) {
+	    bitmap_info->bmiColors[i].rgbBlue = i * 255;
+	    bitmap_info->bmiColors[i].rgbGreen = i * 255;
+	    bitmap_info->bmiColors[i].rgbRed = i * 255;
+	    bitmap_info->bmiColors[i].rgbReserved = 0;
+	}
+	break;
+    }
+
+    surface->win32.dc = CreateCompatibleDC (original_dc);
+    if (!surface->win32.dc)
+	goto FAIL;
+
+    surface->bitmap = CreateDIBSection (surface->win32.dc,
+			                bitmap_info,
+			                DIB_RGB_COLORS,
+			                &bits,
+			                NULL, 0);
+    if (!surface->bitmap)
+	goto FAIL;
+
+    surface->is_dib = TRUE;
+
+    GdiFlush();
+
+    surface->saved_dc_bitmap = SelectObject (surface->win32.dc,
+					     surface->bitmap);
+    if (!surface->saved_dc_bitmap)
+	goto FAIL;
+
+    if (bitmap_info && num_palette > 2)
+	free (bitmap_info);
+
+    if (bits_out)
+	*bits_out = bits;
+
+    if (rowstride_out) {
+	/* Windows bitmaps are padded to 32-bit (dword) boundaries */
+	switch (format) {
+	case CAIRO_FORMAT_INVALID:
+	case CAIRO_FORMAT_RGB16_565:
+	case CAIRO_FORMAT_RGB30:
+	    ASSERT_NOT_REACHED;
+	case CAIRO_FORMAT_ARGB32:
+	case CAIRO_FORMAT_RGB24:
+	    *rowstride_out = 4 * width;
+	    break;
+
+	case CAIRO_FORMAT_A8:
+	    *rowstride_out = (width + 3) & ~3;
+	    break;
+
+	case CAIRO_FORMAT_A1:
+	    *rowstride_out = ((width + 31) & ~31) / 8;
+	    break;
+	}
+    }
+
+    surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc);
+
+    return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+    status = _cairo_win32_print_gdi_error (__FUNCTION__);
+
+    if (bitmap_info && num_palette > 2)
+	free (bitmap_info);
+
+    if (surface->saved_dc_bitmap) {
+	SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
+	surface->saved_dc_bitmap = NULL;
+    }
+
+    if (surface->bitmap) {
+	DeleteObject (surface->bitmap);
+	surface->bitmap = NULL;
+    }
+
+    if (surface->win32.dc) {
+	DeleteDC (surface->win32.dc);
+	surface->win32.dc = NULL;
+    }
+
+    return status;
+}
+
+static cairo_surface_t *
+_cairo_win32_display_surface_create_for_dc (HDC             original_dc,
+					    cairo_format_t  format,
+					    int	            width,
+					    int	            height)
+{
+    cairo_status_t status;
+    cairo_device_t *device;
+    cairo_win32_display_surface_t *surface;
+    unsigned char *bits;
+    int rowstride;
+
+    surface = malloc (sizeof (*surface));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    surface->fallback = NULL;
+
+    status = _create_dc_and_bitmap (surface, original_dc, format,
+				    width, height,
+				    &bits, &rowstride);
+    if (status)
+	goto FAIL;
+
+    surface->image = cairo_image_surface_create_for_data (bits, format,
+							  width, height, rowstride);
+    status = surface->image->status;
+    if (status)
+	goto FAIL;
+
+    _cairo_image_surface_set_parent (to_image_surface(surface->image),
+				     &surface->win32.base);
+
+    surface->win32.format = format;
+
+    surface->win32.extents.x = 0;
+    surface->win32.extents.y = 0;
+    surface->win32.extents.width = width;
+    surface->win32.extents.height = height;
+
+    surface->initial_clip_rgn = NULL;
+    surface->had_simple_clip = FALSE;
+
+    device = _cairo_win32_device_get ();
+
+    _cairo_surface_init (&surface->win32.base,
+			 &cairo_win32_display_surface_backend,
+			 device,
+			 _cairo_content_from_format (format));
+
+    cairo_device_destroy (device);
+
+    return &surface->win32.base;
+
+ FAIL:
+    if (surface->bitmap) {
+	SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
+	DeleteObject (surface->bitmap);
+	DeleteDC (surface->win32.dc);
+    }
+    free (surface);
+
+    return _cairo_surface_create_in_error (status);
+}
+
+static cairo_surface_t *
+_cairo_win32_display_surface_create_similar (void	    *abstract_src,
+					     cairo_content_t content,
+					     int	     width,
+					     int	     height)
+{
+    cairo_win32_display_surface_t *src = abstract_src;
+    cairo_format_t format = _cairo_format_from_content (content);
+    cairo_surface_t *new_surf = NULL;
+
+    /* We force a DIB always if:
+     * - we need alpha; or
+     * - the parent is a DIB; or
+     * - the parent is for printing (because we don't care about the
+     *   bit depth at that point)
+     *
+     * We also might end up with a DIB even if a DDB is requested if
+     * DDB creation failed due to out of memory.
+     */
+    if (!(src->is_dib || content & CAIRO_CONTENT_ALPHA)) {
+	/* try to create a ddb */
+	new_surf = cairo_win32_surface_create_with_ddb (src->win32.dc, CAIRO_FORMAT_RGB24, width, height);
+
+	if (new_surf->status)
+	    new_surf = NULL;
+    }
+
+    if (new_surf == NULL) {
+	new_surf = _cairo_win32_display_surface_create_for_dc (src->win32.dc, format, width, height);
+    }
+
+    return new_surf;
+}
+
+static cairo_surface_t *
+_cairo_win32_display_surface_create_similar_image (void	    *abstract_other,
+						   cairo_format_t format,
+						   int	     width,
+						   int	     height)
+{
+    cairo_win32_display_surface_t *surface = abstract_other;
+
+    surface = (cairo_win32_display_surface_t *)
+	_cairo_win32_display_surface_create_for_dc (surface->win32.dc,
+						    format, width, height);
+    if (surface->win32.base.status)
+	return &surface->win32.base;
+
+    return surface->image;
+}
+
+static cairo_status_t
+_cairo_win32_display_surface_finish (void *abstract_surface)
+{
+    cairo_win32_display_surface_t *surface = abstract_surface;
+
+    if (surface->image)
+	cairo_surface_destroy (surface->image);
+
+    /* If we created the Bitmap and DC, destroy them */
+    if (surface->bitmap) {
+	SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
+	DeleteObject (surface->bitmap);
+	DeleteDC (surface->win32.dc);
+    }
+
+    if (surface->initial_clip_rgn)
+	DeleteObject (surface->initial_clip_rgn);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_surface_t *
+_cairo_win32_display_surface_map_to_image (void                    *abstract_surface,
+					   const cairo_rectangle_int_t   *extents)
+{
+    cairo_win32_display_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->win32.base.unique_id));
+
+    if (surface->image)
+	goto done;
+
+    if (surface->fallback == NULL) {
+	surface->fallback =
+	    _cairo_win32_display_surface_create_for_dc (surface->win32.dc,
+							surface->win32.format,
+							surface->win32.extents.width,
+							surface->win32.extents.height);
+	if (unlikely (status = surface->fallback->status))
+	    goto err;
+
+	if (!BitBlt (to_win32_surface(surface->fallback)->dc,
+		     0, 0,
+		     surface->win32.extents.width,
+		     surface->win32.extents.height,
+		     surface->win32.dc,
+		     0, 0,
+		     SRCCOPY)) {
+	    status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
+	    goto err;
+	}
+    }
+
+    surface = to_win32_display_surface (surface->fallback);
+    if (surface->image->damage == NULL)
+	surface->image->damage = _cairo_damage_create ();
+
+done:
+    GdiFlush();
+    return _cairo_image_surface_map_to_image (surface->image, extents);
+
+err:
+    cairo_surface_destroy (surface->fallback);
+    surface->fallback = NULL;
+
+    return _cairo_surface_create_in_error (status);
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_unmap_image (void                    *surface,
+					  cairo_image_surface_t   *image)
+{
+    /* Delay the download until the next flush, which means we also need
+     * to make sure our sources rare flushed.
+     */
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_display_surface_flush (void *abstract_surface)
+{
+    cairo_win32_display_surface_t *surface = abstract_surface;
+    cairo_win32_display_surface_t *fallback;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->win32.base.unique_id));
+    if (surface->fallback == NULL)
+	return CAIRO_STATUS_SUCCESS;
+
+    fallback = to_win32_display_surface (surface->fallback);
+    assert (fallback->image);
+
+    if (fallback->image->damage) {
+	cairo_damage_t *damage;
+
+	damage = _cairo_damage_reduce (fallback->image->damage);
+	fallback->image->damage = NULL;
+
+	if (damage->status) {
+	    if (!BitBlt (surface->win32.dc,
+			 0, 0,
+			 surface->win32.extents.width,
+			 surface->win32.extents.height,
+			 fallback->win32.dc,
+			 0, 0,
+			 SRCCOPY))
+		status = _cairo_win32_print_gdi_error (__FUNCTION__);
+	} else {
+	    int n = cairo_region_num_rectangles (damage->region), i;
+	    for (i = 0; i < n; i++) {
+		cairo_rectangle_int_t rect;
+
+		cairo_region_get_rectangle (damage->region, i, &rect);
+		if (!BitBlt (surface->win32.dc,
+			     rect.x, rect.y,
+			     rect.width, rect.height,
+			     fallback->win32.dc,
+			     0, 0,
+			     SRCCOPY)) {
+		    status = _cairo_win32_print_gdi_error (__FUNCTION__);
+		    break;
+		}
+	    }
+	}
+	_cairo_damage_destroy (damage);
+    } else {
+	cairo_surface_destroy (surface->fallback);
+	surface->fallback = NULL;
+    }
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_win32_display_surface_mark_dirty (void *abstract_surface,
+					 int x, int y, int width, int height)
+{
+    _cairo_win32_display_surface_discard_fallback (abstract_surface);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_display_surface_t *surface)
+{
+    RECT rect;
+    int clipBoxType;
+    int gm;
+    XFORM saved_xform;
+
+    /* GetClipBox/GetClipRgn and friends interact badly with a world transform
+     * set.  GetClipBox returns values in logical (transformed) coordinates;
+     * it's unclear what GetClipRgn returns, because the region is empty in the
+     * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates.
+     * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn
+     * works in device units.
+     *
+     * So, avoid the whole mess and get rid of the world transform
+     * while we store our initial data and when we restore initial coordinates.
+     *
+     * XXX we may need to modify x/y by the ViewportOrg or WindowOrg
+     * here in GM_COMPATIBLE; unclear.
+     */
+    gm = GetGraphicsMode (hdc);
+    if (gm == GM_ADVANCED) {
+	GetWorldTransform (hdc, &saved_xform);
+	ModifyWorldTransform (hdc, NULL, MWT_IDENTITY);
+    }
+
+    clipBoxType = GetClipBox (hdc, &rect);
+    if (clipBoxType == ERROR) {
+	_cairo_win32_print_gdi_error (__FUNCTION__);
+	SetGraphicsMode (hdc, gm);
+	/* XXX: Can we make a more reasonable guess at the error cause here? */
+	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
+    }
+
+    surface->win32.extents.x = rect.left;
+    surface->win32.extents.y = rect.top;
+    surface->win32.extents.width = rect.right - rect.left;
+    surface->win32.extents.height = rect.bottom - rect.top;
+
+    surface->initial_clip_rgn = NULL;
+    surface->had_simple_clip = FALSE;
+
+    if (clipBoxType == COMPLEXREGION) {
+	surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
+	if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
+	    DeleteObject(surface->initial_clip_rgn);
+	    surface->initial_clip_rgn = NULL;
+	}
+    } else if (clipBoxType == SIMPLEREGION) {
+	surface->had_simple_clip = TRUE;
+    }
+
+    if (gm == GM_ADVANCED)
+	SetWorldTransform (hdc, &saved_xform);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface,
+				       cairo_clip_t *clip)
+{
+    char stack[512];
+    cairo_rectangle_int_t extents;
+    int num_rects;
+    RGNDATA *data;
+    size_t data_size;
+    RECT *rects;
+    int i;
+    HRGN gdi_region;
+    cairo_status_t status;
+    cairo_region_t *region;
+
+    /* The semantics we want is that any clip set by cairo combines
+     * is intersected with the clip on device context that the
+     * surface was created for. To implement this, we need to
+     * save the original clip when first setting a clip on surface.
+     */
+
+    assert (_cairo_clip_is_region (clip));
+    region = _cairo_clip_get_region (clip);
+    if (region == NULL)
+	return CAIRO_STATUS_SUCCESS;
+
+    cairo_region_get_extents (region, &extents);
+    num_rects = cairo_region_num_rectangles (region);
+
+    /* XXX see notes in _cairo_win32_save_initial_clip --
+     * this code will interact badly with a HDC which had an initial
+     * world transform -- we should probably manually transform the
+     * region rects, because SelectClipRgn takes device units, not
+     * logical units (unlike IntersectClipRect).
+     */
+
+    data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
+    if (data_size > sizeof (stack)) {
+	data = malloc (data_size);
+	if (!data)
+	    return _cairo_error(CAIRO_STATUS_NO_MEMORY);
+    } else
+	data = (RGNDATA *)stack;
+
+    data->rdh.dwSize = sizeof (RGNDATAHEADER);
+    data->rdh.iType = RDH_RECTANGLES;
+    data->rdh.nCount = num_rects;
+    data->rdh.nRgnSize = num_rects * sizeof (RECT);
+    data->rdh.rcBound.left = extents.x;
+    data->rdh.rcBound.top = extents.y;
+    data->rdh.rcBound.right = extents.x + extents.width;
+    data->rdh.rcBound.bottom = extents.y + extents.height;
+
+    rects = (RECT *)data->Buffer;
+    for (i = 0; i < num_rects; i++) {
+	cairo_rectangle_int_t rect;
+
+	cairo_region_get_rectangle (region, i, &rect);
+
+	rects[i].left   = rect.x;
+	rects[i].top    = rect.y;
+	rects[i].right  = rect.x + rect.width;
+	rects[i].bottom = rect.y + rect.height;
+    }
+
+    gdi_region = ExtCreateRegion (NULL, data_size, data);
+    if ((char *)data != stack)
+	free (data);
+
+    if (!gdi_region)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    /* AND the new region into our DC */
+    status = CAIRO_STATUS_SUCCESS;
+    if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR)
+	status = _cairo_win32_print_gdi_error (__FUNCTION__);
+
+    DeleteObject (gdi_region);
+
+    return status;
+}
+
+void
+_cairo_win32_display_surface_unset_clip (cairo_win32_display_surface_t *surface)
+{
+    XFORM saved_xform;
+    int gm = GetGraphicsMode (surface->win32.dc);
+    if (gm == GM_ADVANCED) {
+	GetWorldTransform (surface->win32.dc, &saved_xform);
+	ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY);
+    }
+
+    /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */
+    SelectClipRgn (surface->win32.dc, surface->initial_clip_rgn);
+
+    if (surface->had_simple_clip) {
+	/* then if we had a simple clip, intersect */
+	IntersectClipRect (surface->win32.dc,
+			   surface->win32.extents.x,
+			   surface->win32.extents.y,
+			   surface->win32.extents.x + surface->win32.extents.width,
+			   surface->win32.extents.y + surface->win32.extents.height);
+    }
+
+    if (gm == GM_ADVANCED)
+	SetWorldTransform (surface->win32.dc, &saved_xform);
+}
+
+void
+_cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface)
+{
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, surface->win32.base.unique_id));
+
+    if (surface->fallback) {
+	cairo_surface_destroy (surface->fallback);
+	surface->fallback = NULL;
+    }
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_paint (void			*surface,
+				    cairo_operator_t		 op,
+				    const cairo_pattern_t	*source,
+				    const cairo_clip_t		*clip)
+{
+    cairo_win32_device_t *device = to_win32_device_from_surface (surface);
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+
+    if (clip == NULL &&
+	(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR))
+	_cairo_win32_display_surface_discard_fallback (surface);
+
+    return _cairo_compositor_paint (device->compositor,
+				    surface, op, source, clip);
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_mask (void				*surface,
+				   cairo_operator_t		 op,
+				   const cairo_pattern_t	*source,
+				   const cairo_pattern_t	*mask,
+				   const cairo_clip_t		*clip)
+{
+    cairo_win32_device_t *device = to_win32_device_from_surface (surface);
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+
+    if (clip == NULL && op == CAIRO_OPERATOR_SOURCE)
+	_cairo_win32_display_surface_discard_fallback (surface);
+
+    return _cairo_compositor_mask (device->compositor,
+				   surface, op, source, mask, clip);
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_stroke (void			*surface,
+				     cairo_operator_t		 op,
+				     const cairo_pattern_t	*source,
+				     const cairo_path_fixed_t	*path,
+				     const cairo_stroke_style_t	*style,
+				     const cairo_matrix_t	*ctm,
+				     const cairo_matrix_t	*ctm_inverse,
+				     double			 tolerance,
+				     cairo_antialias_t		 antialias,
+				     const cairo_clip_t		*clip)
+{
+    cairo_win32_device_t *device = to_win32_device_from_surface (surface);
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+
+    return _cairo_compositor_stroke (device->compositor, surface,
+				     op, source, path,
+				     style, ctm, ctm_inverse,
+				     tolerance, antialias, clip);
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_fill (void				*surface,
+				   cairo_operator_t		 op,
+				   const cairo_pattern_t	*source,
+				   const cairo_path_fixed_t	*path,
+				   cairo_fill_rule_t		 fill_rule,
+				   double			 tolerance,
+				   cairo_antialias_t		 antialias,
+				   const cairo_clip_t		*clip)
+{
+    cairo_win32_device_t *device = to_win32_device_from_surface (surface);
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+
+    return _cairo_compositor_fill (device->compositor, surface,
+				   op, source, path,
+				   fill_rule, tolerance, antialias,
+				   clip);
+}
+
+static cairo_int_status_t
+_cairo_win32_display_surface_glyphs (void			*surface,
+				     cairo_operator_t		 op,
+				     const cairo_pattern_t	*source,
+				     cairo_glyph_t		*glyphs,
+				     int			 num_glyphs,
+				     cairo_scaled_font_t	*scaled_font,
+				     const cairo_clip_t		*clip)
+{
+    cairo_win32_device_t *device = to_win32_device_from_surface (surface);
+
+    TRACE ((stderr, "%s (surface=%d)\n",
+	    __FUNCTION__, to_win32_surface(surface)->base.unique_id));
+
+    return _cairo_compositor_glyphs (device->compositor, surface,
+				     op, source,
+				     glyphs, num_glyphs, scaled_font,
+				     clip);
+}
+
+static const cairo_surface_backend_t cairo_win32_display_surface_backend = {
+    CAIRO_SURFACE_TYPE_WIN32,
+    _cairo_win32_display_surface_finish,
+
+    _cairo_default_context_create,
+
+    _cairo_win32_display_surface_create_similar,
+    _cairo_win32_display_surface_create_similar_image,
+    _cairo_win32_display_surface_map_to_image,
+    _cairo_win32_display_surface_unmap_image,
+
+    _cairo_surface_default_source,
+    _cairo_surface_default_acquire_source_image,
+    _cairo_surface_default_release_source_image,
+    NULL,  /* snapshot */
+
+    NULL, /* copy_page */
+    NULL, /* show_page */
+
+    _cairo_win32_surface_get_extents,
+    NULL, /* get_font_options */
+
+    _cairo_win32_display_surface_flush,
+    _cairo_win32_display_surface_mark_dirty,
+
+    _cairo_win32_display_surface_paint,
+    _cairo_win32_display_surface_mask,
+    _cairo_win32_display_surface_stroke,
+    _cairo_win32_display_surface_fill,
+    NULL, /* fill/stroke */
+    _cairo_win32_display_surface_glyphs,
+};
+
+/* Notes:
+ *
+ * Win32 alpha-understanding functions
+ *
+ * BitBlt - will copy full 32 bits from a 32bpp DIB to result
+ *          (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
+ *          (but not safe going RGB24->ARGB32, if RGB24 is also represented
+ *           as a 32bpp DIB, since the alpha isn't discarded!)
+ *
+ * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
+ *              it will still copy over the src alpha, because the SCA value (255) will be
+ *              multiplied by all the src components.
+ */
+
+/**
+ * cairo_win32_surface_create:
+ * @hdc: the DC to create a surface for
+ *
+ * Creates a cairo surface that targets the given DC.  The DC will be
+ * queried for its initial clip extents, and this will be used as the
+ * size of the cairo surface.  The resulting surface will always be of
+ * format %CAIRO_FORMAT_RGB24; should you need another surface format,
+ * you will need to create one through
+ * cairo_win32_surface_create_with_dib().
+ *
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_win32_surface_create (HDC hdc)
+{
+    cairo_win32_display_surface_t *surface;
+
+    cairo_format_t format;
+    cairo_status_t status;
+    cairo_device_t *device;
+
+    /* Assume that everything coming in as a HDC is RGB24 */
+    format = CAIRO_FORMAT_RGB24;
+
+    surface = malloc (sizeof (*surface));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    status = _cairo_win32_save_initial_clip (hdc, surface);
+    if (status) {
+	free (surface);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    surface->image = NULL;
+    surface->fallback = NULL;
+    surface->win32.format = format;
+
+    surface->win32.dc = hdc;
+    surface->bitmap = NULL;
+    surface->is_dib = FALSE;
+    surface->saved_dc_bitmap = NULL;
+
+    surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc);
+
+    device = _cairo_win32_device_get ();
+
+    _cairo_surface_init (&surface->win32.base,
+			 &cairo_win32_display_surface_backend,
+			 device,
+			 _cairo_content_from_format (format));
+
+    cairo_device_destroy (device);
+
+    return &surface->win32.base;
+}
+
+/**
+ * cairo_win32_surface_create_with_dib:
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a device-independent-bitmap surface not associated with
+ * any particular existing surface or device context. The created
+ * bitmap will be uninitialized.
+ *
+ * Return value: the newly created surface
+ *
+ * Since: 1.2
+ **/
+cairo_surface_t *
+cairo_win32_surface_create_with_dib (cairo_format_t format,
+				     int	    width,
+				     int	    height)
+{
+    if (! CAIRO_FORMAT_VALID (format))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+
+    return _cairo_win32_display_surface_create_for_dc (NULL, format, width, height);
+}
+
+/**
+ * cairo_win32_surface_create_with_ddb:
+ * @hdc: a DC compatible with the surface to create
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a device-dependent-bitmap surface not associated with
+ * any particular existing surface or device context. The created
+ * bitmap will be uninitialized.
+ *
+ * Return value: the newly created surface
+ *
+ * Since: 1.4
+ **/
+cairo_surface_t *
+cairo_win32_surface_create_with_ddb (HDC hdc,
+				     cairo_format_t format,
+				     int width,
+				     int height)
+{
+    cairo_win32_display_surface_t *new_surf;
+    HBITMAP ddb;
+    HDC screen_dc, ddb_dc;
+    HBITMAP saved_dc_bitmap;
+
+    if (format != CAIRO_FORMAT_RGB24)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+/* XXX handle these eventually
+	format != CAIRO_FORMAT_A8 ||
+	format != CAIRO_FORMAT_A1)
+*/
+
+    if (!hdc) {
+	screen_dc = GetDC (NULL);
+	hdc = screen_dc;
+    } else {
+	screen_dc = NULL;
+    }
+
+    ddb_dc = CreateCompatibleDC (hdc);
+    if (ddb_dc == NULL) {
+	new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	goto FINISH;
+    }
+
+    ddb = CreateCompatibleBitmap (hdc, width, height);
+    if (ddb == NULL) {
+	DeleteDC (ddb_dc);
+
+	/* Note that if an app actually does hit this out of memory
+	 * condition, it's going to have lots of other issues, as
+	 * video memory is probably exhausted.  However, it can often
+	 * continue using DIBs instead of DDBs.
+	 */
+	new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	goto FINISH;
+    }
+
+    saved_dc_bitmap = SelectObject (ddb_dc, ddb);
+
+    new_surf = (cairo_win32_display_surface_t*) cairo_win32_surface_create (ddb_dc);
+    new_surf->bitmap = ddb;
+    new_surf->saved_dc_bitmap = saved_dc_bitmap;
+    new_surf->is_dib = FALSE;
+
+FINISH:
+    if (screen_dc)
+	ReleaseDC (NULL, screen_dc);
+
+    return &new_surf->win32.base;
+}
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index 73fc052..ed171c2 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -236,13 +236,15 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
 	if (status)
 	    return status;
 
-	scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
-                                                   scaled_font->y_scale);
-	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
+	scaled_font->logical_size =
+	    _cairo_lround (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale);
+	scaled_font->logical_scale =
+	    WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
     }
 
     cairo_matrix_scale (&scaled_font->logical_to_device,
-			1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
+			1.0 / scaled_font->logical_scale,
+			1.0 / scaled_font->logical_scale);
 
     scaled_font->device_to_logical = scaled_font->logical_to_device;
 
@@ -1049,7 +1051,6 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
 	    extents.y_bearing = (- extents.y_bearing - extents.height);
 	    extents.y_advance = - extents.y_advance;
 	}
-
     } else {
 	/* For all other transformations, we use the design metrics
 	 * of the font.
@@ -1295,6 +1296,7 @@ _draw_glyphs_on_surface (cairo_win32_surface_t     *surface,
     return status;
 }
 
+#if 0
 /* Duplicate the green channel of a 4-channel mask in the alpha channel, then
  * invert the whole mask.
  */
@@ -1360,6 +1362,7 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface)
 
     return &image8->base;
 }
+#endif
 
 static cairo_int_status_t
 _cairo_win32_scaled_font_glyph_init (void		       *abstract_font,
@@ -1656,9 +1659,9 @@ _cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
 }
 
 static cairo_int_status_t
-_cairo_win32_scaled_font_index_to_glyph_name (void	      	*abstract_font,
+_cairo_win32_scaled_font_index_to_glyph_name (void		*abstract_font,
 					      char             **glyph_names,
-					      int              	 num_glyph_names,
+					      int		 num_glyph_names,
 					      unsigned long      glyph_index,
 					      unsigned long     *glyph_array_index)
 {
@@ -1688,7 +1691,7 @@ _cairo_win32_scaled_font_index_to_glyph_name (void	      	*abstract_font,
 	*glyph_array_index = scaled_font->type1_notdef_index;
     else if (glyph_index <= scaled_font->type1_notdef_index)
 	*glyph_array_index = glyph_index - 1;
-    else if (glyph_index < num_glyph_names)
+    else if (glyph_index < (unsigned long)num_glyph_names)
 	*glyph_array_index = glyph_index;
     else
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1756,8 +1759,12 @@ _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_f
 
     GdiFlush();
 
+#if 0
     image = _compute_a8_mask (surface);
     status = image->status;
+#else
+    status = CAIRO_STATUS_NO_MEMORY;
+#endif
     if (status)
 	goto FAIL;
 
diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c
new file mode 100644
index 0000000..054d9f2
--- /dev/null
+++ b/src/win32/cairo-win32-gdi-compositor.c
@@ -0,0 +1,646 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Behdad Esfahbod <behdad at behdad.org>
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ *	Karl Tomlinson <karlt+ at karlt.net>, Mozilla Corporation
+ */
+
+/* The original X drawing API was very restrictive in what it could handle,
+ * pixel-aligned fill/blits are all that map into Cairo's drawing model.
+ */
+
+#include "cairoint.h"
+
+#include "cairo-win32-private.h"
+
+#include "cairo-boxes-private.h"
+#include "cairo-compositor-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-region-private.h"
+#include "cairo-surface-offset-private.h"
+
+#if !defined(AC_SRC_OVER)
+#define AC_SRC_OVER                 0x00
+#pragma pack(1)
+typedef struct {
+    BYTE   BlendOp;
+    BYTE   BlendFlags;
+    BYTE   SourceConstantAlpha;
+    BYTE   AlphaFormat;
+}BLENDFUNCTION;
+#pragma pack()
+#endif
+
+/* for compatibility with VC++ 6 */
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA                0x01
+#endif
+
+#define PELS_72DPI  ((LONG)(72. / 0.0254))
+
+/* the low-level interface */
+
+struct fill_box {
+    HDC dc;
+    HBRUSH brush;
+};
+
+static cairo_bool_t fill_box (cairo_box_t *box, void *closure)
+{
+    struct fill_box *fb = closure;
+    RECT rect;
+
+    rect.left = _cairo_fixed_integer_part (box->p1.x);
+    rect.top = _cairo_fixed_integer_part (box->p1.y);
+    rect.right = _cairo_fixed_integer_part (box->p2.x);
+    rect.bottom = _cairo_fixed_integer_part (box->p2.y);
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    return FillRect (fb->dc, &rect, fb->brush);
+}
+
+struct check_box {
+    cairo_rectangle_int_t limit;
+    int tx, ty;
+};
+
+struct copy_box {
+    cairo_rectangle_int_t limit;
+    int tx, ty;
+    HDC dst, src;
+    BLENDFUNCTION bf;
+    cairo_win32_alpha_blend_func_t alpha_blend;
+};
+
+static cairo_bool_t copy_box (cairo_box_t *box, void *closure)
+{
+    const struct copy_box *cb = closure;
+    int x = _cairo_fixed_integer_part (box->p1.x);
+    int y = _cairo_fixed_integer_part (box->p1.y);
+    int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
+    int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    return BitBlt (cb->dst, x, y, width, height,
+		   cb->src, x + cb->tx, y + cb->ty,
+		   SRCCOPY);
+}
+
+static cairo_bool_t alpha_box (cairo_box_t *box, void *closure)
+{
+    const struct copy_box *cb = closure;
+    int x = _cairo_fixed_integer_part (box->p1.x);
+    int y = _cairo_fixed_integer_part (box->p1.y);
+    int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
+    int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    return cb->alpha_blend (cb->dst, x, y, width, height,
+			    cb->src, x + cb->tx, y + cb->ty, width, height,
+			    cb->bf);
+}
+
+struct upload_box {
+    cairo_rectangle_int_t limit;
+    int tx, ty;
+    HDC dst;
+    BITMAPINFO bi;
+    void *data;
+};
+
+static cairo_bool_t upload_box (cairo_box_t *box, void *closure)
+{
+    const struct upload_box *cb = closure;
+    int x = _cairo_fixed_integer_part (box->p1.x);
+    int y = _cairo_fixed_integer_part (box->p1.y);
+    int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
+    int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    return StretchDIBits (cb->dst, x, y + height - 1, width, -height,
+			  x + cb->tx,  height - (y + cb->ty - 1),
+			  width, -height,
+			  cb->data, &cb->bi,
+			  DIB_RGB_COLORS, SRCCOPY);
+}
+
+/* the mid-level: converts boxes into drawing operations */
+
+static COLORREF color_to_rgb(const cairo_color_t *c)
+{
+    return RGB (c->red_short >> 8, c->green_short >> 8, c->blue_short >> 8);
+}
+
+static cairo_int_status_t
+fill_boxes (cairo_win32_display_surface_t	*dst,
+	    const cairo_pattern_t		*src,
+	    cairo_boxes_t			*boxes)
+{
+    const cairo_color_t *color = &((cairo_solid_pattern_t *) src)->color;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    struct fill_box fb;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    fb.dc = dst->win32.dc;
+    fb.brush = CreateSolidBrush (color_to_rgb(color));
+    if (!fb.brush)
+	return _cairo_win32_print_gdi_error (__FUNCTION__);
+
+    if (! _cairo_boxes_for_each_box (boxes, fill_box, &fb))
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    DeleteObject (fb.brush);
+
+    return status;
+}
+
+static cairo_bool_t source_contains_box (cairo_box_t *box, void *closure)
+{
+    struct check_box *data = closure;
+
+    /* The box is pixel-aligned so the truncation is safe. */
+    return
+	_cairo_fixed_integer_part (box->p1.x) + data->tx >= data->limit.x &&
+	_cairo_fixed_integer_part (box->p1.y) + data->ty >= data->limit.y &&
+	_cairo_fixed_integer_part (box->p2.x) + data->tx <= data->limit.x + data->limit.width &&
+	_cairo_fixed_integer_part (box->p2.y) + data->ty <= data->limit.y + data->limit.height;
+}
+
+static cairo_status_t
+copy_boxes (cairo_win32_display_surface_t *dst,
+	    const cairo_pattern_t *source,
+	    cairo_boxes_t *boxes)
+{
+    const cairo_surface_pattern_t *pattern;
+    struct copy_box cb;
+    cairo_surface_t *surface;
+    cairo_status_t status;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    pattern = (const cairo_surface_pattern_t *) source;
+    surface = _cairo_surface_get_source (pattern->surface, &cb.limit);
+    if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
+	surface = to_image_surface(surface)->parent;
+	if (surface == NULL)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    if (surface->type != CAIRO_SURFACE_TYPE_WIN32)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (! _cairo_matrix_is_integer_translation (&source->matrix,
+						&cb.tx, &cb.ty))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    cb.dst = dst->win32.dc;
+    cb.src = to_win32_surface(surface)->dc;
+
+    /* First check that the data is entirely within the image */
+    if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_surface_flush (surface);
+    if (status)
+	return status;
+
+    cb.tx += cb.limit.x;
+    cb.ty += cb.limit.y;
+    status = CAIRO_STATUS_SUCCESS;
+    if (! _cairo_boxes_for_each_box (boxes, copy_box, &cb))
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    _cairo_win32_display_surface_discard_fallback (dst);
+    return status;
+}
+
+static cairo_status_t
+upload_boxes (cairo_win32_display_surface_t *dst,
+	      const cairo_pattern_t *source,
+	      cairo_boxes_t *boxes)
+{
+    const cairo_surface_pattern_t *pattern;
+    struct upload_box cb;
+    cairo_surface_t *surface;
+    cairo_image_surface_t *image;
+    void *image_extra;
+    cairo_status_t status;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB) == 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (! _cairo_matrix_is_integer_translation (&source->matrix,
+						&cb.tx, &cb.ty))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    pattern = (const cairo_surface_pattern_t *) source;
+    surface = _cairo_surface_get_source (pattern->surface, &cb.limit);
+
+    /* First check that the data is entirely within the image */
+    if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (surface->type != CAIRO_SURFACE_TYPE_IMAGE) {
+	status = _cairo_surface_acquire_source_image (surface,
+						      &image, &image_extra);
+	if (status)
+	    return status;
+    } else
+	image = to_image_surface(surface);
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (!(image->format == CAIRO_FORMAT_ARGB32 ||
+	  image->format == CAIRO_FORMAT_RGB24))
+	goto err;
+    if (image->stride != 4*image->width)
+	goto err;
+
+    cb.dst = dst->win32.dc;
+    cb.data = image->data;
+
+    cb.bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+    cb.bi.bmiHeader.biWidth = image->width;
+    cb.bi.bmiHeader.biHeight = -image->height;
+    cb.bi.bmiHeader.biSizeImage = 0;
+    cb.bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+    cb.bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+    cb.bi.bmiHeader.biPlanes = 1;
+    cb.bi.bmiHeader.biBitCount = 32;
+    cb.bi.bmiHeader.biCompression = BI_RGB;
+    cb.bi.bmiHeader.biClrUsed = 0;
+    cb.bi.bmiHeader.biClrImportant = 0;
+
+    cb.tx += cb.limit.x;
+    cb.ty += cb.limit.y;
+    status = CAIRO_STATUS_SUCCESS;
+    if (! _cairo_boxes_for_each_box (boxes, upload_box, &cb))
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    _cairo_win32_display_surface_discard_fallback (dst);
+err:
+    if (&image->base != surface)
+	_cairo_surface_release_source_image (surface, image, image_extra);
+
+    return status;
+}
+
+static cairo_status_t
+alpha_blend_boxes (cairo_win32_display_surface_t *dst,
+		   const cairo_pattern_t *source,
+		   cairo_boxes_t *boxes,
+		   uint8_t alpha)
+{
+    const cairo_surface_pattern_t *pattern;
+    struct copy_box cb;
+    cairo_surface_t *surface;
+    cairo_win32_display_surface_t *src;
+    cairo_status_t status;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    pattern = (const cairo_surface_pattern_t *) source;
+    surface = _cairo_surface_get_source (pattern->surface, &cb.limit);
+    if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
+	surface = to_image_surface(surface)->parent;
+	if (surface == NULL)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    if (pattern->surface->type != CAIRO_SURFACE_TYPE_WIN32)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (! _cairo_matrix_is_integer_translation (&source->matrix,
+						&cb.tx, &cb.ty))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    src = to_win32_display_surface (surface);
+    cb.dst = dst->win32.dc;
+    cb.src = src->win32.dc;
+
+    /* First check that the data is entirely within the image */
+    if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_surface_flush (&src->win32.base);
+    if (status)
+	return status;
+
+    cb.bf.BlendOp = AC_SRC_OVER;
+    cb.bf.BlendFlags = 0;
+    cb.bf.SourceConstantAlpha = alpha;
+    cb.bf.AlphaFormat = (src->win32.format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
+    cb.alpha_blend = to_win32_device(dst->win32.base.device)->alpha_blend;
+
+    cb.tx += cb.limit.x;
+    cb.ty += cb.limit.y;
+    status = CAIRO_STATUS_SUCCESS;
+    if (! _cairo_boxes_for_each_box (boxes, alpha_box, &cb))
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    _cairo_win32_display_surface_discard_fallback (dst);
+    return status;
+}
+
+static cairo_bool_t
+can_alpha_blend (cairo_win32_display_surface_t *dst)
+{
+    if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND) == 0)
+	return FALSE;
+
+    return to_win32_device(dst->win32.base.device)->alpha_blend != NULL;
+}
+
+static cairo_status_t
+draw_boxes (cairo_composite_rectangles_t *composite,
+	    cairo_boxes_t *boxes)
+{
+    cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface);
+    cairo_operator_t op = composite->op;
+    const cairo_pattern_t *src = &composite->source_pattern.base;
+    cairo_int_status_t status;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    if (boxes->num_boxes == 0 && composite->is_bounded)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (!boxes->is_pixel_aligned)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op == CAIRO_OPERATOR_CLEAR)
+	op = CAIRO_OPERATOR_SOURCE;
+
+    if (op == CAIRO_OPERATOR_OVER &&
+	_cairo_pattern_is_opaque (src, &composite->bounded))
+	op = CAIRO_OPERATOR_SOURCE;
+
+    if (dst->win32.base.is_clear && op == CAIRO_OPERATOR_OVER)
+	op = CAIRO_OPERATOR_SOURCE;
+
+    if (op == CAIRO_OPERATOR_SOURCE) {
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	if (src->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    status = copy_boxes (dst, src, boxes);
+	    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+		status = upload_boxes (dst, src, boxes);
+	} else if (src->type == CAIRO_PATTERN_TYPE_SOLID) {
+	    status = fill_boxes (dst, src, boxes);
+	}
+	return status;
+    }
+
+    if (op == CAIRO_OPERATOR_OVER && can_alpha_blend (dst))
+	return alpha_blend_boxes (dst, src, boxes, 255);
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+opacity_boxes (cairo_composite_rectangles_t *composite,
+	       cairo_boxes_t *boxes)
+{
+    cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface);
+    cairo_operator_t op = composite->op;
+    const cairo_pattern_t *src = &composite->source_pattern.base;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+    if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (boxes->num_boxes == 0 && composite->is_bounded)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (!boxes->is_pixel_aligned)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op != CAIRO_OPERATOR_OVER)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (!can_alpha_blend (dst))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    return alpha_blend_boxes (dst, src, boxes,
+			      composite->mask_pattern.solid.color.alpha_short >> 8);
+}
+
+/* high-level compositor interface */
+
+static cairo_bool_t check_blit (cairo_composite_rectangles_t *composite)
+{
+    cairo_win32_display_surface_t *dst;
+
+    if (composite->clip->path)
+	return FALSE;
+
+    dst = to_win32_display_surface (composite->surface);
+    if (dst->fallback)
+	return FALSE;
+
+    if (dst->win32.format != CAIRO_FORMAT_RGB24)
+	return FALSE;
+
+    if (dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)
+	return TRUE;
+
+    return dst->image == NULL;
+}
+
+static cairo_int_status_t
+_cairo_win32_gdi_compositor_paint (const cairo_compositor_t	*compositor,
+				   cairo_composite_rectangles_t *composite)
+{
+    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (check_blit (composite)) {
+	cairo_boxes_t boxes;
+
+	TRACE ((stderr, "%s\n", __FUNCTION__));
+	_cairo_clip_steal_boxes (composite->clip, &boxes);
+	status = draw_boxes (composite, &boxes);
+	_cairo_clip_unsteal_boxes (composite->clip, &boxes);
+    }
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_gdi_compositor_mask (const cairo_compositor_t	*compositor,
+				  cairo_composite_rectangles_t *composite)
+{
+    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (check_blit (composite)) {
+	cairo_boxes_t boxes;
+
+	TRACE ((stderr, "%s\n", __FUNCTION__));
+	_cairo_clip_steal_boxes (composite->clip, &boxes);
+	status = opacity_boxes (composite, &boxes);
+	_cairo_clip_unsteal_boxes (composite->clip, &boxes);
+    }
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_gdi_compositor_stroke (const cairo_compositor_t	*compositor,
+				    cairo_composite_rectangles_t *composite,
+				    const cairo_path_fixed_t	*path,
+				    const cairo_stroke_style_t	*style,
+				    const cairo_matrix_t	*ctm,
+				    const cairo_matrix_t	*ctm_inverse,
+				    double			 tolerance,
+				    cairo_antialias_t		 antialias)
+{
+    cairo_int_status_t status;
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (check_blit (composite) &&
+	_cairo_path_fixed_stroke_is_rectilinear (path)) {
+	cairo_boxes_t boxes;
+
+	TRACE ((stderr, "%s\n", __FUNCTION__));
+	_cairo_boxes_init_with_clip (&boxes, composite->clip);
+	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
+								style,
+								ctm,
+								antialias,
+								&boxes);
+	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
+	    status = draw_boxes (composite, &boxes);
+	_cairo_boxes_fini (&boxes);
+    }
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_gdi_compositor_fill (const cairo_compositor_t	*compositor,
+				  cairo_composite_rectangles_t	*composite,
+				  const cairo_path_fixed_t	*path,
+				  cairo_fill_rule_t		 fill_rule,
+				  double			 tolerance,
+				  cairo_antialias_t		 antialias)
+{
+    cairo_int_status_t status;
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (check_blit (composite) &&
+	_cairo_path_fixed_fill_is_rectilinear (path)) {
+	cairo_boxes_t boxes;
+
+	TRACE ((stderr, "%s\n", __FUNCTION__));
+	_cairo_boxes_init_with_clip (&boxes, composite->clip);
+	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
+							      fill_rule,
+							      antialias,
+							      &boxes);
+	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
+	    status = draw_boxes (composite, &boxes);
+	_cairo_boxes_fini (&boxes);
+    }
+
+    return status;
+}
+
+static cairo_bool_t check_glyphs (cairo_composite_rectangles_t *composite,
+				  cairo_scaled_font_t *scaled_font)
+{
+    if (! _cairo_clip_is_region (composite->clip))
+	return FALSE;
+
+    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
+	return FALSE;
+
+    if (! _cairo_pattern_is_opaque_solid (&composite->source_pattern.base))
+	return FALSE;
+
+    return (composite->op == CAIRO_OPERATOR_CLEAR ||
+	    composite->op == CAIRO_OPERATOR_SOURCE ||
+	    composite->op == CAIRO_OPERATOR_OVER);
+}
+
+static cairo_int_status_t
+_cairo_win32_gdi_compositor_glyphs (const cairo_compositor_t	*compositor,
+				    cairo_composite_rectangles_t*composite,
+				    cairo_scaled_font_t		*scaled_font,
+				    cairo_glyph_t		*glyphs,
+				    int				 num_glyphs,
+				    cairo_bool_t		 overlap)
+{
+    cairo_int_status_t status;
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (check_blit (composite) && check_glyphs (composite, scaled_font)) {
+	cairo_win32_display_surface_t *dst = to_win32_display_surface (composite->surface);
+
+	TRACE ((stderr, "%s\n", __FUNCTION__));
+	status = _cairo_win32_display_surface_set_clip(dst, composite->clip);
+	if (status)
+	    return status;
+
+	status = _cairo_win32_surface_emit_glyphs (&dst->win32,
+						   &composite->source_pattern.base,
+						   glyphs,
+						   num_glyphs,
+						   scaled_font,
+						   TRUE);
+
+	_cairo_win32_display_surface_unset_clip (dst);
+    }
+
+    return status;
+}
+
+const cairo_compositor_t *
+_cairo_win32_gdi_compositor_get (void)
+{
+    static cairo_compositor_t compositor;
+
+    if (compositor.delegate == NULL) {
+	compositor.delegate = &_cairo_fallback_compositor;
+
+	compositor.paint  = _cairo_win32_gdi_compositor_paint;
+	compositor.mask   = _cairo_win32_gdi_compositor_mask;
+	compositor.fill   = _cairo_win32_gdi_compositor_fill;
+	compositor.stroke = _cairo_win32_gdi_compositor_stroke;
+	compositor.glyphs = _cairo_win32_gdi_compositor_glyphs;
+    }
+
+    return &compositor;
+}
diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c
index 17a68f7..881a42f 100644
--- a/src/win32/cairo-win32-printing-surface.c
+++ b/src/win32/cairo-win32-printing-surface.c
@@ -102,36 +102,36 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend;
 
 static void
-_cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface)
+_cairo_win32_printing_surface_init_ps_mode (cairo_win32_printing_surface_t *surface)
 {
     DWORD word;
     INT ps_feature, ps_level;
 
     word = PSIDENT_GDICENTRIC;
-    if (ExtEscape (surface->dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0)
+    if (ExtEscape (surface->win32.dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0)
 	return;
 
     ps_feature = FEATURESETTING_PSLEVEL;
-    if (ExtEscape (surface->dc, GET_PS_FEATURESETTING, sizeof(INT),
+    if (ExtEscape (surface->win32.dc, GET_PS_FEATURESETTING, sizeof(INT),
 		   (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0)
 	return;
 
     if (ps_level >= 3)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+	surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
 }
 
 static void
-_cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface)
+_cairo_win32_printing_surface_init_image_support (cairo_win32_printing_surface_t *surface)
 {
     DWORD word;
 
     word = CHECKJPEGFORMAT;
-    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
+    if (ExtEscape(surface->win32.dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
+	surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
 
     word = CHECKPNGFORMAT;
-    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG;
+    if (ExtEscape(surface->win32.dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
+	surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG;
 }
 
 /* When creating an EMF file, ExtTextOut with ETO_GLYPH_INDEX does not
@@ -152,7 +152,7 @@ _cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface
  * and argument 0.
  */
 static void
-_cairo_win32_printing_surface_init_language_pack (cairo_win32_surface_t *surface)
+_cairo_win32_printing_surface_init_language_pack (cairo_win32_printing_surface_t *surface)
 {
     typedef BOOL (WINAPI *gdi_init_lang_pack_func_t)(int);
     gdi_init_lang_pack_func_t gdi_init_lang_pack;
@@ -219,7 +219,7 @@ surface_pattern_supported (const cairo_surface_pattern_t *pattern)
 }
 
 static cairo_bool_t
-pattern_supported (cairo_win32_surface_t *surface, const cairo_pattern_t *pattern)
+pattern_supported (cairo_win32_printing_surface_t *surface, const cairo_pattern_t *pattern)
 {
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 	return TRUE;
@@ -228,13 +228,13 @@ pattern_supported (cairo_win32_surface_t *surface, const cairo_pattern_t *patter
 	return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
 
     if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
-	return surface->flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+	return surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
 
     return FALSE;
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_analyze_operation (cairo_win32_printing_surface_t *surface,
                                                  cairo_operator_t       op,
                                                  const cairo_pattern_t *pattern)
 {
@@ -280,7 +280,7 @@ _cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface,
 }
 
 static cairo_bool_t
-_cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_operation_supported (cairo_win32_printing_surface_t *surface,
                                                    cairo_operator_t       op,
                                                    const cairo_pattern_t *pattern)
 {
@@ -291,7 +291,7 @@ _cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surfac
 }
 
 static void
-_cairo_win32_printing_surface_init_clear_color (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_init_clear_color (cairo_win32_printing_surface_t *surface,
 						cairo_solid_pattern_t *color)
 {
     if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
@@ -301,7 +301,7 @@ _cairo_win32_printing_surface_init_clear_color (cairo_win32_surface_t *surface,
 }
 
 static COLORREF
-_cairo_win32_printing_surface_flatten_transparency (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_flatten_transparency (cairo_win32_printing_surface_t *surface,
 						    const cairo_color_t   *color)
 {
     COLORREF c;
@@ -332,7 +332,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_win32_printing_surface_select_solid_brush (cairo_win32_printing_surface_t *surface,
                                                   const cairo_pattern_t *source)
 {
     cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source;
@@ -343,59 +343,59 @@ _cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface
     surface->brush = CreateSolidBrush (color);
     if (!surface->brush)
 	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)");
-    surface->old_brush = SelectObject (surface->dc, surface->brush);
+    surface->old_brush = SelectObject (surface->win32.dc, surface->brush);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_win32_printing_surface_done_solid_brush (cairo_win32_surface_t *surface)
+_cairo_win32_printing_surface_done_solid_brush (cairo_win32_printing_surface_t *surface)
 {
     if (surface->old_brush) {
-	SelectObject (surface->dc, surface->old_brush);
+	SelectObject (surface->win32.dc, surface->old_brush);
 	DeleteObject (surface->brush);
 	surface->old_brush = NULL;
     }
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_printing_surface_t *surface,
 						RECT                  *clip)
 {
     XFORM xform;
 
     _cairo_matrix_to_win32_xform (&surface->ctm, &xform);
-    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
+    if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY))
 	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform");
-    GetClipBox (surface->dc, clip);
+    GetClipBox (surface->win32.dc, clip);
 
     _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
-    if (!SetWorldTransform (surface->dc, &xform))
+    if (!SetWorldTransform (surface->win32.dc, &xform))
 	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_printing_surface_t *surface,
                                                    const cairo_pattern_t *pattern)
 {
     RECT clip;
     cairo_status_t status;
 
-    GetClipBox (surface->dc, &clip);
+    GetClipBox (surface->win32.dc, &clip);
     status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern);
     if (status)
 	return status;
 
-    FillRect (surface->dc, &clip, surface->brush);
+    FillRect (surface->win32.dc, &clip, surface->brush);
     _cairo_win32_printing_surface_done_solid_brush (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *surface,
+_cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_printing_surface_t   *surface,
 						       cairo_surface_pattern_t *pattern)
 {
     cairo_content_t old_content;
@@ -422,7 +422,7 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *
     old_has_ctm = surface->has_ctm;
     cairo_matrix_multiply (&p2d, &p2d, &surface->ctm);
     surface->ctm = p2d;
-    SaveDC (surface->dc);
+    SaveDC (surface->win32.dc);
     _cairo_matrix_to_win32_xform (&p2d, &xform);
 
     status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
@@ -461,7 +461,7 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *
 	    cairo_matrix_t m;
 	    double x, y;
 
-	    SaveDC (surface->dc);
+	    SaveDC (surface->win32.dc);
 	    m = p2d;
 	    cairo_matrix_translate (&m,
 				    x_tile*recording_extents.width,
@@ -480,39 +480,39 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *
 	    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
 
 	    /* Set clip path around bbox of the pattern. */
-	    BeginPath (surface->dc);
+	    BeginPath (surface->win32.dc);
 
 	    x = 0;
 	    y = 0;
 	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    MoveToEx (surface->dc, (int) x, (int) y, NULL);
+	    MoveToEx (surface->win32.dc, (int) x, (int) y, NULL);
 
 	    x = recording_extents.width;
 	    y = 0;
 	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
+	    LineTo (surface->win32.dc, (int) x, (int) y);
 
 	    x = recording_extents.width;
 	    y = recording_extents.height;
 	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
+	    LineTo (surface->win32.dc, (int) x, (int) y);
 
 	    x = 0;
 	    y = recording_extents.height;
 	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
+	    LineTo (surface->win32.dc, (int) x, (int) y);
 
-	    CloseFigure (surface->dc);
-	    EndPath (surface->dc);
-	    SelectClipPath (surface->dc, RGN_AND);
+	    CloseFigure (surface->win32.dc);
+	    EndPath (surface->win32.dc);
+	    SelectClipPath (surface->win32.dc, RGN_AND);
 
-	    SaveDC (surface->dc); /* Allow clip path to be reset during replay */
+	    SaveDC (surface->win32.dc); /* Allow clip path to be reset during replay */
 	    status = _cairo_recording_surface_replay_region (&recording_surface->base, NULL,
-							     &surface->base,
+							     &surface->win32.base,
 							     CAIRO_RECORDING_REGION_NATIVE);
 	    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 	    /* Restore both the clip save and our earlier path SaveDC */
-	    RestoreDC (surface->dc, -2);
+	    RestoreDC (surface->win32.dc, -2);
 
 	    if (status)
 		return status;
@@ -522,13 +522,13 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *
     surface->content = old_content;
     surface->ctm = old_ctm;
     surface->has_ctm = old_has_ctm;
-    RestoreDC (surface->dc, -1);
+    RestoreDC (surface->win32.dc, -1);
 
     return status;
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
+_cairo_win32_printing_surface_check_jpeg (cairo_win32_printing_surface_t   *surface,
 					  cairo_surface_t         *source,
 					  const unsigned char    **data,
 					  unsigned long           *length,
@@ -539,7 +539,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
     cairo_int_status_t status;
     DWORD result;
 
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG))
+    if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
@@ -552,7 +552,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
 	return status;
 
     result = 0;
-    if (ExtEscape(surface->dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data,
+    if (ExtEscape(surface->win32.dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data,
 		  sizeof(result), (char *) &result) <= 0)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -566,7 +566,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
+_cairo_win32_printing_surface_check_png (cairo_win32_printing_surface_t   *surface,
 					 cairo_surface_t         *source,
 					 const unsigned char    **data,
 					 unsigned long           *length,
@@ -578,7 +578,7 @@ _cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
     cairo_int_status_t status;
     DWORD result;
 
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG))
+    if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_PNG,
@@ -591,7 +591,7 @@ _cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
 	return status;
 
     result = 0;
-    if (ExtEscape(surface->dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data,
+    if (ExtEscape(surface->win32.dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data,
 		  sizeof(result), (char *) &result) <= 0)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -605,7 +605,7 @@ _cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surface,
+_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_t   *surface,
 						   cairo_surface_pattern_t *pattern)
 {
     cairo_status_t status;
@@ -629,7 +629,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
     /* If we can't use StretchDIBits with this surface, we can't do anything
      * here.
      */
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
+    if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
@@ -727,17 +727,17 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&m, &m, &surface->gdi_ctm);
-    SaveDC (surface->dc);
+    SaveDC (surface->win32.dc);
     _cairo_matrix_to_win32_xform (&m, &xform);
 
-    if (! SetWorldTransform (surface->dc, &xform)) {
+    if (! SetWorldTransform (surface->win32.dc, &xform)) {
 	status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern");
 	goto CLEANUP_OPAQUE_IMAGE;
     }
 
-    oldmode = SetStretchBltMode(surface->dc, HALFTONE);
+    oldmode = SetStretchBltMode(surface->win32.dc, HALFTONE);
 
-    GetClipBox (surface->dc, &clip);
+    GetClipBox (surface->win32.dc, &clip);
     if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
 	left = floor ( clip.left / (double) opaque_image->width);
 	right = ceil (clip.right / (double) opaque_image->width);
@@ -752,7 +752,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 
     for (y_tile = top; y_tile < bottom; y_tile++) {
 	for (x_tile = left; x_tile < right; x_tile++) {
-	    if (!StretchDIBits (surface->dc,
+	    if (!StretchDIBits (surface->win32.dc,
 				x_tile*opaque_image->width,
 				y_tile*opaque_image->height,
 				opaque_image->width,
@@ -771,8 +771,8 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 	    }
 	}
     }
-    SetStretchBltMode(surface->dc, oldmode);
-    RestoreDC (surface->dc, -1);
+    SetStretchBltMode(surface->win32.dc, oldmode);
+    RestoreDC (surface->win32.dc, -1);
 
 CLEANUP_OPAQUE_IMAGE:
     if (opaque_image != image)
@@ -784,7 +784,7 @@ CLEANUP_IMAGE:
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t   *surface,
+_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_printing_surface_t   *surface,
                                                      cairo_surface_pattern_t *pattern)
 {
     if (_cairo_surface_is_recording (pattern->surface)) {
@@ -809,7 +809,7 @@ vertex_set_color (TRIVERTEX *vert, cairo_color_stop_t *color)
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface_t *surface,
                                                     cairo_linear_pattern_t *pattern)
 {
     TRIVERTEX *vert;
@@ -825,7 +825,7 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
     cairo_status_t status;
 
     extend = cairo_pattern_get_extend (&pattern->base.base);
-    SaveDC (surface->dc);
+    SaveDC (surface->win32.dc);
 
     mat = pattern->base.base.matrix;
     status = cairo_matrix_invert (&mat);
@@ -853,10 +853,10 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
 
     _cairo_matrix_to_win32_xform (&mat, &xform);
 
-    if (!SetWorldTransform (surface->dc, &xform))
+    if (!SetWorldTransform (surface->win32.dc, &xform))
 	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2");
 
-    GetClipBox (surface->dc, &clip);
+    GetClipBox (surface->win32.dc, &clip);
 
     if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
 	range_start = floor (clip.left / d);
@@ -939,7 +939,7 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
 	total_rects += 2;
     }
 
-    if (!GradientFill (surface->dc,
+    if (!GradientFill (surface->win32.dc,
 		       vert, total_verts,
 		       rect, total_rects,
 		       GRADIENT_FILL_RECT_H))
@@ -947,13 +947,13 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
 
     free (rect);
     free (vert);
-    RestoreDC (surface->dc, -1);
+    RestoreDC (surface->win32.dc, -1);
 
     return 0;
 }
 
 static cairo_int_status_t
-_cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
+_cairo_win32_printing_surface_paint_pattern (cairo_win32_printing_surface_t *surface,
                                              const cairo_pattern_t *pattern)
 {
     cairo_status_t status;
@@ -990,7 +990,7 @@ _cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
 }
 
 typedef struct _win32_print_path_info {
-    cairo_win32_surface_t *surface;
+    cairo_win32_printing_surface_t *surface;
 } win32_path_info_t;
 
 static cairo_status_t
@@ -1005,9 +1005,9 @@ _cairo_win32_printing_surface_path_move_to (void *closure,
 	x = _cairo_fixed_to_double (point->x);
 	y = _cairo_fixed_to_double (point->y);
 	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	MoveToEx (path_info->surface->dc, (int) x, (int) y, NULL);
+	MoveToEx (path_info->surface->win32.dc, (int) x, (int) y, NULL);
     } else {
-	MoveToEx (path_info->surface->dc,
+	MoveToEx (path_info->surface->win32.dc,
 		  _cairo_fixed_integer_part (point->x),
 		  _cairo_fixed_integer_part (point->y),
 		  NULL);
@@ -1029,9 +1029,9 @@ _cairo_win32_printing_surface_path_line_to (void *closure,
 	x = _cairo_fixed_to_double (point->x);
 	y = _cairo_fixed_to_double (point->y);
 	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	LineTo (path_info->surface->dc, (int) x, (int) y);
+	LineTo (path_info->surface->win32.dc, (int) x, (int) y);
     } else {
-	LineTo (path_info->surface->dc,
+	LineTo (path_info->surface->win32.dc,
 		_cairo_fixed_integer_part (point->x),
 		_cairo_fixed_integer_part (point->y));
     }
@@ -1077,7 +1077,7 @@ _cairo_win32_printing_surface_path_curve_to (void          *closure,
 	points[2].x = _cairo_fixed_integer_part (d->x);
 	points[2].y = _cairo_fixed_integer_part (d->y);
     }
-    PolyBezierTo (path_info->surface->dc, points, 3);
+    PolyBezierTo (path_info->surface->win32.dc, points, 3);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1087,13 +1087,13 @@ _cairo_win32_printing_surface_path_close_path (void *closure)
 {
     win32_path_info_t *path_info = closure;
 
-    CloseFigure (path_info->surface->dc);
+    CloseFigure (path_info->surface->win32.dc);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_win32_printing_surface_emit_path (cairo_win32_surface_t    *surface,
+_cairo_win32_printing_surface_emit_path (cairo_win32_printing_surface_t    *surface,
 					 const cairo_path_fixed_t *path)
 {
     win32_path_info_t path_info;
@@ -1110,10 +1110,10 @@ _cairo_win32_printing_surface_emit_path (cairo_win32_surface_t    *surface,
 static cairo_int_status_t
 _cairo_win32_printing_surface_show_page (void *abstract_surface)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
 
     /* Undo both SaveDC's that we did in start_page */
-    RestoreDC (surface->dc, -2);
+    RestoreDC (surface->win32.dc, -2);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1125,8 +1125,8 @@ _cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper
                                                    double	       tolerance,
                                                    cairo_antialias_t   antialias)
 {
-    cairo_win32_surface_t *surface = cairo_container_of (clipper,
-							 cairo_win32_surface_t,
+    cairo_win32_printing_surface_t *surface = cairo_container_of (clipper,
+							 cairo_win32_printing_surface_t,
 							 clipper);
     cairo_status_t status;
 
@@ -1134,28 +1134,28 @@ _cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper
 	return CAIRO_STATUS_SUCCESS;
 
     if (path == NULL) {
-	RestoreDC (surface->dc, -1);
-	SaveDC (surface->dc);
+	RestoreDC (surface->win32.dc, -1);
+	SaveDC (surface->win32.dc);
 
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    BeginPath (surface->dc);
+    BeginPath (surface->win32.dc);
     status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
+    EndPath (surface->win32.dc);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
-	SetPolyFillMode (surface->dc, WINDING);
+	SetPolyFillMode (surface->win32.dc, WINDING);
 	break;
     case CAIRO_FILL_RULE_EVEN_ODD:
-	SetPolyFillMode (surface->dc, ALTERNATE);
+	SetPolyFillMode (surface->win32.dc, ALTERNATE);
 	break;
     default:
 	ASSERT_NOT_REACHED;
     }
 
-    SelectClipPath (surface->dc, RGN_AND);
+    SelectClipPath (surface->win32.dc, RGN_AND);
 
     return status;
 }
@@ -1178,7 +1178,7 @@ _cairo_win32_printing_surface_paint (void			*abstract_surface,
                                      const cairo_pattern_t	*source,
 				     const cairo_clip_t      *clip)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
     cairo_solid_pattern_t clear;
     cairo_status_t status;
 
@@ -1261,7 +1261,7 @@ _cairo_win32_printing_surface_stroke (void			*abstract_surface,
                                       cairo_antialias_t		antialias,
 				      const cairo_clip_t    *clip)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
     HPEN pen;
     LOGBRUSH brush;
@@ -1311,7 +1311,7 @@ _cairo_win32_printing_surface_stroke (void			*abstract_surface,
 	pen_style |= PS_SOLID;
     }
 
-    SetMiterLimit (surface->dc, (FLOAT) (style->miter_limit), NULL);
+    SetMiterLimit (surface->win32.dc, (FLOAT) (style->miter_limit), NULL);
     if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
 	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
 
@@ -1334,43 +1334,43 @@ _cairo_win32_printing_surface_stroke (void			*abstract_surface,
 		       dash_array);
     if (pen == NULL)
 	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen");
-    obj = SelectObject (surface->dc, pen);
+    obj = SelectObject (surface->win32.dc, pen);
     if (obj == NULL)
 	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject");
 
-    BeginPath (surface->dc);
+    BeginPath (surface->win32.dc);
     status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
+    EndPath (surface->win32.dc);
     if (status)
 	return status;
 
     /*
      * Switch to user space to set line parameters
      */
-    SaveDC (surface->dc);
+    SaveDC (surface->win32.dc);
 
     _cairo_matrix_to_win32_xform (&mat, &xform);
     xform.eDx = 0.0f;
     xform.eDy = 0.0f;
 
-    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
+    if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY))
 	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform");
 
     if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	StrokePath (surface->dc);
+	StrokePath (surface->win32.dc);
     } else {
-	if (!WidenPath (surface->dc))
+	if (!WidenPath (surface->win32.dc))
 	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath");
-	if (!SelectClipPath (surface->dc, RGN_AND))
+	if (!SelectClipPath (surface->win32.dc, RGN_AND))
 	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath");
 
 	/* Return to device space to paint the pattern */
 	_cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
-	if (!SetWorldTransform (surface->dc, &xform))
+	if (!SetWorldTransform (surface->win32.dc, &xform))
 	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform");
 	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
     }
-    RestoreDC (surface->dc, -1);
+    RestoreDC (surface->win32.dc, -1);
     DeleteObject (pen);
     free (dash_array);
 
@@ -1387,7 +1387,7 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
 				    cairo_antialias_t		 antialias,
 				    const cairo_clip_t		*clip)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
     cairo_solid_pattern_t clear;
 
@@ -1407,16 +1407,16 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
     assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
 
     surface->path_empty = TRUE;
-    BeginPath (surface->dc);
+    BeginPath (surface->win32.dc);
     status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
+    EndPath (surface->win32.dc);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
-	SetPolyFillMode (surface->dc, WINDING);
+	SetPolyFillMode (surface->win32.dc, WINDING);
 	break;
     case CAIRO_FILL_RULE_EVEN_ODD:
-	SetPolyFillMode (surface->dc, ALTERNATE);
+	SetPolyFillMode (surface->win32.dc, ALTERNATE);
 	break;
     default:
 	ASSERT_NOT_REACHED;
@@ -1427,13 +1427,13 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
 	if (status)
 	    return status;
 
-	FillPath (surface->dc);
+	FillPath (surface->win32.dc);
 	_cairo_win32_printing_surface_done_solid_brush (surface);
     } else if (surface->path_empty == FALSE) {
-	SaveDC (surface->dc);
-	SelectClipPath (surface->dc, RGN_AND);
+	SaveDC (surface->win32.dc);
+	SelectClipPath (surface->win32.dc, RGN_AND);
 	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
-	RestoreDC (surface->dc, -1);
+	RestoreDC (surface->win32.dc, -1);
     }
 
     fflush(stderr);
@@ -1441,13 +1441,14 @@ _cairo_win32_printing_surface_fill (void		        *abstract_surface,
     return status;
 }
 
+
 static cairo_int_status_t
-_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t 	*surface,
+_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_printing_surface_t	*surface,
 						 cairo_operator_t	 op,
 						 const cairo_pattern_t  *source,
-						 cairo_glyph_t        	*glyphs,
+						 cairo_glyph_t		 *glyphs,
 						 int			 num_glyphs,
-						 cairo_scaled_font_t  	*scaled_font,
+						 cairo_scaled_font_t	*scaled_font,
 						 const cairo_clip_t	*clip)
 {
     cairo_matrix_t ctm;
@@ -1502,15 +1503,12 @@ _cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t 	*surface
 	if (i == num_glyphs - 1 ||
 	    ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode))
 	{
-	    status = _cairo_win32_surface_show_glyphs_internal (
-		surface,
-		op,
-		source,
-		sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
-		i - first + 1,
-		scaled_font,
-		clip,
-		! sequence_is_unicode);
+	    status = _cairo_win32_surface_emit_glyphs (&surface->win32,
+						       source,
+						       sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
+						       i - first + 1,
+						       scaled_font,
+						       ! sequence_is_unicode);
 	    first = i + 1;
 	    if (i < num_glyphs - 1)
 		sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff;
@@ -1536,7 +1534,7 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
                                            cairo_scaled_font_t  *scaled_font,
 					   const cairo_clip_t	*clip)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_pattern_t *opaque = NULL;
@@ -1620,12 +1618,12 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
     }
 #endif
 
-    SaveDC (surface->dc);
+    SaveDC (surface->win32.dc);
     old_ctm = surface->ctm;
     old_has_ctm = surface->has_ctm;
     surface->has_ctm = TRUE;
     surface->path_empty = TRUE;
-    BeginPath (surface->dc);
+    BeginPath (surface->win32.dc);
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_glyph_lookup (scaled_font,
 					     glyphs[i].index,
@@ -1637,7 +1635,7 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 	cairo_matrix_translate (&surface->ctm, glyphs[i].x, glyphs[i].y);
 	status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path);
     }
-    EndPath (surface->dc);
+    EndPath (surface->win32.dc);
     surface->ctm = old_ctm;
     surface->has_ctm = old_has_ctm;
     if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
@@ -1646,15 +1644,15 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 	    if (status)
 		return status;
 
-	    SetPolyFillMode (surface->dc, WINDING);
-	    FillPath (surface->dc);
+	    SetPolyFillMode (surface->win32.dc, WINDING);
+	    FillPath (surface->win32.dc);
 	    _cairo_win32_printing_surface_done_solid_brush (surface);
 	} else {
-	    SelectClipPath (surface->dc, RGN_AND);
+	    SelectClipPath (surface->win32.dc, RGN_AND);
 	    status = _cairo_win32_printing_surface_paint_pattern (surface, source);
 	}
     }
-    RestoreDC (surface->dc, -1);
+    RestoreDC (surface->win32.dc, -1);
 
     if (opaque)
 	cairo_pattern_destroy (opaque);
@@ -1668,6 +1666,17 @@ _cairo_win32_printing_surface_get_supported_mime_types (void	  *abstract_surface
     return _cairo_win32_printing_supported_mime_types;
 }
 
+static cairo_status_t
+_cairo_win32_printing_surface_finish (void *abstract_surface)
+{
+    cairo_win32_printing_surface_t *surface = abstract_surface;
+
+    if (surface->font_subsets != NULL)
+	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_surface_t *
 _cairo_win32_printing_surface_create_similar (void		*abstract_surface,
 					      cairo_content_t	 content,
@@ -1685,13 +1694,13 @@ _cairo_win32_printing_surface_create_similar (void		*abstract_surface,
 static cairo_int_status_t
 _cairo_win32_printing_surface_start_page (void *abstract_surface)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
     XFORM xform;
     double x_res, y_res;
     cairo_matrix_t inverse_ctm;
     cairo_status_t status;
 
-    SaveDC (surface->dc); /* Save application context first, before doing MWT */
+    SaveDC (surface->win32.dc); /* Save application context first, before doing MWT */
 
     /* As the logical coordinates used by GDI functions (eg LineTo)
      * are integers we need to do some additional work to prevent
@@ -1730,8 +1739,8 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
      * To support allowing the user to set a GDI CTM with scale < 1,
      * we avoid switching to an identity CTM if the CTM xx and yy is < 1.
      */
-    SetGraphicsMode (surface->dc, GM_ADVANCED);
-    GetWorldTransform(surface->dc, &xform);
+    SetGraphicsMode (surface->win32.dc, GM_ADVANCED);
+    GetWorldTransform(surface->win32.dc, &xform);
     if (xform.eM11 < 1 && xform.eM22 < 1) {
 	cairo_matrix_init_identity (&surface->ctm);
 	surface->gdi_ctm.xx = xform.eM11;
@@ -1748,7 +1757,7 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
 	surface->ctm.x0 = xform.eDx;
 	surface->ctm.y0 = xform.eDy;
 	cairo_matrix_init_identity (&surface->gdi_ctm);
-	if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY))
+	if (!ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY))
 	    return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform");
     }
 
@@ -1759,12 +1768,12 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
     if (status)
 	return status;
 
-    x_res = GetDeviceCaps (surface->dc, LOGPIXELSX);
-    y_res = GetDeviceCaps (surface->dc, LOGPIXELSY);
+    x_res = GetDeviceCaps (surface->win32.dc, LOGPIXELSX);
+    y_res = GetDeviceCaps (surface->win32.dc, LOGPIXELSY);
     cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res);
-    _cairo_surface_set_resolution (&surface->base, x_res, y_res);
+    _cairo_surface_set_resolution (&surface->win32.base, x_res, y_res);
 
-    SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */
+    SaveDC (surface->win32.dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1773,7 +1782,7 @@ static void
 _cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
                                                   cairo_paginated_mode_t paginated_mode)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_printing_surface_t *surface = abstract_surface;
 
     surface->paginated_mode = paginated_mode;
 }
@@ -1805,30 +1814,29 @@ _cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_su
 cairo_surface_t *
 cairo_win32_printing_surface_create (HDC hdc)
 {
-    cairo_win32_surface_t *surface;
+    cairo_win32_printing_surface_t *surface;
     cairo_surface_t *paginated;
     RECT rect;
 
-    surface = malloc (sizeof (cairo_win32_surface_t));
+    surface = malloc (sizeof (cairo_win32_printing_surface_t));
     if (surface == NULL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
+#if 0
     if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
 	free (surface);
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
+#endif
 
     _cairo_surface_clipper_init (&surface->clipper,
 				 _cairo_win32_printing_surface_clipper_intersect_clip_path);
 
-    surface->image = NULL;
-    surface->format = CAIRO_FORMAT_RGB24;
-    surface->content = CAIRO_CONTENT_COLOR_ALPHA;
+    surface->win32.format = CAIRO_FORMAT_RGB24;
+    surface->win32.base.content = CAIRO_CONTENT_COLOR_ALPHA;
+
+    surface->win32.dc = hdc;
 
-    surface->dc = hdc;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-    surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
     surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
@@ -1838,41 +1846,35 @@ cairo_win32_printing_surface_create (HDC hdc)
     }
 
     GetClipBox(hdc, &rect);
-    surface->extents.x = rect.left;
-    surface->extents.y = rect.top;
-    surface->extents.width = rect.right - rect.left;
-    surface->extents.height = rect.bottom - rect.top;
+    surface->win32.extents.x = rect.left;
+    surface->win32.extents.y = rect.top;
+    surface->win32.extents.width = rect.right - rect.left;
+    surface->win32.extents.height = rect.bottom - rect.top;
 
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-    surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
+    surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc);
+    surface->win32.flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
 
     _cairo_win32_printing_surface_init_ps_mode (surface);
     _cairo_win32_printing_surface_init_image_support (surface);
     _cairo_win32_printing_surface_init_language_pack (surface);
-    _cairo_surface_init (&surface->base,
+    _cairo_surface_init (&surface->win32.base,
 			 &cairo_win32_printing_surface_backend,
 			 NULL, /* device */
                          CAIRO_CONTENT_COLOR_ALPHA);
 
-    paginated = _cairo_paginated_surface_create (&surface->base,
+    paginated = _cairo_paginated_surface_create (&surface->win32.base,
 						 CAIRO_CONTENT_COLOR_ALPHA,
 						 &cairo_win32_surface_paginated_backend);
 
     /* paginated keeps the only reference to surface now, drop ours */
-    cairo_surface_destroy (&surface->base);
+    cairo_surface_destroy (&surface->win32.base);
 
     return paginated;
 }
 
-cairo_bool_t
-_cairo_surface_is_win32_printing (cairo_surface_t *surface)
-{
-    return surface->backend == &cairo_win32_printing_surface_backend;
-}
-
 static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
-    _cairo_win32_surface_finish,
+    _cairo_win32_printing_surface_finish,
 
     _cairo_default_context_create,
 
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
index 07830dc..b6c2431 100644
--- a/src/win32/cairo-win32-private.h
+++ b/src/win32/cairo-win32-private.h
@@ -37,8 +37,12 @@
 #define CAIRO_WIN32_PRIVATE_H
 
 #include "cairo-win32.h"
+
 #include "cairoint.h"
+
+#include "cairo-device-private.h"
 #include "cairo-surface-clipper-private.h"
+#include "cairo-surface-private.h"
 
 #ifndef SHADEBLENDCAPS
 #define SHADEBLENDCAPS 120
@@ -49,13 +53,59 @@
 
 #define WIN32_FONT_LOGICAL_SCALE 32
 
+/* Surface DC flag values */
+enum {
+    /* If this is a surface created for printing or not */
+    CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
+
+    /* Whether the DC is a display DC or not */
+    CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
+
+    /* Whether we can use BitBlt with this surface */
+    CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
+
+    /* Whether we can use AlphaBlend with this surface */
+    CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
+
+    /* Whether we can use StretchBlt with this surface */
+    CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
+
+    /* Whether we can use StretchDIBits with this surface */
+    CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5),
+
+    /* Whether we can use GradientFill rectangles with this surface */
+    CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
+
+    /* Whether we can use the CHECKJPEGFORMAT escape function */
+    CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
+
+    /* Whether we can use the CHECKJPEGFORMAT escape function */
+    CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
+};
+
 typedef struct _cairo_win32_surface {
     cairo_surface_t base;
 
     cairo_format_t format;
-
     HDC dc;
 
+    /* Surface DC flags */
+    unsigned flags;
+
+    /* We use the x and y parts of extents for situations where
+     * we're not supposed to draw to the entire surface.
+     * For example, during a paint event a program will get
+     * a DC that has been clipped to the dirty region.
+     * A cairo surface constructed for that DC will have extents
+     * that match bounds of the clipped region.
+     */
+    cairo_rectangle_int_t extents;
+} cairo_win32_surface_t;
+#define to_win32_surface(S) ((cairo_win32_surface_t *)(S))
+
+typedef struct _cairo_win32_display_surface {
+    cairo_win32_surface_t win32;
+
     /* We create off-screen surfaces as DIBs or DDBs, based on what we created
      * originally*/
     HBITMAP bitmap;
@@ -69,37 +119,19 @@ typedef struct _cairo_win32_surface {
      * on some versions of Windows.
      */
     HBITMAP saved_dc_bitmap;
-
     cairo_surface_t *image;
+    cairo_surface_t *fallback;
 
-    /* We use the x and y parts of extents for situations where
-     * we're not supposed to draw to the entire surface.
-     * For example, during a paint event a program will get
-     * a DC that has been clipped to the dirty region.
-     * A cairo surface constructed for that DC will have extents
-     * that match bounds of the clipped region.
-     *
-     * jrmuizel: I'm not sure if storing these extents instead
-     * of just using the size is better... */
-    cairo_rectangle_int_t extents;
-
-    /* Initial clip bits
-     * We need these kept around so that we maintain
-     * whatever clip was set on the original DC at creation
-     * time when cairo is asked to reset the surface clip.
-     */
-    cairo_rectangle_int_t clip_rect;
     HRGN initial_clip_rgn;
     cairo_bool_t had_simple_clip;
-    cairo_region_t *clip_region;
+} cairo_win32_display_surface_t;
+#define to_win32_display_surface(S) ((cairo_win32_display_surface_t *)(S))
 
-    /* For path clipping to the printing-surface */
-    cairo_surface_clipper_t clipper;
+typedef struct _cairo_win32_printing_surface {
+    cairo_win32_surface_t win32;
 
-    /* Surface DC flags */
-    uint32_t flags;
+    cairo_surface_clipper_t clipper;
 
-    /* printing surface bits */
     cairo_paginated_mode_t paginated_mode;
     cairo_content_t content;
     cairo_bool_t path_empty;
@@ -109,49 +141,44 @@ typedef struct _cairo_win32_surface {
     cairo_matrix_t gdi_ctm;
     HBRUSH brush, old_brush;
     cairo_scaled_font_subsets_t *font_subsets;
-} cairo_win32_surface_t;
+} cairo_win32_printing_surface_t;
+#define to_win32_printing_surface(S) ((cairo_win32_printing_surface_t *)(S))
 
-/* Surface DC flag values */
-enum {
-    /* If this is a surface created for printing or not */
-    CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
-
-    /* Whether the DC is a display DC or not */
-    CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
-
-    /* Whether we can use BitBlt with this surface */
-    CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
+typedef BOOL (WINAPI *cairo_win32_alpha_blend_func_t) (HDC hdcDest,
+						       int nXOriginDest,
+						       int nYOriginDest,
+						       int nWidthDest,
+						       int hHeightDest,
+						       HDC hdcSrc,
+						       int nXOriginSrc,
+						       int nYOriginSrc,
+						       int nWidthSrc,
+						       int nHeightSrc,
+						       BLENDFUNCTION blendFunction);
 
-    /* Whether we can use AlphaBlend with this surface */
-    CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
+typedef struct _cairo_win32_device {
+    cairo_device_t base;
 
-    /* Whether we can use StretchBlt with this surface */
-    CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
+    HMODULE msimg32_dll;
 
-    /* Whether we can use StretchDIBits with this surface */
-    CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5),
+    const cairo_compositor_t *compositor;
 
-    /* Whether we can use GradientFill rectangles with this surface */
-    CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
+    cairo_win32_alpha_blend_func_t alpha_blend;
+} cairo_win32_device_t;
+#define to_win32_device(D) ((cairo_win32_device_t *)(D))
+#define to_win32_device_from_surface(S) to_win32_device(((cairo_surface_t *)(S))->device)
 
-    /* Whether we can use the CHECKJPEGFORMAT escape function */
-    CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
+cairo_private cairo_device_t *
+_cairo_win32_device_get (void);
 
-    /* Whether we can use the CHECKJPEGFORMAT escape function */
-    CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
-};
+const cairo_compositor_t *
+_cairo_win32_gdi_compositor_get (void);
 
 cairo_status_t
 _cairo_win32_print_gdi_error (const char *context);
 
-cairo_bool_t
-_cairo_surface_is_win32 (cairo_surface_t *surface);
-
-cairo_bool_t
-_cairo_surface_is_win32_printing (cairo_surface_t *surface);
-
-cairo_status_t
-_cairo_win32_surface_finish (void *abstract_surface);
+cairo_private void
+_cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface);
 
 cairo_bool_t
 _cairo_win32_surface_get_extents (void		          *abstract_surface,
@@ -160,34 +187,13 @@ _cairo_win32_surface_get_extents (void		          *abstract_surface,
 uint32_t
 _cairo_win32_flags_for_dc (HDC dc);
 
-cairo_status_t
-_cairo_win32_surface_set_clip_region (void           *abstract_surface,
-				      cairo_region_t *region);
-
 cairo_int_status_t
-_cairo_win32_surface_show_glyphs_internal (void			 *surface,
-					   cairo_operator_t	  op,
-					   const cairo_pattern_t *source,
-					   cairo_glyph_t	 *glyphs,
-					   int			  num_glyphs,
-					   cairo_scaled_font_t	 *scaled_font,
-					   const cairo_clip_t	 *clip,
-					   cairo_bool_t		  glyph_indices);
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs (void			*surface,
-				  cairo_operator_t	 op,
-				  const cairo_pattern_t	*source,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font,
-				  const cairo_clip_t	*clip);
-
-cairo_surface_t *
-_cairo_win32_surface_create_similar (void	    *abstract_src,
-				     cairo_content_t content,
-				     int	     width,
-				     int	     height);
+_cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
+				  const cairo_pattern_t *source,
+				  cairo_glyph_t	 *glyphs,
+				  int			  num_glyphs,
+				  cairo_scaled_font_t	 *scaled_font,
+				  cairo_bool_t		  glyph_indexing);
 
 static inline void
 _cairo_matrix_to_win32_xform (const cairo_matrix_t *m,
@@ -201,11 +207,12 @@ _cairo_matrix_to_win32_xform (const cairo_matrix_t *m,
     xform->eDy = (FLOAT) m->y0;
 }
 
-cairo_int_status_t
-_cairo_win32_save_initial_clip (HDC dc, cairo_win32_surface_t *surface);
+cairo_status_t
+_cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface,
+				       cairo_clip_t *clip);
 
-cairo_int_status_t
-_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface);
+void
+_cairo_win32_display_surface_unset_clip (cairo_win32_display_surface_t *surface);
 
 void
 _cairo_win32_debug_dump_hrgn (HRGN rgn, char *header);
diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c
index ec351d3..cec47a2 100644
--- a/src/win32/cairo-win32-surface.c
+++ b/src/win32/cairo-win32-surface.c
@@ -2,6 +2,7 @@
 /* Cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -47,8 +48,6 @@
 
 #include "cairoint.h"
 
-#include "cairo-clip-private.h"
-#include "cairo-composite-rectangles-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
 #include "cairo-image-surface-private.h"
@@ -66,18 +65,6 @@
 # define ETO_PDY 0x2000
 #endif
 
-#undef DEBUG_COMPOSITE
-
-/* for older SDKs */
-#ifndef SHADEBLENDCAPS
-#define SHADEBLENDCAPS  120
-#endif
-#ifndef SB_NONE
-#define SB_NONE         0x00000000
-#endif
-
-#define PELS_72DPI  ((LONG)(72. / 0.0254))
-
 /**
  * SECTION:cairo-win32
  * @Title: Win32 Surfaces
@@ -102,8 +89,6 @@
  * This macro can be used to conditionally compile backend-specific code.
  */
 
-static const cairo_surface_backend_t cairo_win32_surface_backend;
-
 /**
  * _cairo_win32_print_gdi_error:
  * @context: context string to display along with the error
@@ -139,1399 +124,84 @@ _cairo_win32_print_gdi_error (const char *context)
      * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there
      * is no CAIRO_STATUS_UNKNOWN_ERROR.
      */
-
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 }
 
-uint32_t
-_cairo_win32_flags_for_dc (HDC dc)
-{
-    uint32_t flags = 0;
-
-    if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
-	flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY;
-
-	/* These will always be possible, but the actual GetDeviceCaps
-	 * calls will return whether they're accelerated or not.
-	 * We may want to use our own (pixman) routines sometimes
-	 * if they're eventually faster, but for now have GDI do
-	 * everything.
-	 */
-	flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
-	flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
-	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
-	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
-    } else {
-	int cap;
-
-	cap = GetDeviceCaps(dc, SHADEBLENDCAPS);
-	if (cap != SB_NONE)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
-
-	cap = GetDeviceCaps(dc, RASTERCAPS);
-	if (cap & RC_BITBLT)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
-	if (cap & RC_STRETCHBLT)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
-	if (cap & RC_STRETCHDIB)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
-    }
-
-    return flags;
-}
-
-static cairo_status_t
-_create_dc_and_bitmap (cairo_win32_surface_t *surface,
-		       HDC                    original_dc,
-		       cairo_format_t         format,
-		       int                    width,
-		       int                    height,
-		       unsigned char        **bits_out,
-		       int                   *rowstride_out)
-{
-    cairo_status_t status;
-
-    BITMAPINFO *bitmap_info = NULL;
-    struct {
-	BITMAPINFOHEADER bmiHeader;
-	RGBQUAD bmiColors[2];
-    } bmi_stack;
-    void *bits;
-
-    int num_palette = 0;	/* Quiet GCC */
-    int i;
-
-    surface->dc = NULL;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-
-    switch (format) {
-    default:
-    case CAIRO_FORMAT_INVALID:
-	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-    case CAIRO_FORMAT_ARGB32:
-    case CAIRO_FORMAT_RGB24:
-	num_palette = 0;
-	break;
-
-    case CAIRO_FORMAT_A8:
-	num_palette = 256;
-	break;
-
-    case CAIRO_FORMAT_A1:
-	num_palette = 2;
-	break;
-    }
-
-    if (num_palette > 2) {
-	bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
-	if (!bitmap_info)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    } else {
-	bitmap_info = (BITMAPINFO *)&bmi_stack;
-    }
-
-    bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-    bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
-    bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
-    bitmap_info->bmiHeader.biSizeImage = 0;
-    bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
-    bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
-    bitmap_info->bmiHeader.biPlanes = 1;
-
-    switch (format) {
-    /* We can't create real RGB24 bitmaps because something seems to
-     * break if we do, especially if we don't set up an image
-     * fallback.  It could be a bug with using a 24bpp pixman image
-     * (and creating one with masks).  So treat them like 32bpp.
-     * Note: This causes problems when using BitBlt/AlphaBlend/etc!
-     * see end of file.
-     */
-    case CAIRO_FORMAT_RGB24:
-    case CAIRO_FORMAT_ARGB32:
-	bitmap_info->bmiHeader.biBitCount = 32;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 0;	/* unused */
-	bitmap_info->bmiHeader.biClrImportant = 0;
-	break;
-
-    case CAIRO_FORMAT_A8:
-	bitmap_info->bmiHeader.biBitCount = 8;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 256;
-	bitmap_info->bmiHeader.biClrImportant = 0;
-
-	for (i = 0; i < 256; i++) {
-	    bitmap_info->bmiColors[i].rgbBlue = i;
-	    bitmap_info->bmiColors[i].rgbGreen = i;
-	    bitmap_info->bmiColors[i].rgbRed = i;
-	    bitmap_info->bmiColors[i].rgbReserved = 0;
-	}
-
-	break;
-
-    case CAIRO_FORMAT_A1:
-	bitmap_info->bmiHeader.biBitCount = 1;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 2;
-	bitmap_info->bmiHeader.biClrImportant = 0;
-
-	for (i = 0; i < 2; i++) {
-	    bitmap_info->bmiColors[i].rgbBlue = i * 255;
-	    bitmap_info->bmiColors[i].rgbGreen = i * 255;
-	    bitmap_info->bmiColors[i].rgbRed = i * 255;
-	    bitmap_info->bmiColors[i].rgbReserved = 0;
-	}
-
-	break;
-    }
-
-    surface->dc = CreateCompatibleDC (original_dc);
-    if (!surface->dc)
-	goto FAIL;
-
-    surface->bitmap = CreateDIBSection (surface->dc,
-			                bitmap_info,
-			                DIB_RGB_COLORS,
-			                &bits,
-			                NULL, 0);
-    if (!surface->bitmap)
-	goto FAIL;
-
-    surface->is_dib = TRUE;
-
-    GdiFlush();
-
-    surface->saved_dc_bitmap = SelectObject (surface->dc,
-					     surface->bitmap);
-    if (!surface->saved_dc_bitmap)
-	goto FAIL;
-
-    if (bitmap_info && num_palette > 2)
-	free (bitmap_info);
-
-    if (bits_out)
-	*bits_out = bits;
-
-    if (rowstride_out) {
-	/* Windows bitmaps are padded to 32-bit (dword) boundaries */
-	switch (format) {
-	case CAIRO_FORMAT_ARGB32:
-	case CAIRO_FORMAT_RGB24:
-	    *rowstride_out = 4 * width;
-	    break;
-
-	case CAIRO_FORMAT_A8:
-	    *rowstride_out = (width + 3) & ~3;
-	    break;
-
-	case CAIRO_FORMAT_A1:
-	    *rowstride_out = ((width + 31) & ~31) / 8;
-	    break;
-	}
-    }
-
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-
-    return CAIRO_STATUS_SUCCESS;
-
- FAIL:
-    status = _cairo_win32_print_gdi_error ("_create_dc_and_bitmap");
-
-    if (bitmap_info && num_palette > 2)
-	free (bitmap_info);
-
-    if (surface->saved_dc_bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	surface->saved_dc_bitmap = NULL;
-    }
-
-    if (surface->bitmap) {
-	DeleteObject (surface->bitmap);
-	surface->bitmap = NULL;
-    }
-
-    if (surface->dc) {
- 	DeleteDC (surface->dc);
-	surface->dc = NULL;
-    }
-
-    return status;
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_create_for_dc (HDC             original_dc,
-				    cairo_format_t  format,
-				    int	            width,
-				    int	            height)
-{
-    cairo_status_t status;
-    cairo_win32_surface_t *surface;
-    unsigned char *bits;
-    int rowstride;
-
-    if (! CAIRO_FORMAT_VALID (format))
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-
-    surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    surface->clip_region = NULL;
-
-    status = _create_dc_and_bitmap (surface, original_dc, format,
-				    width, height,
-				    &bits, &rowstride);
-    if (status)
-	goto FAIL;
-
-    surface->image = cairo_image_surface_create_for_data (bits, format,
-							  width, height, rowstride);
-    status = surface->image->status;
-    if (status)
-	goto FAIL;
-
-    surface->format = format;
-
-    surface->clip_rect.x = 0;
-    surface->clip_rect.y = 0;
-    surface->clip_rect.width = width;
-    surface->clip_rect.height = height;
-
-    surface->initial_clip_rgn = NULL;
-    surface->had_simple_clip = FALSE;
-
-    surface->extents = surface->clip_rect;
-    surface->font_subsets = NULL;
-
-    _cairo_surface_init (&surface->base,
-			 &cairo_win32_surface_backend,
-			 NULL, /* device */
-			 _cairo_content_from_format (format));
-
-    return &surface->base;
-
- FAIL:
-    if (surface->bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	DeleteObject (surface->bitmap);
-	DeleteDC (surface->dc);
-    }
-    free (surface);
-
-    return _cairo_surface_create_in_error (status);
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_create_similar_internal (void	    *abstract_src,
-					      cairo_content_t content,
-					      int	     width,
-					      int	     height,
-					      cairo_bool_t   force_dib)
-{
-    cairo_win32_surface_t *src = abstract_src;
-    cairo_format_t format = _cairo_format_from_content (content);
-    cairo_surface_t *new_surf = NULL;
-
-    /* We force a DIB always if:
-     * - we need alpha; or
-     * - the parent is a DIB; or
-     * - the parent is for printing (because we don't care about the bit depth at that point)
-     *
-     * We also might end up with a DIB even if a DDB is requested if DDB creation failed
-     * due to out of memory.
-     */
-    if (src->is_dib ||
-	(content & CAIRO_CONTENT_ALPHA) ||
-	src->base.backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
-    {
-	force_dib = TRUE;
-    }
-
-    if (!force_dib) {
-	/* try to create a ddb */
-	new_surf = cairo_win32_surface_create_with_ddb (src->dc, CAIRO_FORMAT_RGB24, width, height);
-
-	if (new_surf->status != CAIRO_STATUS_SUCCESS)
-	    new_surf = NULL;
-    }
-
-    if (new_surf == NULL) {
-	new_surf = _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
-    }
-
-    return new_surf;
-}
-
-cairo_surface_t *
-_cairo_win32_surface_create_similar (void	    *abstract_src,
-				     cairo_content_t content,
-				     int	     width,
-				     int	     height)
-{
-    return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE);
-}
-
-cairo_status_t
-_cairo_win32_surface_finish (void *abstract_surface)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    if (surface->image)
-	cairo_surface_destroy (surface->image);
-
-    /* If we created the Bitmap and DC, destroy them */
-    if (surface->bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	DeleteObject (surface->bitmap);
-	DeleteDC (surface->dc);
-    } else {
-	_cairo_win32_restore_initial_clip (surface);
-    }
-
-    if (surface->initial_clip_rgn)
-	DeleteObject (surface->initial_clip_rgn);
-
-    if (surface->font_subsets != NULL)
-	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
-				   int                     x,
-				   int                     y,
-				   int                     width,
-				   int                     height,
-				   cairo_win32_surface_t **local_out)
-{
-    cairo_win32_surface_t *local;
-    cairo_int_status_t status;
-    cairo_content_t content = _cairo_content_from_format (surface->format);
-
-    local =
-	(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
-	(surface, content, width, height, TRUE);
-    if (local == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (local->base.status)
-	return local->base.status;
-
-    status = CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Only BitBlt if the source surface supports it. */
-    if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
-	BitBlt (local->dc,
-		0, 0,
-		width, height,
-		surface->dc,
-		x, y,
-		SRCCOPY))
-    {
-	status = CAIRO_STATUS_SUCCESS;
-    }
-
-    if (status) {
-	/* If we failed here, most likely the source or dest doesn't
-	 * support BitBlt/AlphaBlend (e.g. a printer).
-	 * You can't reliably get bits from a printer DC, so just fill in
-	 * the surface as white (common case for printing).
-	 */
-
-	RECT r;
-	r.left = r.top = 0;
-	r.right = width;
-	r.bottom = height;
-	FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
-    }
-
-    *local_out = local;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_map_to_image (void                    *abstract_surface,
-				   const cairo_rectangle_int_t   *extents)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local = NULL;
-    cairo_status_t status;
-
-    if (surface->image) {
-	GdiFlush();
-	return _cairo_surface_create_for_rectangle_int (surface->image,
-							extents);
-    }
-
-    status = _cairo_win32_surface_get_subimage (abstract_surface,
-						extents->x,
-						extents->y,
-						extents->width,
-						extents->height,
-						&local);
-    if (unlikely (status))
-	return _cairo_surface_create_in_error (status);
-
-    status = cairo_surface_set_user_data (local->image,
-					  (const cairo_user_data_key_t *)surface->image,
-					  local, NULL);
-    if (unlikely (status)) {
-	cairo_surface_destroy (&local->base);
-	return _cairo_surface_create_in_error (status);
-    }
-
-    cairo_surface_set_device_offset (local->image, -extents->x, -extents->y);
-    return local->image;
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_unmap_image (void                    *abstract_surface,
-				  cairo_image_surface_t   *image)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local;
-
-    local = cairo_surface_get_user_data (&image->base,
-					 (const cairo_user_data_key_t *) surface->image);
-    if (!local)
-	return CAIRO_INT_STATUS_SUCCESS;
-
-    if (!BitBlt (surface->dc,
-		 image->base.device_transform.x0,
-		 image->base.device_transform.y0,
-		 image->width, image->height,
-		 local->dc,
-		 0, 0,
-		 SRCCOPY))
-	_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
-					   cairo_image_surface_t  **image_out,
-					   void                   **image_extra)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local;
-    cairo_status_t status;
-
-    if (surface->image) {
-	*image_out = (cairo_image_surface_t *)surface->image;
-	*image_extra = NULL;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
-						surface->extents.width,
-						surface->extents.height, &local);
-    if (status)
-	return status;
-
-    *image_out = (cairo_image_surface_t *)local->image;
-    *image_extra = local;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_win32_surface_release_source_image (void                   *abstract_surface,
-					   cairo_image_surface_t  *image,
-					   void                   *image_extra)
-{
-    cairo_win32_surface_t *local = image_extra;
-
-    if (local)
-	cairo_surface_destroy ((cairo_surface_t *)local);
-}
-
-cairo_status_t
-_cairo_win32_surface_set_clip_region (void           *abstract_surface,
-				      cairo_region_t *region)
+cairo_bool_t
+_cairo_win32_surface_get_extents (void		          *abstract_surface,
+				  cairo_rectangle_int_t   *rectangle)
 {
     cairo_win32_surface_t *surface = abstract_surface;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    if (surface->clip_region == region)
-	return CAIRO_STATUS_SUCCESS;
-
-    cairo_region_destroy (surface->clip_region);
-    surface->clip_region = cairo_region_reference (region);
-
-    /* The semantics we want is that any clip set by cairo combines
-     * is intersected with the clip on device context that the
-     * surface was created for. To implement this, we need to
-     * save the original clip when first setting a clip on surface.
-     */
-
-    /* Clear any clip set by cairo, return to the original first */
-    status = _cairo_win32_restore_initial_clip (surface);
-
-    /* Then combine any new region with it */
-    if (region) {
-	cairo_rectangle_int_t extents;
-	int num_rects;
-	RGNDATA *data;
-	size_t data_size;
-	RECT *rects;
-	int i;
-	HRGN gdi_region;
-
-	/* Create a GDI region for the cairo region */
-
-	cairo_region_get_extents (region, &extents);
-	num_rects = cairo_region_num_rectangles (region);
-	/* XXX see notes in _cairo_win32_save_initial_clip --
-	 * this code will interact badly with a HDC which had an initial
-	 * world transform -- we should probably manually transform the
-	 * region rects, because SelectClipRgn takes device units, not
-	 * logical units (unlike IntersectClipRect).
-	 */
-
-	data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
-	data = malloc (data_size);
-	if (!data)
-	    return _cairo_error(CAIRO_STATUS_NO_MEMORY);
-	rects = (RECT *)data->Buffer;
-
-	data->rdh.dwSize = sizeof (RGNDATAHEADER);
-	data->rdh.iType = RDH_RECTANGLES;
-	data->rdh.nCount = num_rects;
-	data->rdh.nRgnSize = num_rects * sizeof (RECT);
-	data->rdh.rcBound.left = extents.x;
-	data->rdh.rcBound.top = extents.y;
-	data->rdh.rcBound.right = extents.x + extents.width;
-	data->rdh.rcBound.bottom = extents.y + extents.height;
-
-	for (i = 0; i < num_rects; i++) {
-	    cairo_rectangle_int_t rect;
-
-	    cairo_region_get_rectangle (region, i, &rect);
-
-	    rects[i].left   = rect.x;
-	    rects[i].top    = rect.y;
-	    rects[i].right  = rect.x + rect.width;
-	    rects[i].bottom = rect.y + rect.height;
-	}
-
-	gdi_region = ExtCreateRegion (NULL, data_size, data);
-	free (data);
-
-	if (!gdi_region)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	/* AND the new region into our DC */
-	if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
-	    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
-
-	DeleteObject (gdi_region);
-    }
 
-    return status;
-}
-
-#if !defined(AC_SRC_OVER)
-#define AC_SRC_OVER                 0x00
-#pragma pack(1)
-typedef struct {
-    BYTE   BlendOp;
-    BYTE   BlendFlags;
-    BYTE   SourceConstantAlpha;
-    BYTE   AlphaFormat;
-}BLENDFUNCTION;
-#pragma pack()
-#endif
-
-/* for compatibility with VC++ 6 */
-#ifndef AC_SRC_ALPHA
-#define AC_SRC_ALPHA                0x01
-#endif
-
-typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest,
-						 int nXOriginDest,
-						 int nYOriginDest,
-						 int nWidthDest,
-						 int hHeightDest,
-						 HDC hdcSrc,
-						 int nXOriginSrc,
-						 int nYOriginSrc,
-						 int nWidthSrc,
-						 int nHeightSrc,
-						 BLENDFUNCTION blendFunction);
-
-static cairo_int_status_t
-_composite_alpha_blend (cairo_win32_surface_t *dst,
-			cairo_win32_surface_t *src,
-			int                    alpha,
-			int                    src_x,
-			int                    src_y,
-			int                    src_w,
-			int                    src_h,
-			int                    dst_x,
-			int                    dst_y,
-			int                    dst_w,
-			int                    dst_h)
-{
-    static unsigned alpha_blend_checked = FALSE;
-    static cairo_alpha_blend_func_t alpha_blend = NULL;
-
-    BLENDFUNCTION blend_function;
-
-    /* Check for AlphaBlend dynamically to allow compiling on
-     * MSVC 6 and use on older windows versions
-     */
-    if (!alpha_blend_checked) {
-	OSVERSIONINFO os;
-
-	os.dwOSVersionInfoSize = sizeof (os);
-	GetVersionEx (&os);
-
-	/* If running on Win98, disable using AlphaBlend()
-	 * to avoid Win98 AlphaBlend() bug */
-	if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
-	    os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
-	{
-	    HMODULE msimg32_dll = LoadLibraryW (L"msimg32");
-
-	    if (msimg32_dll != NULL)
-		alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,
-									"AlphaBlend");
-	}
-
-	alpha_blend_checked = TRUE;
-    }
-
-    if (alpha_blend == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    blend_function.BlendOp = AC_SRC_OVER;
-    blend_function.BlendFlags = 0;
-    blend_function.SourceConstantAlpha = alpha;
-    blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
-
-    if (!alpha_blend (dst->dc,
-		      dst_x, dst_y,
-		      dst_w, dst_h,
-		      src->dc,
-		      src_x, src_y,
-		      src_w, src_h,
-		      blend_function))
-	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
-				      cairo_image_surface_t *src_image,
-				      cairo_win32_surface_t *dst,
-				      cairo_rectangle_int_t src_extents,
-				      cairo_rectangle_int_t src_r,
-				      cairo_rectangle_int_t dst_r,
-				      int alpha,
-				      cairo_bool_t needs_alpha,
-				      cairo_bool_t needs_scale)
-{
-    /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
-    if (src_image) {
-	if (needs_alpha || needs_scale)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
-	    BITMAPINFO bi;
-	    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-	    bi.bmiHeader.biWidth = src_image->width;
-	    bi.bmiHeader.biHeight = - src_image->height;
-	    bi.bmiHeader.biSizeImage = 0;
-	    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
-	    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
-	    bi.bmiHeader.biPlanes = 1;
-	    bi.bmiHeader.biBitCount = 32;
-	    bi.bmiHeader.biCompression = BI_RGB;
-	    bi.bmiHeader.biClrUsed = 0;
-	    bi.bmiHeader.biClrImportant = 0;
-
-	    /* StretchDIBits is broken with top-down dibs; you need to do some
-	     * special munging to make the coordinate space work (basically,
-	     * need to address everything based on the bottom left, instead of top left,
-	     * and need to tell it to flip the resulting image.
-	     *
-	     * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
-	     */
-	    if (!StretchDIBits (dst->dc,
-				/* dst x,y,w,h */
-				dst_r.x, dst_r.y + dst_r.height - 1,
-				dst_r.width, - (int) dst_r.height,
-				/* src x,y,w,h */
-				src_r.x, src_extents.height - src_r.y + 1,
-				src_r.width, - (int) src_r.height,
-				src_image->data,
-				&bi,
-				DIB_RGB_COLORS,
-				SRCCOPY))
-		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
-	}
-    } else if (!needs_alpha) {
-	/* BitBlt or StretchBlt? */
-	if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
-	    if (!BitBlt (dst->dc,
-			 dst_r.x, dst_r.y,
-			 dst_r.width, dst_r.height,
-			 src->dc,
-			 src_r.x, src_r.y,
-			 SRCCOPY))
-		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
-	} else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
-	    /* StretchBlt? */
-	    /* XXX check if we want HALFTONE, based on the src filter */
-	    BOOL success;
-	    int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
-	    success = StretchBlt(dst->dc,
-				 dst_r.x, dst_r.y,
-				 dst_r.width, dst_r.height,
-				 src->dc,
-				 src_r.x, src_r.y,
-				 src_r.width, src_r.height,
-				 SRCCOPY);
-	    SetStretchBltMode(dst->dc, oldmode);
-
-	    if (!success)
-		return _cairo_win32_print_gdi_error ("StretchBlt");
-	}
-    } else if (needs_alpha && !needs_scale) {
-  	return _composite_alpha_blend (dst, src, alpha,
-				       src_r.x, src_r.y, src_r.width, src_r.height,
-				       dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
+    *rectangle = surface->extents;
+    return TRUE;
 }
 
-/* from pixman-private.h */
-#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
-
-static cairo_int_status_t
-_cairo_win32_surface_composite (cairo_operator_t	op,
-				const cairo_pattern_t	*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,
-				cairo_region_t	       *clip_region)
+/**
+ * cairo_win32_surface_get_dc
+ * @surface: a #cairo_surface_t
+ *
+ * Returns the HDC associated with this surface, or %NULL if none.
+ * Also returns %NULL if the surface is not a win32 surface.
+ *
+ * A call to cairo_surface_flush() is required before using the HDC to
+ * ensure that all pending drawing operations are finished and to
+ * restore any temporary modification cairo has made to its state. A
+ * call to cairo_surface_mark_dirty() is required after the state or
+ * the content of the HDC has been modified.
+ *
+ * Return value: HDC or %NULL if no HDC available.
+ *
+ * Since: 1.2
+ **/
+HDC
+cairo_win32_surface_get_dc (cairo_surface_t *surface)
 {
-    cairo_win32_surface_t *dst = abstract_dst;
-    cairo_win32_surface_t *src;
-    cairo_surface_pattern_t *src_surface_pattern;
-    int alpha;
-    double scalex, scaley;
-    cairo_fixed_t x0_fixed, y0_fixed;
-    cairo_int_status_t status;
-
-    cairo_bool_t needs_alpha, needs_scale, needs_repeat;
-    cairo_image_surface_t *src_image = NULL;
-
-    cairo_format_t src_format;
-    cairo_rectangle_int_t src_extents;
-
-    cairo_rectangle_int_t src_r = { src_x, src_y, width, height };
-    cairo_rectangle_int_t dst_r = { dst_x, dst_y, width, height };
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "+++ composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
-	     op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
-#endif
-
-    /* If the destination can't do any of these, then
-     * we may as well give up, since this is what we'll
-     * look to for optimization.
-     */
-    if ((dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT |
-		       CAIRO_WIN32_SURFACE_CAN_ALPHABLEND |
-		       CAIRO_WIN32_SURFACE_CAN_STRETCHBLT |
-		       CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
-	== 0)
-    {
-	goto UNSUPPORTED;
-    }
-
-    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
-	goto UNSUPPORTED;
-
-    if (pattern->extend != CAIRO_EXTEND_NONE &&
-	pattern->extend != CAIRO_EXTEND_REPEAT)
-	goto UNSUPPORTED;
-
-    if (mask_pattern) {
-	/* FIXME: When we fully support RENDER style 4-channel
-	 * masks we need to check r/g/b != 1.0.
-	 */
-	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
-    } else {
-	alpha = 255;
-    }
-
-    src_surface_pattern = (cairo_surface_pattern_t *)pattern;
-    src = (cairo_win32_surface_t *)src_surface_pattern->surface;
-
-    if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE &&
-	dst->flags & (CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
-    {
-	/* In some very limited cases, we can use StretchDIBits to draw
-	 * an image surface directly:
-	 *  - source is CAIRO_FORMAT_ARGB32
-	 *  - dest is CAIRO_FORMAT_ARGB32
-	 *  - alpha is 255
-	 *  - operator is SOURCE or OVER
-	 *  - image stride is 4*width
-	 */
-	src_image = (cairo_image_surface_t*) src;
-
-	if (src_image->format != CAIRO_FORMAT_RGB24 ||
-	    dst->format != CAIRO_FORMAT_RGB24 ||
-	    alpha != 255 ||
-	    (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
-	    src_image->stride != (src_image->width * 4))
-	{
-	    goto UNSUPPORTED;
-	}
-
-	src_format = src_image->format;
-	src_extents.x = 0;
-	src_extents.y = 0;
-	src_extents.width = src_image->width;
-	src_extents.height = src_image->height;
-    } else if (src->base.backend != dst->base.backend) {
-	goto UNSUPPORTED;
-    } else {
-	src_format = src->format;
-	src_extents = src->extents;
-    }
-
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "Before check: src size: (%d %d) xy [%d %d] -> dst [%d %d %d %d] {srcmat %f %f %f %f}\n",
-	     src_extents.width, src_extents.height,
-	     src_x, src_y,
-	     dst_x, dst_y, width, height,
-	     pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy);
-#endif
-
-    /* We can only use GDI functions if the source and destination rectangles
-     * are on integer pixel boundaries.  Figure that out here.
-     */
-    x0_fixed = _cairo_fixed_from_double(pattern->matrix.x0 / pattern->matrix.xx);
-    y0_fixed = _cairo_fixed_from_double(pattern->matrix.y0 / pattern->matrix.yy);
-
-    if (pattern->matrix.yx != 0.0 ||
-	pattern->matrix.xy != 0.0 ||
-	!_cairo_fixed_is_integer(x0_fixed) ||
-	!_cairo_fixed_is_integer(y0_fixed))
-    {
-	goto UNSUPPORTED;
-    }
-
-    scalex = pattern->matrix.xx;
-    scaley = pattern->matrix.yy;
-
-    src_r.x += _cairo_fixed_integer_part(x0_fixed);
-    src_r.y += _cairo_fixed_integer_part(y0_fixed);
-
-    /* Success, right? */
-    if (scalex == 0.0 || scaley == 0.0)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (scalex != 1.0 || scaley != 1.0)
-	goto UNSUPPORTED;
-
-    /* If the src coordinates are outside of the source surface bounds,
-     * we have to fix them up, because this is an error for the GDI
-     * functions.
-     */
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "before: [%d %d %d %d] -> [%d %d %d %d]\n",
-	     src_r.x, src_r.y, src_r.width, src_r.height,
-	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    fflush (stderr);
-#endif
-
-    /* If the src rectangle doesn't wholly lie within the src extents,
-     * fudge things.  We really need to do fixup on the unpainted
-     * region -- e.g. the SOURCE operator is broken for areas outside
-     * of the extents, because it won't clear that area to transparent
-     * black.
-     */
-
-    if (pattern->extend != CAIRO_EXTEND_REPEAT) {
-	needs_repeat = FALSE;
-
-	/* If the src rect and the extents of the source image don't overlap at all,
-	 * we can't do anything useful here.
-	 */
-	if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
-	    (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
-	{
-	    if (op == CAIRO_OPERATOR_OVER)
-		return CAIRO_STATUS_SUCCESS;
-	    goto UNSUPPORTED;
-	}
-
-	if (src_r.x < 0) {
-	    src_r.width += src_r.x;
-	    src_r.x = 0;
-
-	    dst_r.width += src_r.x;
-	    dst_r.x -= src_r.x;
-	}
-
-	if (src_r.y < 0) {
-	    src_r.height += src_r.y;
-	    src_r.y = 0;
-
-	    dst_r.height += dst_r.y;
-	    dst_r.y -= src_r.y;
-	}
-
-	if (src_r.x + src_r.width > src_extents.width) {
-	    src_r.width = src_extents.width - src_r.x;
-	    dst_r.width = src_r.width;
-	}
-
-	if (src_r.y + src_r.height > src_extents.height) {
-	    src_r.height = src_extents.height - src_r.y;
-	    dst_r.height = src_r.height;
-	}
-    } else {
-	needs_repeat = TRUE;
-    }
-
-    /*
-     * Operations that we can do:
-     *
-     *  RGB OVER  RGB -> BitBlt (same as SOURCE)
-     *  RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
-     * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
-     * ARGB OVER  RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
-     * 
-     *  RGB OVER  RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
-     *  RGB OVER ARGB + mask -> UNSUPPORTED
-     * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
-     * ARGB OVER  RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
-     * 
-     *  RGB SOURCE  RGB -> BitBlt
-     *  RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
-     * ARGB SOURCE ARGB -> BitBlt
-     * ARGB SOURCE  RGB -> BitBlt
-     * 
-     *  RGB SOURCE  RGB + mask -> unsupported
-     *  RGB SOURCE ARGB + mask -> unsupported
-     * ARGB SOURCE ARGB + mask -> unsupported
-     * ARGB SOURCE  RGB + mask -> unsupported
-     */
-
-    /*
-     * Figure out what action to take.
-     */
-    if (op == CAIRO_OPERATOR_OVER) {
-	if (alpha == 0)
-	    return CAIRO_STATUS_SUCCESS;
+    if (surface->backend->type == CAIRO_SURFACE_TYPE_WIN32)
+	return to_win32_surface(surface)->dc;
 
-	if (src_format == dst->format) {
-	    if (alpha == 255 && src_format == CAIRO_FORMAT_RGB24) {
-		needs_alpha = FALSE;
-	    } else {
-		needs_alpha = TRUE;
-	    }
-	} else if (src_format == CAIRO_FORMAT_ARGB32 &&
-		   dst->format == CAIRO_FORMAT_RGB24)
-	{
-	    needs_alpha = TRUE;
-	} else {
-	    goto UNSUPPORTED;
-	}
-    } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
-	if ((src_format == dst->format) ||
-	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
-	{
-	    needs_alpha = FALSE;
-	} else {
-	    goto UNSUPPORTED;
-	}
-    } else {
-	goto UNSUPPORTED;
-    }
-
-    if (scalex == 1.0 && scaley == 1.0) {
-	needs_scale = FALSE;
-    } else {
-	/* Should never be reached until we turn StretchBlt back on */
-	needs_scale = TRUE;
-    }
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
-	     src_r.x, src_r.y, src_r.width, src_r.height,
-	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    fflush (stderr);
-#endif
-
-    status = _cairo_win32_surface_set_clip_region (dst, clip_region);
-    if (status)
-	return status;
-
-    /* If we need to repeat, we turn the repeated blit into
-     * a bunch of piece-by-piece blits.
-     */
-    if (needs_repeat) {
-	cairo_rectangle_int_t piece_src_r, piece_dst_r;
-	uint32_t rendered_width = 0, rendered_height = 0;
-	uint32_t to_render_height, to_render_width;
-	int32_t piece_x, piece_y;
-	int32_t src_start_x = MOD(src_r.x, src_extents.width);
-	int32_t src_start_y = MOD(src_r.y, src_extents.height);
-
-	if (needs_scale)
-	    goto UNSUPPORTED;
-
-	/* If both the src and dest have an image, we may as well fall
-	 * back, because it will be faster than our separate blits.
-	 * Our blit code will be fastest when the src is a DDB and the
-	 * destination is a DDB.
-	 */
-	if ((src_image || src->image) && dst->image)
-	    goto UNSUPPORTED;
-
-	/* If the src is not a bitmap but an on-screen (or unknown)
-	 * DC, chances are that fallback will be faster.
-	 */
-	if (src->bitmap == NULL)
-	    goto UNSUPPORTED;
-
-	/* If we can use PatBlt, just do so */
-	if (!src_image && !needs_alpha)
-	{
-	    HBRUSH brush;
-	    HGDIOBJ old_brush;
-	    POINT old_brush_origin;
-
-	    /* Set up the brush with our bitmap */
-	    brush = CreatePatternBrush (src->bitmap);
-
-	    /* SetBrushOrgEx sets the coordinates in the destination DC of where the
-	     * pattern should start.
-	     */
-	    SetBrushOrgEx (dst->dc, dst_r.x - src_start_x,
-			   dst_r.y - src_start_y, &old_brush_origin);
-
-	    old_brush = SelectObject (dst->dc, brush);
-
-	    PatBlt (dst->dc, dst_r.x, dst_r.y, dst_r.width, dst_r.height, PATCOPY);
-
-	    /* Restore the old brush and pen */
-	    SetBrushOrgEx (dst->dc, old_brush_origin.x, old_brush_origin.y, NULL);
-	    SelectObject (dst->dc, old_brush);
-	    DeleteObject (brush);
-
-	    return CAIRO_STATUS_SUCCESS;
-	}
-
-	/* If we were not able to use PatBlt, then manually expand out the blit */
-
-	/* Arbitrary factor; we think that going through
-	 * fallback will be faster if we have to do more
-	 * than this amount of blits in either direction.
-	 */
-	if (dst_r.width / src_extents.width > 5 ||
-	    dst_r.height / src_extents.height > 5)
-	    goto UNSUPPORTED;
-
-	for (rendered_height = 0;
-	     rendered_height < dst_r.height;
-	     rendered_height += to_render_height)
-	{
-	    piece_y = (src_start_y + rendered_height) % src_extents.height;
-	    to_render_height = src_extents.height - piece_y;
-
-	    if (rendered_height + to_render_height > dst_r.height)
-		to_render_height = dst_r.height - rendered_height;
-
-	    for (rendered_width = 0;
-		 rendered_width < dst_r.width;
-		 rendered_width += to_render_width)
-	    {
-		piece_x = (src_start_x + rendered_width) % src_extents.width;
-		to_render_width = src_extents.width - piece_x;
-
-		if (rendered_width + to_render_width > dst_r.width)
-		    to_render_width = dst_r.width - rendered_width;
-
-		piece_src_r.x = piece_x;
-		piece_src_r.y = piece_y;
-		piece_src_r.width = to_render_width;
-		piece_src_r.height = to_render_height;
-
-		piece_dst_r.x = dst_r.x + rendered_width;
-		piece_dst_r.y = dst_r.y + rendered_height;
-		piece_dst_r.width = to_render_width;
-		piece_dst_r.height = to_render_height;
-
-		status = _cairo_win32_surface_composite_inner (src, src_image, dst,
-							       src_extents, piece_src_r, piece_dst_r,
-							       alpha, needs_alpha, needs_scale);
-		if (status != CAIRO_STATUS_SUCCESS) {
-		    /* Uh oh.  If something failed, and it's the first
-		     * piece, then we can jump to UNSUPPORTED. 
-		     * Otherwise, this is bad times, because part of the
-		     * rendering was already done. */
-		    if (rendered_width == 0 &&
-			rendered_height == 0)
-		    {
-			goto UNSUPPORTED;
-		    }
-
-		    return status;
-		}
-	    }
-	}
-    } else {
-	status = _cairo_win32_surface_composite_inner (src, src_image, dst,
-						       src_extents, src_r, dst_r,
-						       alpha, needs_alpha, needs_scale);
-    }
-
-    if (status == CAIRO_STATUS_SUCCESS)
-	return status;
-
-UNSUPPORTED:
-    /* Fall back to image surface directly, if this is a DIB surface */
-    if (dst->image) {
-	GdiFlush();
-
-#if 0
-	return dst->image->backend->composite (op, pattern, mask_pattern,
-					       dst->image,
-					       src_x, src_y,
-					       mask_x, mask_y,
-					       dst_x, dst_y,
-					       width, height,
-					       clip_region);
-#endif
+    if (_cairo_surface_is_paginated (surface)) {
+	cairo_surface_t *target = _cairo_paginated_surface_get_target (surface);
+	if (target->backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
+	    return to_win32_surface(target)->dc;
     }
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    return NULL;
 }
 
-/* This big function tells us how to optimize operators for the
- * case of solid destination and constant-alpha source
+/**
+ * cairo_win32_surface_get_image
+ * @surface: a #cairo_surface_t
  *
- * Note: This function needs revisiting if we add support for
- *       super-luminescent colors (a == 0, r,g,b > 0)
+ * Returns a #cairo_surface_t image surface that refers to the same bits
+ * as the DIB of the Win32 surface.  If the passed-in win32 surface
+ * is not a DIB surface, %NULL is returned.
+ *
+ * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t),
+ * or %NULL if the win32 surface is not a DIB.
+ *
+ * Since: 1.4
  */
-static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED }
-categorize_solid_dest_operator (cairo_operator_t op,
-				unsigned short   alpha)
-{
-    enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source;
-
-    if (alpha >= 0xff00)
-	source = SOURCE_SOLID;
-    else if (alpha < 0x100)
-	source = SOURCE_TRANSPARENT;
-    else
-	source = SOURCE_OTHER;
-
-    switch (op) {
-    case CAIRO_OPERATOR_CLEAR:    /* 0                 0 */
-    case CAIRO_OPERATOR_OUT:      /* 1 - Ab            0 */
-	return DO_CLEAR;
-	break;
-
-    case CAIRO_OPERATOR_SOURCE:   /* 1                 0 */
-    case CAIRO_OPERATOR_IN:       /* Ab                0 */
-	return DO_SOURCE;
-	break;
-
-    case CAIRO_OPERATOR_OVER:     /* 1            1 - Aa */
-    case CAIRO_OPERATOR_ATOP:     /* Ab           1 - Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_SOURCE;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_DEST_OUT: /* 0            1 - Aa */
-    case CAIRO_OPERATOR_XOR:      /* 1 - Ab       1 - Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_CLEAR;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-    	break;
-
-    case CAIRO_OPERATOR_DEST:     /* 0                 1 */
-    case CAIRO_OPERATOR_DEST_OVER:/* 1 - Ab            1 */
-    case CAIRO_OPERATOR_SATURATE: /* min(1,(1-Ab)/Aa)  1 */
-	return DO_NOTHING;
-	break;
-
-    case CAIRO_OPERATOR_DEST_IN:  /* 0                Aa */
-    case CAIRO_OPERATOR_DEST_ATOP:/* 1 - Ab           Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_NOTHING;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_CLEAR;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_ADD:	  /* 1                1 */
-	if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_MULTIPLY:
-    case CAIRO_OPERATOR_SCREEN:
-    case CAIRO_OPERATOR_OVERLAY:
-    case CAIRO_OPERATOR_DARKEN:
-    case CAIRO_OPERATOR_LIGHTEN:
-    case CAIRO_OPERATOR_COLOR_DODGE:
-    case CAIRO_OPERATOR_COLOR_BURN:
-    case CAIRO_OPERATOR_HARD_LIGHT:
-    case CAIRO_OPERATOR_SOFT_LIGHT:
-    case CAIRO_OPERATOR_DIFFERENCE:
-    case CAIRO_OPERATOR_EXCLUSION:
-    case CAIRO_OPERATOR_HSL_HUE:
-    case CAIRO_OPERATOR_HSL_SATURATION:
-    case CAIRO_OPERATOR_HSL_COLOR:
-    case CAIRO_OPERATOR_HSL_LUMINOSITY:
-	return DO_UNSUPPORTED;
-
-    default:
-	ASSERT_NOT_REACHED;
-	return DO_UNSUPPORTED;
-    }
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_fill_rectangles (void			*abstract_surface,
-				      cairo_operator_t		op,
-				      const cairo_color_t	*color,
-				      cairo_rectangle_int_t	*rects,
-				      int			num_rects)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_status_t status;
-    COLORREF new_color;
-    HBRUSH new_brush;
-    int i;
-
-    /* XXXperf If it's not RGB24, we need to do a little more checking
-     * to figure out when we can use GDI.  We don't have that checking
-     * anywhere at the moment, so just bail and use the fallback
-     * paths. */
-    if (surface->format != CAIRO_FORMAT_RGB24)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_win32_surface_set_clip_region (surface, NULL);
-    if (status)
-	return status;
-
-    /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
-     * surfaces with alpha.)
-     */
-    switch (categorize_solid_dest_operator (op, color->alpha_short)) {
-    case DO_CLEAR:
-	new_color = RGB (0, 0, 0);
-	break;
-    case DO_SOURCE:
-	new_color = RGB (color->red_short >> 8, color->green_short >> 8, color->blue_short >> 8);
-	break;
-    case DO_NOTHING:
-	return CAIRO_STATUS_SUCCESS;
-    case DO_UNSUPPORTED:
-    default:
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    new_brush = CreateSolidBrush (new_color);
-    if (!new_brush)
-	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
-
-    for (i = 0; i < num_rects; i++) {
-	RECT rect;
-
-	rect.left = rects[i].x;
-	rect.top = rects[i].y;
-	rect.right = rects[i].x + rects[i].width;
-	rect.bottom = rects[i].y + rects[i].height;
-
-	if (!FillRect (surface->dc, &rect, new_brush))
-	    goto FAIL;
-    }
-
-    DeleteObject (new_brush);
-
-    return CAIRO_STATUS_SUCCESS;
-
- FAIL:
-    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
-
-    DeleteObject (new_brush);
-
-    return status;
-}
-
-cairo_bool_t
-_cairo_win32_surface_get_extents (void		          *abstract_surface,
-				  cairo_rectangle_int_t   *rectangle)
+cairo_surface_t *
+cairo_win32_surface_get_image (cairo_surface_t *surface)
 {
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    *rectangle = surface->extents;
-    return TRUE;
-}
+    if (surface->backend->type != CAIRO_SURFACE_TYPE_WIN32)
+	return NULL;
 
-static cairo_status_t
-_cairo_win32_surface_flush (void *abstract_surface)
-{
-    return _cairo_win32_surface_set_clip_region (abstract_surface, NULL);
+    GdiFlush();
+    return to_win32_display_surface(surface)->image;
 }
 
 #define STACK_GLYPH_SIZE 256
-
 cairo_int_status_t
-_cairo_win32_surface_show_glyphs_internal (void			 *surface,
-					   cairo_operator_t	  op,
-					   const cairo_pattern_t *source,
-					   cairo_glyph_t	 *glyphs,
-					   int			  num_glyphs,
-					   cairo_scaled_font_t	 *scaled_font,
-					   const cairo_clip_t	 *clip,
-					   cairo_bool_t		  glyph_indexing)
+_cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
+				  const cairo_pattern_t *source,
+				  cairo_glyph_t	 *glyphs,
+				  int			  num_glyphs,
+				  cairo_scaled_font_t	 *scaled_font,
+				  cairo_bool_t		  glyph_indexing)
 {
 #if CAIRO_HAS_WIN32_FONT
-    cairo_win32_surface_t *dst = surface;
-
     WORD glyph_buf_stack[STACK_GLYPH_SIZE];
     WORD *glyph_buf = glyph_buf_stack;
     int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
@@ -1551,31 +221,11 @@ _cairo_win32_surface_show_glyphs_internal (void			 *surface,
     unsigned int glyph_index_option;
 
     /* We can only handle win32 fonts */
-    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* We can only handle opaque solid color sources */
-    if (!_cairo_pattern_is_opaque_solid(source))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    assert (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32);
 
-    /* We can only handle operator SOURCE or OVER with the destination
-     * having no alpha */
-    if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
-	(dst->format != CAIRO_FORMAT_RGB24))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* If we have a fallback mask clip set on the dst, we have
-     * to go through the fallback path, but only if we're not
-     * doing this for printing */
-    if (clip != NULL) {
-	if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) {
-	    if (! _cairo_clip_is_region (clip))
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	    _cairo_win32_surface_set_clip_region (surface,
-						  _cairo_clip_get_region (clip));
-	}
-    }
+    /* We can only handle opaque solid color sources and destinations */
+    assert (_cairo_pattern_is_opaque_solid(source));
+    assert (dst->format == CAIRO_FORMAT_RGB24);
 
     solid_pattern = (cairo_solid_pattern_t *)source;
     color = RGB(((int)solid_pattern->color.red_short) >> 8,
@@ -1666,422 +316,4 @@ _cairo_win32_surface_show_glyphs_internal (void			 *surface,
     return CAIRO_INT_STATUS_UNSUPPORTED;
 #endif
 }
-
 #undef STACK_GLYPH_SIZE
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs (void			*surface,
-				  cairo_operator_t	 op,
-				  const cairo_pattern_t *source,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font,
-				  const cairo_clip_t    *clip)
-{
-    return _cairo_win32_surface_show_glyphs_internal (surface,
-						      op,
-						      source,
-						      glyphs,
-						      num_glyphs,
-						      scaled_font,
-						      clip,
-						      TRUE);
-}
-
-
-/**
- * cairo_win32_surface_create:
- * @hdc: the DC to create a surface for
- *
- * Creates a cairo surface that targets the given DC.  The DC will be
- * queried for its initial clip extents, and this will be used as the
- * size of the cairo surface.  The resulting surface will always be of
- * format %CAIRO_FORMAT_RGB24; should you need another surface format,
- * you will need to create one through
- * cairo_win32_surface_create_with_dib().
- *
- * Return value: the newly created surface
- **/
-cairo_surface_t *
-cairo_win32_surface_create (HDC hdc)
-{
-    cairo_win32_surface_t *surface;
-
-    cairo_format_t format;
-    RECT rect;
-
-    /* Assume that everything coming in as a HDC is RGB24 */
-    format = CAIRO_FORMAT_RGB24;
-
-    surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
-	free (surface);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    surface->clip_region = NULL;
-    surface->image = NULL;
-    surface->format = format;
-
-    surface->dc = hdc;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-    surface->saved_dc_bitmap = NULL;
-    surface->brush = NULL;
-    surface->old_brush = NULL;
-    surface->font_subsets = NULL;
-
-    GetClipBox(hdc, &rect);
-    surface->extents.x = rect.left;
-    surface->extents.y = rect.top;
-    surface->extents.width = rect.right - rect.left;
-    surface->extents.height = rect.bottom - rect.top;
-
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-
-    _cairo_surface_init (&surface->base,
-			 &cairo_win32_surface_backend,
-			 NULL, /* device */
-			 _cairo_content_from_format (format));
-
-    return &surface->base;
-}
-
-/**
- * cairo_win32_surface_create_with_dib:
- * @format: format of pixels in the surface to create
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
- *
- * Creates a device-independent-bitmap surface not associated with
- * any particular existing surface or device context. The created
- * bitmap will be uninitialized.
- *
- * Return value: the newly created surface
- *
- * Since: 1.2
- **/
-cairo_surface_t *
-cairo_win32_surface_create_with_dib (cairo_format_t format,
-				     int	    width,
-				     int	    height)
-{
-    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
-}
-
-/**
- * cairo_win32_surface_create_with_ddb:
- * @hdc: a DC compatible with the surface to create
- * @format: format of pixels in the surface to create
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
- *
- * Creates a device-dependent-bitmap surface not associated with
- * any particular existing surface or device context. The created
- * bitmap will be uninitialized.
- *
- * Return value: the newly created surface
- *
- * Since: 1.4
- **/
-cairo_surface_t *
-cairo_win32_surface_create_with_ddb (HDC hdc,
-				     cairo_format_t format,
-				     int width,
-				     int height)
-{
-    cairo_win32_surface_t *new_surf;
-    HBITMAP ddb;
-    HDC screen_dc, ddb_dc;
-    HBITMAP saved_dc_bitmap;
-
-    if (format != CAIRO_FORMAT_RGB24)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-/* XXX handle these eventually
-	format != CAIRO_FORMAT_A8 ||
-	format != CAIRO_FORMAT_A1)
-*/
-
-    if (!hdc) {
-	screen_dc = GetDC (NULL);
-	hdc = screen_dc;
-    } else {
-	screen_dc = NULL;
-    }
-
-    ddb_dc = CreateCompatibleDC (hdc);
-    if (ddb_dc == NULL) {
-	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-	goto FINISH;
-    }
-
-    ddb = CreateCompatibleBitmap (hdc, width, height);
-    if (ddb == NULL) {
-	DeleteDC (ddb_dc);
-
-	/* Note that if an app actually does hit this out of memory
-	 * condition, it's going to have lots of other issues, as
-	 * video memory is probably exhausted.  However, it can often
-	 * continue using DIBs instead of DDBs.
-	 */
-	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-	goto FINISH;
-    }
-
-    saved_dc_bitmap = SelectObject (ddb_dc, ddb);
-
-    new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
-    new_surf->bitmap = ddb;
-    new_surf->saved_dc_bitmap = saved_dc_bitmap;
-    new_surf->is_dib = FALSE;
-
-FINISH:
-    if (screen_dc)
-	ReleaseDC (NULL, screen_dc);
-
-    return (cairo_surface_t*) new_surf;
-}
-
-/**
- * _cairo_surface_is_win32:
- * @surface: a #cairo_surface_t
- *
- * Checks if a surface is a win32 surface.  This will
- * return False if this is a win32 printing surface; use
- * _cairo_surface_is_win32_printing() to check for that.
- *
- * Return value: True if the surface is an win32 surface
- **/
-int
-_cairo_surface_is_win32 (cairo_surface_t *surface)
-{
-    return surface->backend == &cairo_win32_surface_backend;
-}
-
-/**
- * cairo_win32_surface_get_dc
- * @surface: a #cairo_surface_t
- *
- * Returns the HDC associated with this surface, or %NULL if none.
- * Also returns %NULL if the surface is not a win32 surface.
- *
- * A call to cairo_surface_flush() is required before using the HDC to
- * ensure that all pending drawing operations are finished and to
- * restore any temporary modification cairo has made to its state. A
- * call to cairo_surface_mark_dirty() is required after the state or
- * the content of the HDC has been modified.
- *
- * Return value: HDC or %NULL if no HDC available.
- *
- * Since: 1.2
- **/
-HDC
-cairo_win32_surface_get_dc (cairo_surface_t *surface)
-{
-    if (_cairo_surface_is_win32 (surface))
-	return ((cairo_win32_surface_t *) target)->dc;
-
-    if (_cairo_surface_is_paginated (surface)) {
-	cairo_surface_t *target = _cairo_paginated_surface_get_target (surface);
-	if (_cairo_surface_is_win32_printing (target))
-	    return ((cairo_win32_surface_t *) target)->dc;
-    }
-
-    return NULL;
-}
-
-/**
- * cairo_win32_surface_get_image
- * @surface: a #cairo_surface_t
- *
- * Returns a #cairo_surface_t image surface that refers to the same bits
- * as the DIB of the Win32 surface.  If the passed-in win32 surface
- * is not a DIB surface, %NULL is returned.
- *
- * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t),
- * or %NULL if the win32 surface is not a DIB.
- *
- * Since: 1.4
- */
-cairo_surface_t *
-cairo_win32_surface_get_image (cairo_surface_t *surface)
-{
-    if (!_cairo_surface_is_win32(surface))
-	return NULL;
-
-    return ((cairo_win32_surface_t*)surface)->image;
-}
-
-static const cairo_surface_backend_t cairo_win32_surface_backend = {
-    CAIRO_SURFACE_TYPE_WIN32,
-    _cairo_win32_surface_finish,
-
-    _cairo_default_context_create,
-
-    _cairo_win32_surface_create_similar,
-    NULL,
-    _cairo_win32_surface_map_to_image,
-    _cairo_win32_surface_unmap_image,
-
-    _cairo_surface_default_source,
-    _cairo_win32_surface_acquire_source_image,
-    _cairo_win32_surface_release_source_image,
-    NULL,  /* snapshot */
-
-    NULL, /* copy_page */
-    NULL, /* show_page */
-
-    _cairo_win32_surface_get_extents,
-    NULL, /* get_font_options */
-
-    _cairo_win32_surface_flush,
-    NULL, /* mark_dirty_rectangle */
-
-    NULL, /* paint */
-    NULL, /* mask */
-    NULL, /* stroke */
-    NULL, /* fill */
-    NULL, /* fill/stroke */
-    _cairo_win32_surface_show_glyphs,
-};
-
-/* Notes:
- *
- * Win32 alpha-understanding functions
- *
- * BitBlt - will copy full 32 bits from a 32bpp DIB to result
- *          (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
- *          (but not safe going RGB24->ARGB32, if RGB24 is also represented
- *           as a 32bpp DIB, since the alpha isn't discarded!)
- *
- * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
- *              it will still copy over the src alpha, because the SCA value (255) will be
- *              multiplied by all the src components.
- */
-
-
-cairo_int_status_t
-_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
-{
-    RECT rect;
-    int clipBoxType;
-    int gm;
-    XFORM saved_xform;
-
-    /* GetClipBox/GetClipRgn and friends interact badly with a world transform
-     * set.  GetClipBox returns values in logical (transformed) coordinates;
-     * it's unclear what GetClipRgn returns, because the region is empty in the
-     * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates.
-     * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn
-     * works in device units.
-     *
-     * So, avoid the whole mess and get rid of the world transform
-     * while we store our initial data and when we restore initial coordinates.
-     *
-     * XXX we may need to modify x/y by the ViewportOrg or WindowOrg
-     * here in GM_COMPATIBLE; unclear.
-     */
-    gm = GetGraphicsMode (hdc);
-    if (gm == GM_ADVANCED) {
-	GetWorldTransform (hdc, &saved_xform);
-	ModifyWorldTransform (hdc, NULL, MWT_IDENTITY);
-    }
-
-    clipBoxType = GetClipBox (hdc, &rect);
-    if (clipBoxType == ERROR) {
-	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
-	SetGraphicsMode (hdc, gm);
-	/* XXX: Can we make a more reasonable guess at the error cause here? */
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    surface->clip_rect.x = rect.left;
-    surface->clip_rect.y = rect.top;
-    surface->clip_rect.width = rect.right - rect.left;
-    surface->clip_rect.height = rect.bottom - rect.top;
-
-    surface->initial_clip_rgn = NULL;
-    surface->had_simple_clip = FALSE;
-
-    if (clipBoxType == COMPLEXREGION) {
-	surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
-	if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
-	    DeleteObject(surface->initial_clip_rgn);
-	    surface->initial_clip_rgn = NULL;
-	}
-    } else if (clipBoxType == SIMPLEREGION) {
-	surface->had_simple_clip = TRUE;
-    }
-
-    if (gm == GM_ADVANCED)
-	SetWorldTransform (hdc, &saved_xform);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface)
-{
-    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
-
-    XFORM saved_xform;
-    int gm = GetGraphicsMode (surface->dc);
-    if (gm == GM_ADVANCED) {
-	GetWorldTransform (surface->dc, &saved_xform);
-	ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY);
-    }
-
-    /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */
-    SelectClipRgn (surface->dc, surface->initial_clip_rgn);
-
-    if (surface->had_simple_clip) {
-	/* then if we had a simple clip, intersect */
-	IntersectClipRect (surface->dc,
-			   surface->clip_rect.x,
-			   surface->clip_rect.y,
-			   surface->clip_rect.x + surface->clip_rect.width,
-			   surface->clip_rect.y + surface->clip_rect.height);
-    }
-
-    if (gm == GM_ADVANCED)
-	SetWorldTransform (surface->dc, &saved_xform);
-
-    return status;
-}
-
-void
-_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
-{
-    RGNDATA *rd;
-    unsigned int z;
-
-    if (header)
-	fprintf (stderr, "%s\n", header);
-
-    if (rgn == NULL) {
-	fprintf (stderr, " NULL\n");
-    }
-
-    z = GetRegionData(rgn, 0, NULL);
-    rd = (RGNDATA*) malloc(z);
-    z = GetRegionData(rgn, z, rd);
-
-    fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n",
-	     rd->rdh.nCount,
-	     rd->rdh.rcBound.left,
-	     rd->rdh.rcBound.top,
-	     rd->rdh.rcBound.right - rd->rdh.rcBound.left,
-	     rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
-
-    for (z = 0; z < rd->rdh.nCount; z++) {
-	RECT r = ((RECT*)rd->Buffer)[z];
-	fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n",
-		 z, r.left, r.top, r.right - r.left, r.bottom - r.top);
-    }
-
-    free(rd);
-    fflush (stderr);
-}
diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c
new file mode 100644
index 0000000..8785530
--- /dev/null
+++ b/src/win32/cairo-win32-system.c
@@ -0,0 +1,89 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+/* This file should include code that is system-specific, not
+ * feature-specific.  For example, the DLL initialization/finalization
+ * code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c).
+ * Same about possible ELF-specific code.
+ *
+ * And no other function should live here.
+ */
+
+
+#include "cairoint.h"
+
+#if CAIRO_MUTEX_IMPL_WIN32
+#if !CAIRO_WIN32_STATIC_BUILD
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+
+/* declare to avoid "no previous prototype for 'DllMain'" warning */
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+         DWORD     fdwReason,
+         LPVOID    lpvReserved);
+
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+         DWORD     fdwReason,
+         LPVOID    lpvReserved)
+{
+    switch (fdwReason) {
+        case DLL_PROCESS_ATTACH:
+            CAIRO_MUTEX_INITIALIZE ();
+            break;
+
+        case DLL_PROCESS_DETACH:
+            CAIRO_MUTEX_FINALIZE ();
+            break;
+    }
+
+    return TRUE;
+}
+
+#endif
+#endif
commit 92c0b37d04f9df8df53a455c8e8dda1946c84c87
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 12 10:17:12 2012 +0000

    win32: Move to separate directoy
    
    I suspect I may split the win32 code into a few more files, so move it
    to its own directory to reduce the clutter.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 6bcdd43..22a7b47 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -334,10 +334,14 @@ cairo_quartz_image_sources = cairo-quartz-image-surface.c
 cairo_quartz_font_sources = cairo-quartz-font.c
 
 cairo_win32_headers = cairo-win32.h
-cairo_win32_private = cairo-win32-private.h
-cairo_win32_sources = cairo-win32-surface.c cairo-win32-printing-surface.c
-
-cairo_win32_font_sources = cairo-win32-font.c
+cairo_win32_private = win32/cairo-win32-private.h
+cairo_win32_sources = \
+	win32/cairo-win32-surface.c \
+	win32/cairo-win32-printing-surface.c \
+	$(NULL)
+cairo_win32_font_sources = \
+	win32/cairo-win32-font.c \
+	$(NULL)
 
 cairo_skia_headers = cairo-skia.h
 cairo_skia_cxx_sources = \
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
deleted file mode 100644
index 73fc052..0000000
--- a/src/cairo-win32-font.c
+++ /dev/null
@@ -1,2437 +0,0 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- */
-
-#define WIN32_LEAN_AND_MEAN
-/* We require Windows 2000 features such as GetGlyphIndices */
-#if !defined(WINVER) || (WINVER < 0x0500)
-# define WINVER 0x0500
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-# define _WIN32_WINNT 0x0500
-#endif
-
-#include "cairoint.h"
-
-#include "cairo-win32-private.h"
-
-#include "cairo-array-private.h"
-#include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
-#include "cairo-pattern-private.h"
-#include "cairo-scaled-font-subsets-private.h"
-
-#include <wchar.h>
-
-#ifndef SPI_GETFONTSMOOTHINGTYPE
-#define SPI_GETFONTSMOOTHINGTYPE 0x200a
-#endif
-#ifndef FE_FONTSMOOTHINGCLEARTYPE
-#define FE_FONTSMOOTHINGCLEARTYPE 2
-#endif
-#ifndef CLEARTYPE_QUALITY
-#define CLEARTYPE_QUALITY 5
-#endif
-#ifndef TT_PRIM_CSPLINE
-#define TT_PRIM_CSPLINE 3
-#endif
-
-#define CMAP_TAG 0x70616d63
-
-/**
- * SECTION:cairo-win32-fonts
- * @Title: Win32 Fonts
- * @Short_Description: Font support for Microsoft Windows
- * @See_Also: #cairo_font_face_t
- *
- * The Microsoft Windows font backend is primarily used to render text on
- * Microsoft Windows systems.
- */
-
-/**
- * CAIRO_HAS_WIN32_FONT:
- *
- * Defined if the Microsoft Windows font backend is available.
- * This macro can be used to conditionally compile backend-specific code.
- */
-
-const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend;
-
-typedef struct {
-    cairo_scaled_font_t base;
-
-    LOGFONTW logfont;
-
-    BYTE quality;
-
-    /* We do drawing and metrics computation in a "logical space" which
-     * is similar to font space, except that it is scaled by a factor
-     * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication
-     * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision.
-     */
-    double logical_scale;
-
-    /* The size we should actually request the font at from Windows; differs
-     * from the logical_scale because it is quantized for orthogonal
-     * transformations
-     */
-    double logical_size;
-
-    /* Transformations from device <=> logical space
-     */
-    cairo_matrix_t logical_to_device;
-    cairo_matrix_t device_to_logical;
-
-    /* We special case combinations of 90-degree-rotations, scales and
-     * flips ... that is transformations that take the axes to the
-     * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y
-     * encode the 8 possibilities for orientation (4 rotation angles with
-     * and without a flip), and scale_x, scale_y the scale components.
-     */
-    cairo_bool_t preserve_axes;
-    cairo_bool_t swap_axes;
-    cairo_bool_t swap_x;
-    cairo_bool_t swap_y;
-    double x_scale;
-    double y_scale;
-
-    /* The size of the design unit of the font
-     */
-    int em_square;
-
-    HFONT scaled_hfont;
-    HFONT unscaled_hfont;
-
-    cairo_bool_t is_bitmap;
-    cairo_bool_t is_type1;
-    cairo_bool_t delete_scaled_hfont;
-    cairo_bool_t has_type1_notdef_index;
-    unsigned long type1_notdef_index;
-} cairo_win32_scaled_font_t;
-
-static cairo_status_t
-_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
-					     cairo_scaled_glyph_t      *scaled_glyph);
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
-                                             cairo_scaled_glyph_t      *scaled_glyph);
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
-					  cairo_scaled_glyph_t      *scaled_glyph);
-
-static void
-_cairo_win32_font_face_destroy (void *abstract_face);
-
-
-#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
-
-static HDC
-_get_global_font_dc (void)
-{
-    static HDC hdc;
-
-    if (!hdc) {
-	hdc = CreateCompatibleDC (NULL);
-	if (!hdc) {
-	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
-	    return NULL;
-	}
-
-	if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
-	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
-	    DeleteDC (hdc);
-	    return NULL;
-	}
-    }
-
-    return hdc;
-}
-
-static cairo_status_t
-_compute_transform (cairo_win32_scaled_font_t *scaled_font,
-		    cairo_matrix_t            *sc)
-{
-    cairo_status_t status;
-
-    if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy) &&
-	    !NEARLY_ZERO(sc->xx) && !NEARLY_ZERO(sc->yy)) {
-	scaled_font->preserve_axes = TRUE;
-	scaled_font->x_scale = sc->xx;
-	scaled_font->swap_x = (sc->xx < 0);
-	scaled_font->y_scale = sc->yy;
-	scaled_font->swap_y = (sc->yy < 0);
-	scaled_font->swap_axes = FALSE;
-
-    } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy) &&
-	    !NEARLY_ZERO(sc->yx) && !NEARLY_ZERO(sc->xy)) {
-	scaled_font->preserve_axes = TRUE;
-	scaled_font->x_scale = sc->yx;
-	scaled_font->swap_x = (sc->yx < 0);
-	scaled_font->y_scale = sc->xy;
-	scaled_font->swap_y = (sc->xy < 0);
-	scaled_font->swap_axes = TRUE;
-
-    } else {
-	scaled_font->preserve_axes = FALSE;
-	scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE;
-    }
-
-    if (scaled_font->preserve_axes) {
-	if (scaled_font->swap_x)
-	    scaled_font->x_scale = - scaled_font->x_scale;
-	if (scaled_font->swap_y)
-	    scaled_font->y_scale = - scaled_font->y_scale;
-
-	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
-	scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
-                                    _cairo_lround (scaled_font->y_scale);
-    }
-
-    /* The font matrix has x and y "scale" components which we extract and
-     * use as character scale values.
-     */
-    cairo_matrix_init (&scaled_font->logical_to_device,
-		       sc->xx, sc->yx, sc->xy, sc->yy, 0, 0);
-
-    if (!scaled_font->preserve_axes) {
-	status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device,
-						      &scaled_font->x_scale, &scaled_font->y_scale,
-						      TRUE);	/* XXX: Handle vertical text */
-	if (status)
-	    return status;
-
-	scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
-                                                   scaled_font->y_scale);
-	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
-    }
-
-    cairo_matrix_scale (&scaled_font->logical_to_device,
-			1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
-
-    scaled_font->device_to_logical = scaled_font->logical_to_device;
-
-    status = cairo_matrix_invert (&scaled_font->device_to_logical);
-    if (status)
-	cairo_matrix_init_identity (&scaled_font->device_to_logical);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-_have_cleartype_quality (void)
-{
-    OSVERSIONINFO version_info;
-
-    version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-
-    if (!GetVersionEx (&version_info)) {
-	_cairo_win32_print_gdi_error ("_have_cleartype_quality");
-	return FALSE;
-    }
-
-    return (version_info.dwMajorVersion > 5 ||
-	    (version_info.dwMajorVersion == 5 &&
-	     version_info.dwMinorVersion >= 1));	/* XP or newer */
-}
-
-static BYTE
-_get_system_quality (void)
-{
-    BOOL font_smoothing;
-    UINT smoothing_type;
-
-    if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
-	_cairo_win32_print_gdi_error ("_get_system_quality");
-	return DEFAULT_QUALITY;
-    }
-
-    if (font_smoothing) {
-	if (_have_cleartype_quality ()) {
-	    if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE,
-				       0, &smoothing_type, 0)) {
-		_cairo_win32_print_gdi_error ("_get_system_quality");
-		return DEFAULT_QUALITY;
-	    }
-
-	    if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
-		return CLEARTYPE_QUALITY;
-	}
-
-	return ANTIALIASED_QUALITY;
-    } else {
-	return DEFAULT_QUALITY;
-    }
-}
-
-/* If face_hfont is non-%NULL then font_matrix must be a simple scale by some
- * factor S, ctm must be the identity, logfont->lfHeight must be -S,
- * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
- * all be 0, and face_hfont is the result of calling CreateFontIndirectW on
- * logfont.
- */
-static cairo_status_t
-_win32_scaled_font_create (LOGFONTW                   *logfont,
-			   HFONT                      face_hfont,
-			   cairo_font_face_t	      *font_face,
-			   const cairo_matrix_t       *font_matrix,
-			   const cairo_matrix_t       *ctm,
-			   const cairo_font_options_t *options,
-			   cairo_scaled_font_t       **font_out)
-{
-    HDC hdc;
-    cairo_win32_scaled_font_t *f;
-    cairo_matrix_t scale;
-    cairo_status_t status;
-
-    hdc = _get_global_font_dc ();
-    if (hdc == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    f = malloc (sizeof(cairo_win32_scaled_font_t));
-    if (f == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    f->logfont = *logfont;
-
-    /* We don't have any control over the hinting style or subpixel
-     * order in the Win32 font API, so we ignore those parts of
-     * cairo_font_options_t. We use the 'antialias' field to set
-     * the 'quality'.
-     *
-     * XXX: The other option we could pay attention to, but don't
-     *      here is the hint_metrics options.
-     */
-    if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
-	f->quality = _get_system_quality ();
-    else {
-	switch (options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
-	    f->quality = NONANTIALIASED_QUALITY;
-	    break;
-	case CAIRO_ANTIALIAS_GRAY:
-	case CAIRO_ANTIALIAS_FAST:
-	case CAIRO_ANTIALIAS_GOOD:
-	    f->quality = ANTIALIASED_QUALITY;
-	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
-	case CAIRO_ANTIALIAS_BEST:
-	    if (_have_cleartype_quality ())
-		f->quality = CLEARTYPE_QUALITY;
-	    else
-		f->quality = ANTIALIASED_QUALITY;
-	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	    ASSERT_NOT_REACHED;
-	}
-    }
-
-    f->em_square = 0;
-    f->scaled_hfont = NULL;
-    f->unscaled_hfont = NULL;
-    f->has_type1_notdef_index = FALSE;
-
-    if (f->quality == logfont->lfQuality ||
-        (logfont->lfQuality == DEFAULT_QUALITY &&
-         options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
-        /* If face_hfont is non-NULL, then we can use it to avoid creating our
-         * own --- because the constraints on face_hfont mentioned above
-         * guarantee it was created in exactly the same way that
-         * _win32_scaled_font_get_scaled_hfont would create it.
-         */
-        f->scaled_hfont = face_hfont;
-    }
-    /* don't delete the hfont if we're using the one passed in to us */
-    f->delete_scaled_hfont = !f->scaled_hfont;
-
-    cairo_matrix_multiply (&scale, font_matrix, ctm);
-    status = _compute_transform (f, &scale);
-    if (status)
-	goto FAIL;
-
-    status = _cairo_scaled_font_init (&f->base, font_face,
-				      font_matrix, ctm, options,
-				      &_cairo_win32_scaled_font_backend);
-    if (status)
-	goto FAIL;
-
-    status = _cairo_win32_scaled_font_set_metrics (f);
-    if (status) {
-	_cairo_scaled_font_fini (&f->base);
-	goto FAIL;
-    }
-
-    *font_out = &f->base;
-    return CAIRO_STATUS_SUCCESS;
-
- FAIL:
-    free (f);
-    return status;
-}
-
-static cairo_status_t
-_win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
-					HDC                        hdc)
-{
-    XFORM xform;
-
-    _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
-
-    if (!SetWorldTransform (hdc, &xform))
-	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_win32_scaled_font_set_identity_transform (HDC hdc)
-{
-    if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY))
-	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font,
-				     HFONT *hfont_out)
-{
-    if (!scaled_font->scaled_hfont) {
-	LOGFONTW logfont = scaled_font->logfont;
-	logfont.lfHeight = -scaled_font->logical_size;
-	logfont.lfWidth = 0;
-	logfont.lfEscapement = 0;
-	logfont.lfOrientation = 0;
-	logfont.lfQuality = scaled_font->quality;
-
-	scaled_font->scaled_hfont = CreateFontIndirectW (&logfont);
-	if (!scaled_font->scaled_hfont)
-	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont");
-    }
-
-    *hfont_out = scaled_font->scaled_hfont;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
-				       HDC                        hdc,
-				       HFONT			 *hfont_out)
-{
-    if (scaled_font->unscaled_hfont == NULL) {
-	OUTLINETEXTMETRIC *otm;
-	unsigned int otm_size;
-	HFONT scaled_hfont;
-	LOGFONTW logfont;
-	cairo_status_t status;
-
-	status = _win32_scaled_font_get_scaled_hfont (scaled_font,
-						      &scaled_hfont);
-	if (status)
-	    return status;
-
-	if (! SelectObject (hdc, scaled_hfont))
-	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
-
-	otm_size = GetOutlineTextMetrics (hdc, 0, NULL);
-	if (! otm_size)
-	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
-
-	otm = malloc (otm_size);
-	if (otm == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	if (! GetOutlineTextMetrics (hdc, otm_size, otm)) {
-	    status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
-	    free (otm);
-	    return status;
-	}
-
-	scaled_font->em_square = otm->otmEMSquare;
-	free (otm);
-
-	logfont = scaled_font->logfont;
-	logfont.lfHeight = -scaled_font->em_square;
-	logfont.lfWidth = 0;
-	logfont.lfEscapement = 0;
-	logfont.lfOrientation = 0;
-	logfont.lfQuality = scaled_font->quality;
-
-	scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont);
-	if (! scaled_font->unscaled_hfont)
-	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");
-    }
-
-    *hfont_out = scaled_font->unscaled_hfont;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
-					       HDC                  hdc)
-{
-    cairo_status_t status;
-    HFONT hfont;
-    HFONT old_hfont = NULL;
-
-    status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont);
-    if (status)
-	return status;
-
-    old_hfont = SelectObject (hdc, hfont);
-    if (!old_hfont)
-	return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
-
-    status = _win32_scaled_font_set_identity_transform (hdc);
-    if (status) {
-	SelectObject (hdc, old_hfont);
-	return status;
-    }
-
-    SetMapMode (hdc, MM_TEXT);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_bool_t
-_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
-{
-    cairo_win32_scaled_font_t *win32_scaled_font;
-
-    win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
-
-    return win32_scaled_font->is_type1;
-}
-
-cairo_bool_t
-_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font)
-{
-    cairo_win32_scaled_font_t *win32_scaled_font;
-
-    win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
-
-    return win32_scaled_font->is_bitmap;
-}
-
-static void
-_cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
-{
-}
-
-/* implement the font backend interface */
-
-static cairo_status_t
-_cairo_win32_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
-				       cairo_font_face_t      **font_face)
-{
-    LOGFONTW logfont;
-    uint16_t *face_name;
-    int face_name_len;
-    cairo_status_t status;
-
-    status = _cairo_utf8_to_utf16 (toy_face->family, -1,
-				   &face_name, &face_name_len);
-    if (status)
-	return status;
-
-    if (face_name_len > LF_FACESIZE - 1)
-	face_name_len = LF_FACESIZE - 1;
-
-    memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * face_name_len);
-    logfont.lfFaceName[face_name_len] = 0;
-    free (face_name);
-
-    logfont.lfHeight = 0;	/* filled in later */
-    logfont.lfWidth = 0;	/* filled in later */
-    logfont.lfEscapement = 0;	/* filled in later */
-    logfont.lfOrientation = 0;	/* filled in later */
-
-    switch (toy_face->weight) {
-    case CAIRO_FONT_WEIGHT_NORMAL:
-    default:
-	logfont.lfWeight = FW_NORMAL;
-	break;
-    case CAIRO_FONT_WEIGHT_BOLD:
-	logfont.lfWeight = FW_BOLD;
-	break;
-    }
-
-    switch (toy_face->slant) {
-    case CAIRO_FONT_SLANT_NORMAL:
-    default:
-	logfont.lfItalic = FALSE;
-	break;
-    case CAIRO_FONT_SLANT_ITALIC:
-    case CAIRO_FONT_SLANT_OBLIQUE:
-	logfont.lfItalic = TRUE;
-	break;
-    }
-
-    logfont.lfUnderline = FALSE;
-    logfont.lfStrikeOut = FALSE;
-    /* The docs for LOGFONT discourage using this, since the
-     * interpretation is locale-specific, but it's not clear what
-     * would be a better alternative.
-     */
-    logfont.lfCharSet = DEFAULT_CHARSET;
-    logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
-    logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
-    logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */
-    logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-
-    *font_face = cairo_win32_font_face_create_for_logfontw (&logfont);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_win32_scaled_font_fini (void *abstract_font)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-
-    if (scaled_font == NULL)
-	return;
-
-    if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)
-	DeleteObject (scaled_font->scaled_hfont);
-
-    if (scaled_font->unscaled_hfont)
-	DeleteObject (scaled_font->unscaled_hfont);
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
-					       double		          x,
-					       double		          y,
-					       const char	         *utf8,
-					       cairo_glyph_t            **glyphs,
-					       int		         *num_glyphs)
-{
-    uint16_t *utf16;
-    int n16;
-    int i;
-    WORD *glyph_indices = NULL;
-    cairo_status_t status;
-    double x_pos, y_pos;
-    HDC hdc = NULL;
-    cairo_matrix_t mat;
-
-    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
-    if (status)
-	return status;
-
-    glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
-    if (!glyph_indices) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL1;
-    }
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	goto FAIL2;
-
-    if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
-	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
-	goto FAIL3;
-    }
-
-    *num_glyphs = n16;
-    *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
-    if (!*glyphs) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL3;
-    }
-
-    x_pos = x;
-    y_pos = y;
-
-    mat = scaled_font->base.ctm;
-    status = cairo_matrix_invert (&mat);
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    _cairo_scaled_font_freeze_cache (&scaled_font->base);
-
-    for (i = 0; i < n16; i++) {
-	cairo_scaled_glyph_t *scaled_glyph;
-
-	(*glyphs)[i].index = glyph_indices[i];
-	(*glyphs)[i].x = x_pos;
-	(*glyphs)[i].y = y_pos;
-
-	status = _cairo_scaled_glyph_lookup (&scaled_font->base,
-					     glyph_indices[i],
-					     CAIRO_SCALED_GLYPH_INFO_METRICS,
-					     &scaled_glyph);
-	if (status) {
-	    free (*glyphs);
-	    *glyphs = NULL;
-	    break;
-	}
-
-	x = scaled_glyph->x_advance;
-	y = scaled_glyph->y_advance;
-	cairo_matrix_transform_distance (&mat, &x, &y);
-	x_pos += x;
-	y_pos += y;
-    }
-
-    _cairo_scaled_font_thaw_cache (&scaled_font->base);
-
-FAIL3:
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-FAIL2:
-    free (glyph_indices);
-FAIL1:
-    free (utf16);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_text_to_glyphs (void		*abstract_font,
-					 double		x,
-					 double		y,
-					 const char	*utf8,
-					 cairo_glyph_t **glyphs,
-					 int		*num_glyphs)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    uint16_t *utf16;
-    int n16;
-    GCP_RESULTSW gcp_results;
-    unsigned int buffer_size, i;
-    WCHAR *glyph_indices = NULL;
-    int *dx = NULL;
-    cairo_status_t status;
-    double x_pos, y_pos;
-    double x_incr, y_incr;
-    HDC hdc = NULL;
-
-    /* GetCharacterPlacement() returns utf16 instead of glyph indices
-     * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
-    if (scaled_font->is_type1)
-	 return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
-							       x,
-							       y,
-							       utf8,
-							       glyphs,
-							       num_glyphs);
-
-    /* Compute a vector in user space along the baseline of length one logical space unit */
-    x_incr = 1;
-    y_incr = 0;
-    cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr);
-    x_incr /= scaled_font->logical_scale;
-    y_incr /= scaled_font->logical_scale;
-
-    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
-    if (status)
-	return status;
-
-    gcp_results.lStructSize = sizeof (GCP_RESULTS);
-    gcp_results.lpOutString = NULL;
-    gcp_results.lpOrder = NULL;
-    gcp_results.lpCaretPos = NULL;
-    gcp_results.lpClass = NULL;
-
-    buffer_size = MAX (n16 * 1.2, 16);		/* Initially guess number of chars plus a few */
-    if (buffer_size > INT_MAX) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL1;
-    }
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	goto FAIL1;
-
-    while (TRUE) {
-	free (glyph_indices);
-	glyph_indices = NULL;
-
-	free (dx);
-	dx = NULL;
-
-	glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
-	dx = _cairo_malloc_ab (buffer_size, sizeof (int));
-	if (!glyph_indices || !dx) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto FAIL2;
-	}
-
-	gcp_results.nGlyphs = buffer_size;
-	gcp_results.lpDx = dx;
-	gcp_results.lpGlyphs = glyph_indices;
-
-	if (!GetCharacterPlacementW (hdc, utf16, n16,
-				     0,
-				     &gcp_results,
-				     GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) {
-	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs");
-	    goto FAIL2;
-	}
-
-	if (gcp_results.lpDx && gcp_results.lpGlyphs)
-	    break;
-
-	/* Too small a buffer, try again */
-
-	buffer_size += buffer_size / 2;
-	if (buffer_size > INT_MAX) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto FAIL2;
-	}
-    }
-
-    *num_glyphs = gcp_results.nGlyphs;
-    *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
-    if (!*glyphs) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL2;
-    }
-
-    x_pos = x;
-    y_pos = y;
-
-    for (i = 0; i < gcp_results.nGlyphs; i++) {
-	(*glyphs)[i].index = glyph_indices[i];
-	(*glyphs)[i].x = x_pos ;
-	(*glyphs)[i].y = y_pos;
-
-	x_pos += x_incr * dx[i];
-	y_pos += y_incr * dx[i];
-    }
-
- FAIL2:
-    free (glyph_indices);
-    free (dx);
-
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-
- FAIL1:
-    free (utf16);
-
-    return status;
-}
-
-static unsigned long
-_cairo_win32_scaled_font_ucs4_to_index (void		*abstract_font,
-					uint32_t	 ucs4)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    wchar_t unicode[2];
-    WORD glyph_index;
-    HDC hdc = NULL;
-    cairo_status_t status;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	return 0;
-
-    unicode[0] = ucs4;
-    unicode[1] = 0;
-    if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
-	_cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW");
-	glyph_index = 0;
-    }
-
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-    return glyph_index;
-}
-
-static cairo_status_t
-_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
-{
-    cairo_status_t status;
-    cairo_font_extents_t extents;
-
-    TEXTMETRIC metrics;
-    HDC hdc;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) {
-	/* For 90-degree rotations (including 0), we get the metrics
-	 * from the GDI in logical space, then convert back to font space
-	 */
-	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-	GetTextMetrics (hdc, &metrics);
-	cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-	extents.ascent = metrics.tmAscent / scaled_font->logical_scale;
-	extents.descent = metrics.tmDescent / scaled_font->logical_scale;
-
-	extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;
-	extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;
-	extents.max_y_advance = 0;
-
-    } else {
-	/* For all other transformations, we use the design metrics
-	 * of the font. The GDI results from GetTextMetrics() on a
-	 * transformed font are inexplicably large and we want to
-	 * avoid them.
-	 */
-	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-	GetTextMetrics (hdc, &metrics);
-	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
-
-	extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;
-	extents.descent = (double)metrics.tmDescent / scaled_font->em_square;
-	extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
-	extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
-	extents.max_y_advance = 0;
-
-    }
-
-    scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
-
-    /* Need to determine if this is a Type 1 font for the special
-     * handling in _text_to_glyphs.  Unlike TrueType or OpenType,
-     * Type1 fonts do not have a "cmap" table (or any other table).
-     * However GetFontData() will retrieve a Type1 font when
-     * requesting that GetFontData() retrieve data from the start of
-     * the file. This is to distinguish Type1 from stroke fonts such
-     * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant
-     * but improves performance for the most common fonts.
-     */
-    scaled_font->is_type1 = FALSE;
-    if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
-	(metrics.tmPitchAndFamily & TMPF_VECTOR))
-    {
-	 if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
-	     (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
-	 {
-	      scaled_font->is_type1 = TRUE;
-	 }
-    }
-
-    return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
-}
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
-					     cairo_scaled_glyph_t      *scaled_glyph)
-{
-    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
-    GLYPHMETRICS metrics;
-    cairo_status_t status;
-    cairo_text_extents_t extents;
-    HDC hdc;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    if (scaled_font->is_bitmap) {
-	/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
-	cairo_font_extents_t font_extents;
-	INT width = 0;
-	UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
-
-	cairo_scaled_font_extents (&scaled_font->base, &font_extents);
-
-	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-
-	if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
-	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
-	    width = 0;
-	}
-	cairo_win32_scaled_font_done_font (&scaled_font->base);
-	if (status)
-	    return status;
-
-	extents.x_bearing = 0;
-	extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale);
-	extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale);
-	extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
-	extents.x_advance = extents.width;
-	extents.y_advance = 0;
-    } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
-	/* If we aren't rotating / skewing the axes, then we get the metrics
-	 * from the GDI in device space and convert to font space.
-	 */
-	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-
-	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			      GGO_METRICS | GGO_GLYPH_INDEX,
-			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
-	    memset (&metrics, 0, sizeof (GLYPHMETRICS));
-	} else {
-	    if (metrics.gmBlackBoxX > 0 && scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE) {
-		/* The bounding box reported by Windows supposedly contains the glyph's "black" area;
-		 * however, antialiasing (especially with ClearType) means that the actual image that
-		 * needs to be rendered may "bleed" into the adjacent pixels, mainly on the right side.
-		 * To avoid clipping the glyphs when drawn by _cairo_surface_fallback_show_glyphs,
-		 * for example, or other code that uses glyph extents to determine the area to update,
-		 * we add a pixel of "slop" to left side of the nominal "black" area returned by GDI,
-		 * and two pixels to the right (as tests show some glyphs bleed into this column).
-		 */
-		metrics.gmptGlyphOrigin.x -= 1;
-		metrics.gmBlackBoxX += 3;
-	    }
-	}
-	cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-	if (scaled_font->swap_axes) {
-	    extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
-	    extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
-	    extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;
-	    extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;
-	    extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;
-	    extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;
-	} else {
-	    extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
-	    extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
-	    extents.width = metrics.gmBlackBoxX / scaled_font->x_scale;
-	    extents.height = metrics.gmBlackBoxY / scaled_font->y_scale;
-	    extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale;
-	    extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale;
-	}
-
-	if (scaled_font->swap_x) {
-	    extents.x_bearing = (- extents.x_bearing - extents.width);
-	    extents.x_advance = - extents.x_advance;
-	}
-
-	if (scaled_font->swap_y) {
-	    extents.y_bearing = (- extents.y_bearing - extents.height);
-	    extents.y_advance = - extents.y_advance;
-	}
-
-    } else {
-	/* For all other transformations, we use the design metrics
-	 * of the font.
-	 */
-	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-
-	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-	                      GGO_METRICS | GGO_GLYPH_INDEX,
-			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
-	    memset (&metrics, 0, sizeof (GLYPHMETRICS));
-	}
-	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
-
-	extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
-	extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
-	extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
-	extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
-	extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
-	extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
-    }
-
-    _cairo_scaled_glyph_set_metrics (scaled_glyph,
-				     &scaled_font->base,
-				     &extents);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* Not currently used code, but may be useful in the future if we add
- * back the capability to the scaled font backend interface to get the
- * actual device space bbox rather than computing it from the
- * font-space metrics.
- */
-#if 0
-static cairo_status_t
-_cairo_win32_scaled_font_glyph_bbox (void		 *abstract_font,
-				     const cairo_glyph_t *glyphs,
-				     int                  num_glyphs,
-				     cairo_box_t         *bbox)
-{
-    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
-
-    if (num_glyphs > 0) {
-	HDC hdc;
-	GLYPHMETRICS metrics;
-	cairo_status_t status;
-	int i;
-
-	hdc = _get_global_font_dc ();
-	assert (hdc != NULL);
-
-	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-	if (status)
-	    return status;
-
-	for (i = 0; i < num_glyphs; i++) {
-	    int x = _cairo_lround (glyphs[i].x);
-	    int y = _cairo_lround (glyphs[i].y);
-
-	    GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
-			     &metrics, 0, NULL, &matrix);
-
-	    if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
-		x1 = x + metrics.gmptGlyphOrigin.x;
-	    if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y)
-		y1 = y - metrics.gmptGlyphOrigin.y;
-	    if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX)
-		x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX;
-	    if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY)
-		y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY;
-	}
-
-	cairo_win32_scaled_font_done_font (&scaled_font->base);
-    }
-
-    bbox->p1.x = _cairo_fixed_from_int (x1);
-    bbox->p1.y = _cairo_fixed_from_int (y1);
-    bbox->p2.x = _cairo_fixed_from_int (x2);
-    bbox->p2.y = _cairo_fixed_from_int (y2);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-#endif
-
-typedef struct {
-    cairo_win32_scaled_font_t *scaled_font;
-    HDC hdc;
-
-    cairo_array_t glyphs;
-    cairo_array_t dx;
-
-    int start_x;
-    int last_x;
-    int last_y;
-} cairo_glyph_state_t;
-
-static void
-_start_glyphs (cairo_glyph_state_t        *state,
-	       cairo_win32_scaled_font_t  *scaled_font,
-	       HDC                         hdc)
-{
-    state->hdc = hdc;
-    state->scaled_font = scaled_font;
-
-    _cairo_array_init (&state->glyphs, sizeof (WCHAR));
-    _cairo_array_init (&state->dx, sizeof (int));
-}
-
-static cairo_status_t
-_flush_glyphs (cairo_glyph_state_t *state)
-{
-    cairo_status_t status;
-    int dx = 0;
-    WCHAR * elements;
-    int * dx_elements;
-
-    status = _cairo_array_append (&state->dx, &dx);
-    if (status)
-	return status;
-
-    elements = _cairo_array_index (&state->glyphs, 0);
-    dx_elements = _cairo_array_index (&state->dx, 0);
-    if (!ExtTextOutW (state->hdc,
-		      state->start_x, state->last_y,
-		      ETO_GLYPH_INDEX,
-		      NULL,
-		      elements,
-		      state->glyphs.num_elements,
-		      dx_elements)) {
-	return _cairo_win32_print_gdi_error ("_flush_glyphs");
-    }
-
-    _cairo_array_truncate (&state->glyphs, 0);
-    _cairo_array_truncate (&state->dx, 0);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_add_glyph (cairo_glyph_state_t *state,
-	    unsigned long        index,
-	    double               device_x,
-	    double               device_y)
-{
-    cairo_status_t status;
-    double user_x = device_x;
-    double user_y = device_y;
-    WCHAR glyph_index = index;
-    int logical_x, logical_y;
-
-    cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
-
-    logical_x = _cairo_lround (user_x);
-    logical_y = _cairo_lround (user_y);
-
-    if (state->glyphs.num_elements > 0) {
-	int dx;
-
-	if (logical_y != state->last_y) {
-	    status = _flush_glyphs (state);
-	    if (status)
-		return status;
-	    state->start_x = logical_x;
-	} else {
-	    dx = logical_x - state->last_x;
-	    status = _cairo_array_append (&state->dx, &dx);
-	    if (status)
-		return status;
-	}
-    } else {
-	state->start_x = logical_x;
-    }
-
-    state->last_x = logical_x;
-    state->last_y = logical_y;
-
-    status = _cairo_array_append (&state->glyphs, &glyph_index);
-    if (status)
-	return status;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_finish_glyphs (cairo_glyph_state_t *state)
-{
-    cairo_status_t status;
-
-    status = _flush_glyphs (state);
-
-    _cairo_array_fini (&state->glyphs);
-    _cairo_array_fini (&state->dx);
-
-    return status;
-}
-
-static cairo_status_t
-_draw_glyphs_on_surface (cairo_win32_surface_t     *surface,
-			 cairo_win32_scaled_font_t *scaled_font,
-			 COLORREF                   color,
-			 int                        x_offset,
-			 int                        y_offset,
-			 const cairo_glyph_t       *glyphs,
-			 int			    num_glyphs)
-{
-    cairo_glyph_state_t state;
-    cairo_status_t status, status2;
-    int i;
-
-    if (!SaveDC (surface->dc))
-	return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
-    if (status)
-	goto FAIL1;
-
-    SetTextColor (surface->dc, color);
-    SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT);
-    SetBkMode (surface->dc, TRANSPARENT);
-
-    _start_glyphs (&state, scaled_font, surface->dc);
-
-    for (i = 0; i < num_glyphs; i++) {
-	status = _add_glyph (&state, glyphs[i].index,
-			     glyphs[i].x - x_offset, glyphs[i].y - y_offset);
-	if (status)
-	    goto FAIL2;
-    }
-
- FAIL2:
-    status2 = _finish_glyphs (&state);
-    if (status == CAIRO_STATUS_SUCCESS)
-	status = status2;
-
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
- FAIL1:
-    RestoreDC (surface->dc, -1);
-
-    return status;
-}
-
-/* Duplicate the green channel of a 4-channel mask in the alpha channel, then
- * invert the whole mask.
- */
-static void
-_compute_argb32_mask_alpha (cairo_win32_surface_t *mask_surface)
-{
-    cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
-    int i, j;
-
-    for (i = 0; i < image->height; i++) {
-	uint32_t *p = (uint32_t *) (image->data + i * image->stride);
-	for (j = 0; j < image->width; j++) {
-	    *p = 0xffffffff ^ (*p | ((*p & 0x0000ff00) << 16));
-	    p++;
-	}
-    }
-}
-
-/* Invert a mask
- */
-static void
-_invert_argb32_mask (cairo_win32_surface_t *mask_surface)
-{
-    cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
-    int i, j;
-
-    for (i = 0; i < image->height; i++) {
-	uint32_t *p = (uint32_t *) (image->data + i * image->stride);
-	for (j = 0; j < image->width; j++) {
-	    *p = 0xffffffff ^ *p;
-	    p++;
-	}
-    }
-}
-
-/* Compute an alpha-mask from a monochrome RGB24 image
- */
-static cairo_surface_t *
-_compute_a8_mask (cairo_win32_surface_t *mask_surface)
-{
-    cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
-    cairo_image_surface_t *image8;
-    int i, j;
-
-    if (image24->base.status)
-	return cairo_surface_reference (&image24->base);
-
-    image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
-								  image24->width, image24->height);
-    if (image8->base.status)
-	return &image8->base;
-
-    for (i = 0; i < image24->height; i++) {
-	uint32_t *p = (uint32_t *) (image24->data + i * image24->stride);
-	unsigned char *q = (unsigned char *) (image8->data + i * image8->stride);
-
-	for (j = 0; j < image24->width; j++) {
-	    *q = 255 - ((*p & 0x0000ff00) >> 8);
-	    p++;
-	    q++;
-	}
-    }
-
-    return &image8->base;
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_glyph_init (void		       *abstract_font,
-				     cairo_scaled_glyph_t      *scaled_glyph,
-				     cairo_scaled_glyph_info_t  info)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    cairo_status_t status;
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
-	status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph);
-	if (status)
-	    return status;
-    }
-
-    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
-	status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
-	if (status)
-	    return status;
-    }
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
-	status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
-	if (status)
-	    return status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-#if 0
-static cairo_int_status_t
-_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,
-				      cairo_region_t		*clip_region,
-				      int			*remaining_glyphs)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
-    cairo_status_t status;
-
-    if (width == 0 || height == 0)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (_cairo_surface_is_win32 (generic_surface) &&
-	surface->format == CAIRO_FORMAT_RGB24 &&
-	op == CAIRO_OPERATOR_OVER &&
-	_cairo_pattern_is_opaque_solid (pattern)) {
-
-	cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern;
-
-	/* When compositing OVER on a GDI-understood surface, with a
-	 * solid opaque color, we can just call ExtTextOut directly.
-	 */
-	COLORREF new_color;
-
-	status = _cairo_win32_surface_set_clip_region (surface, clip_region);
-	if (unlikely (status))
-	    return status;
-
-	new_color = RGB (((int)solid_pattern->color.red_short) >> 8,
-			 ((int)solid_pattern->color.green_short) >> 8,
-			 ((int)solid_pattern->color.blue_short) >> 8);
-
-	return _draw_glyphs_on_surface (surface, scaled_font, new_color,
-					0, 0,
-					glyphs, num_glyphs);
-    } else {
-	/* Otherwise, we need to draw using software fallbacks. We create a mask
-	 * surface by drawing the the glyphs onto a DIB, black-on-white then
-	 * inverting. GDI outputs gamma-corrected images so inverted black-on-white
-	 * is very different from white-on-black. We favor the more common
-	 * case where the final output is dark-on-light.
-	 */
-	cairo_win32_surface_t *tmp_surface;
-	cairo_surface_t *mask_surface;
-	cairo_surface_pattern_t mask;
-	RECT r;
-
-	tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
-	if (tmp_surface->base.status)
-	    return tmp_surface->base.status;
-
-	r.left = 0;
-	r.top = 0;
-	r.right = width;
-	r.bottom = height;
-	FillRect (tmp_surface->dc, &r, GetStockObject (WHITE_BRUSH));
-
-	status = _draw_glyphs_on_surface (tmp_surface,
-		                          scaled_font, RGB (0, 0, 0),
-					  dest_x, dest_y,
-					  glyphs, num_glyphs);
-	if (status) {
-	    cairo_surface_destroy (&tmp_surface->base);
-	    return status;
-	}
-
-	if (scaled_font->quality == CLEARTYPE_QUALITY) {
-	    /* For ClearType, we need a 4-channel mask. If we are compositing on
-	     * a surface with alpha, we need to compute the alpha channel of
-	     * the mask (we just copy the green channel). But for a destination
-	     * surface without alpha the alpha channel of the mask is ignored
-	     */
-
-	    if (surface->format != CAIRO_FORMAT_RGB24)
-		_compute_argb32_mask_alpha (tmp_surface);
-	    else
-		_invert_argb32_mask (tmp_surface);
-
-	    mask_surface = &tmp_surface->base;
-	} else {
-	    mask_surface = _compute_a8_mask (tmp_surface);
-	    cairo_surface_destroy (&tmp_surface->base);
-	    status = mask_surface->status;
-	    if (status)
-		return status;
-	}
-
-	/* For op == OVER, no-cleartype, a possible optimization here is to
-	 * draw onto an intermediate ARGB32 surface and alpha-blend that with the
-	 * destination
-	 */
-	_cairo_pattern_init_for_surface (&mask, mask_surface);
-	cairo_surface_destroy (mask_surface);
-
-	if (scaled_font->quality == CLEARTYPE_QUALITY)
-	    mask.base.has_component_alpha = TRUE;
-
-	status = _cairo_surface_mask (&surface->base, op, pattern, &mask.base,
-					   clip_region);
-
-	_cairo_pattern_fini (&mask.base);
-
-	return status;
-    }
-}
-#endif
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_load_truetype_table (void	       *abstract_font,
-                                             unsigned long      tag,
-                                             long               offset,
-                                             unsigned char     *buffer,
-                                             unsigned long     *length)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    HDC hdc;
-    cairo_status_t status;
-    DWORD ret;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	return status;
-
-    ret = GetFontData (hdc, tag, offset, buffer, *length);
-    if (ret == GDI_ERROR || (buffer && ret != *length))
-        status = CAIRO_INT_STATUS_UNSUPPORTED;
-    else
-	*length = ret;
-
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_index_to_ucs4 (void		*abstract_font,
-					unsigned long    index,
-					uint32_t	*ucs4)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    GLYPHSET *glyph_set;
-    uint16_t *utf16 = NULL;
-    WORD *glyph_indices = NULL;
-    HDC hdc = NULL;
-    int res;
-    unsigned int i, j, num_glyphs;
-    cairo_status_t status;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	return status;
-
-    res = GetFontUnicodeRanges(hdc, NULL);
-    if (res == 0) {
-	status = _cairo_win32_print_gdi_error (
-	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
-	goto exit1;
-    }
-
-    glyph_set = malloc (res);
-    if (glyph_set == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto exit1;
-    }
-
-    res = GetFontUnicodeRanges(hdc, glyph_set);
-    if (res == 0) {
-	status = _cairo_win32_print_gdi_error (
-	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
-	goto exit1;
-    }
-
-    *ucs4 = (uint32_t) -1;
-    for (i = 0; i < glyph_set->cRanges; i++) {
-	num_glyphs = glyph_set->ranges[i].cGlyphs;
-
-	utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
-	if (utf16 == NULL) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto exit1;
-	}
-
-	glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
-	if (glyph_indices == NULL) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto exit2;
-	}
-
-	for (j = 0; j < num_glyphs; j++)
-	    utf16[j] = glyph_set->ranges[i].wcLow + j;
-	utf16[j] = 0;
-
-	if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
-	    status = _cairo_win32_print_gdi_error (
-		"_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
-	    goto exit2;
-	}
-
-	for (j = 0; j < num_glyphs; j++) {
-	    if (glyph_indices[j] == index) {
-		*ucs4 = utf16[j];
-		goto exit2;
-	    }
-	}
-
-	free (glyph_indices);
-	glyph_indices = NULL;
-	free (utf16);
-	utf16 = NULL;
-    }
-
-exit2:
-    free (glyph_indices);
-    free (utf16);
-    free (glyph_set);
-exit1:
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-    return status;
-}
-
-static cairo_bool_t
-_cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    cairo_status_t status;
-    int	weight;
-    cairo_bool_t bold;
-    cairo_bool_t italic;
-
-    status = _cairo_truetype_get_style (&scaled_font->base,
-					&weight,
-					&bold,
-					&italic);
-    /* If this doesn't work assume it is not synthetic to avoid
-     * unneccessary subsetting fallbacks. */
-    if (status != CAIRO_STATUS_SUCCESS)
-	return FALSE;
-
-    if (scaled_font->logfont.lfWeight != weight ||
-	scaled_font->logfont.lfItalic != italic)
-	return TRUE;
-
-    return FALSE;
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_index_to_glyph_name (void	      	*abstract_font,
-					      char             **glyph_names,
-					      int              	 num_glyph_names,
-					      unsigned long      glyph_index,
-					      unsigned long     *glyph_array_index)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    int i;
-
-    /* Windows puts .notdef at index 0 then numbers the remaining
-     * glyphs starting from 1 in the order they appear in the font. */
-
-    /* Find the position of .notdef in the list of glyph names. We
-     * only need to do this once per scaled font. */
-    if (! scaled_font->has_type1_notdef_index) {
-	for (i = 0; i < num_glyph_names; i++) {
-	    if (strcmp (glyph_names[i], ".notdef") == 0) {
-		scaled_font->type1_notdef_index = i;
-		scaled_font->has_type1_notdef_index = TRUE;
-		break;
-	    }
-	}
-	if (! scaled_font->has_type1_notdef_index)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    /* Once we know the position of .notdef the position of any glyph
-     * in the font can easily be obtained. */
-    if (glyph_index == 0)
-	*glyph_array_index = scaled_font->type1_notdef_index;
-    else if (glyph_index <= scaled_font->type1_notdef_index)
-	*glyph_array_index = glyph_index - 1;
-    else if (glyph_index < num_glyph_names)
-	*glyph_array_index = glyph_index;
-    else
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_win32_scaled_font_load_type1_data (void	            *abstract_font,
-					  long               offset,
-					  unsigned char     *buffer,
-					  unsigned long     *length)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-
-    if (! scaled_font->is_type1)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Using the tag 0 retrieves the entire font file. This works with
-     * Type 1 fonts as well as TTF/OTF fonts. */
-    return _cairo_win32_scaled_font_load_truetype_table (scaled_font,
-							 0,
-							 offset,
-							 buffer,
-							 length);
-}
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
-                                             cairo_scaled_glyph_t      *scaled_glyph)
-{
-    cairo_status_t status;
-    cairo_glyph_t glyph;
-    cairo_win32_surface_t *surface;
-    cairo_t *cr;
-    cairo_surface_t *image;
-    int width, height;
-    int x1, y1, x2, y2;
-
-    x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
-    y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
-    x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
-    y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
-    width = x2 - x1;
-    height = y2 - y1;
-
-    surface = (cairo_win32_surface_t *)
-	cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
-
-    cr = cairo_create (&surface->base);
-    cairo_set_source_rgb (cr, 1, 1, 1);
-    cairo_paint (cr);
-    status = cairo_status (cr);
-    cairo_destroy(cr);
-    if (status)
-	goto FAIL;
-
-    glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
-    glyph.x = -x1;
-    glyph.y = -y1;
-    status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
-                                      0, 0, &glyph, 1);
-    if (status)
-	goto FAIL;
-
-    GdiFlush();
-
-    image = _compute_a8_mask (surface);
-    status = image->status;
-    if (status)
-	goto FAIL;
-
-    cairo_surface_set_device_offset (image, -x1, -y1);
-    _cairo_scaled_glyph_set_surface (scaled_glyph,
-                                     &scaled_font->base,
-                                     (cairo_image_surface_t *) image);
-
-  FAIL:
-    cairo_surface_destroy (&surface->base);
-
-    return status;
-}
-
-static void
-_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
-                                       FIXED Fx, FIXED Fy,
-                                       cairo_fixed_t *fx, cairo_fixed_t *fy)
-{
-    double x = Fx.value + Fx.fract / 65536.0;
-    double y = Fy.value + Fy.fract / 65536.0;
-    cairo_matrix_transform_point (matrix, &x, &y);
-    *fx = _cairo_fixed_from_double (x);
-    *fy = _cairo_fixed_from_double (y);
-}
-
-static cairo_status_t
-_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
-					  cairo_scaled_glyph_t      *scaled_glyph)
-{
-    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
-    cairo_status_t status;
-    GLYPHMETRICS metrics;
-    HDC hdc;
-    DWORD bytesGlyph;
-    unsigned char *buffer, *ptr;
-    cairo_path_fixed_t *path;
-    cairo_matrix_t transform;
-    cairo_fixed_t x, y;
-
-    if (scaled_font->is_bitmap)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    hdc = _get_global_font_dc ();
-    assert (hdc != NULL);
-
-    path = _cairo_path_fixed_create ();
-    if (!path)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) {
-        status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
-        transform = scaled_font->base.scale;
-        cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square);
-    } else {
-        status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-        cairo_matrix_init_identity(&transform);
-    }
-    if (status)
-        goto CLEANUP_PATH;
-
-    bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-				   GGO_NATIVE | GGO_GLYPH_INDEX,
-				   &metrics, 0, NULL, &matrix);
-
-    if (bytesGlyph == GDI_ERROR) {
-	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
-	goto CLEANUP_FONT;
-    }
-
-    ptr = buffer = malloc (bytesGlyph);
-    if (!buffer) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto CLEANUP_FONT;
-    }
-
-    if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			  GGO_NATIVE | GGO_GLYPH_INDEX,
-			  &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
-	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
-	goto CLEANUP_BUFFER;
-    }
-
-    while (ptr < buffer + bytesGlyph) {
-	TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
-	unsigned char *endPoly = ptr + header->cb;
-
-	ptr += sizeof (TTPOLYGONHEADER);
-
-        _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                               header->pfxStart.x,
-                                               header->pfxStart.y,
-                                               &x, &y);
-        status = _cairo_path_fixed_move_to (path, x, y);
-	if (status)
-	    goto CLEANUP_BUFFER;
-
-	while (ptr < endPoly) {
-	    TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
-	    POINTFX *points = curve->apfx;
-	    int i;
-	    switch (curve->wType) {
-	    case TT_PRIM_LINE:
-		for (i = 0; i < curve->cpfx; i++) {
-                    _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                           points[i].x,
-                                                           points[i].y,
-                                                           &x, &y);
-		    status = _cairo_path_fixed_line_to (path, x, y);
-		    if (status)
-			goto CLEANUP_BUFFER;
-		}
-		break;
-	    case TT_PRIM_QSPLINE:
-		for (i = 0; i < curve->cpfx - 1; i++) {
-		    cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
-		    if (! _cairo_path_fixed_get_current_point (path, &p1x, &p1y))
-			goto CLEANUP_BUFFER;
-                    _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                           points[i].x,
-                                                           points[i].y,
-                                                           &cx, &cy);
-
-		    if (i + 1 == curve->cpfx - 1) {
-                        _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                               points[i + 1].x,
-                                                               points[i + 1].y,
-                                                               &p2x, &p2y);
-		    } else {
-			/* records with more than one curve use interpolation for
-			   control points, per http://support.microsoft.com/kb/q87115/ */
-                        _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                               points[i + 1].x,
-                                                               points[i + 1].y,
-                                                               &x, &y);
-                        p2x = (cx + x) / 2;
-			p2y = (cy + y) / 2;
-		    }
-
-		    c1x = 2 * cx / 3 + p1x / 3;
-		    c1y = 2 * cy / 3 + p1y / 3;
-		    c2x = 2 * cx / 3 + p2x / 3;
-		    c2y = 2 * cy / 3 + p2y / 3;
-
-		    status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
-		    if (status)
-			goto CLEANUP_BUFFER;
-		}
-		break;
-	    case TT_PRIM_CSPLINE:
-		for (i = 0; i < curve->cpfx - 2; i += 2) {
-		    cairo_fixed_t x1, y1, x2, y2;
-                    _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                           points[i].x,
-                                                           points[i].y,
-                                                           &x, &y);
-                    _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                           points[i + 1].x,
-                                                           points[i + 1].y,
-                                                           &x1, &y1);
-                    _cairo_win32_transform_FIXED_to_fixed (&transform,
-                                                           points[i + 2].x,
-                                                           points[i + 2].y,
-                                                           &x2, &y2);
-		    status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2);
-		    if (status)
-			goto CLEANUP_BUFFER;
-		}
-		break;
-	    }
-	    ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
-	}
-	status = _cairo_path_fixed_close_path (path);
-	if (status)
-	    goto CLEANUP_BUFFER;
-    }
-
-    _cairo_scaled_glyph_set_path (scaled_glyph,
-				  &scaled_font->base,
-				  path);
-
- CLEANUP_BUFFER:
-    free (buffer);
-
- CLEANUP_FONT:
-    if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE)
-	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
-    else
-	cairo_win32_scaled_font_done_font (&scaled_font->base);
-
- CLEANUP_PATH:
-    if (status != CAIRO_STATUS_SUCCESS)
-	_cairo_path_fixed_destroy (path);
-
-    return status;
-}
-
-const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
-    CAIRO_FONT_TYPE_WIN32,
-    _cairo_win32_scaled_font_fini,
-    _cairo_win32_scaled_font_glyph_init,
-    NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
-    _cairo_win32_scaled_font_ucs4_to_index,
-    _cairo_win32_scaled_font_load_truetype_table,
-    _cairo_win32_scaled_font_index_to_ucs4,
-    _cairo_win32_scaled_font_is_synthetic,
-    _cairo_win32_scaled_font_index_to_glyph_name,
-    _cairo_win32_scaled_font_load_type1_data
-};
-
-/* #cairo_win32_font_face_t */
-
-typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
-
-/* If hfont is non-%NULL then logfont->lfHeight must be -S for some S,
- * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
- * all be 0, and hfont is the result of calling CreateFontIndirectW on
- * logfont.
- */
-struct _cairo_win32_font_face {
-    cairo_font_face_t base;
-    LOGFONTW logfont;
-    HFONT hfont;
-};
-
-/* implement the platform-specific interface */
-
-static cairo_bool_t
-_is_scale (const cairo_matrix_t *matrix, double scale)
-{
-    return matrix->xx == scale && matrix->yy == scale &&
-           matrix->xy == 0. && matrix->yx == 0. &&
-           matrix->x0 == 0. && matrix->y0 == 0.;
-}
-
-static cairo_status_t
-_cairo_win32_font_face_scaled_font_create (void			*abstract_face,
-					   const cairo_matrix_t	*font_matrix,
-					   const cairo_matrix_t	*ctm,
-					   const cairo_font_options_t *options,
-					   cairo_scaled_font_t **font)
-{
-    HFONT hfont = NULL;
-
-    cairo_win32_font_face_t *font_face = abstract_face;
-
-    if (font_face->hfont) {
-        /* Check whether it's OK to go ahead and use the font-face's HFONT. */
-        if (_is_scale (ctm, 1.) &&
-            _is_scale (font_matrix, -font_face->logfont.lfHeight)) {
-            hfont = font_face->hfont;
-        }
-    }
-
-    return _win32_scaled_font_create (&font_face->logfont,
-				      hfont,
-				      &font_face->base,
-				      font_matrix, ctm, options,
-				      font);
-}
-
-const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
-    CAIRO_FONT_TYPE_WIN32,
-    _cairo_win32_font_face_create_for_toy,
-    _cairo_win32_font_face_destroy,
-    _cairo_win32_font_face_scaled_font_create
-};
-
-/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
- * The primary purpose of this mapping is to provide unique
- * #cairo_font_face_t values so that our cache and mapping from
- * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
- * corresponding #cairo_font_face_t objects fall out of downstream
- * caches, we don't need them in this hash table anymore.
- *
- * Modifications to this hash table are protected by
- * _cairo_win32_font_face_mutex.
- */
-
-static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
-
-static int
-_cairo_win32_font_face_keys_equal (const void *key_a,
-				   const void *key_b);
-
-static void
-_cairo_win32_font_face_hash_table_destroy (void)
-{
-    cairo_hash_table_t *hash_table;
-
-    /* We manually acquire the lock rather than calling
-     * _cairo_win32_font_face_hash_table_lock simply to avoid creating
-     * the table only to destroy it again. */
-    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
-    hash_table = cairo_win32_font_face_hash_table;
-    cairo_win32_font_face_hash_table = NULL;
-    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
-
-    if (hash_table != NULL)
-	_cairo_hash_table_destroy (hash_table);
-}
-
-static cairo_hash_table_t *
-_cairo_win32_font_face_hash_table_lock (void)
-{
-    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
-
-    if (unlikely (cairo_win32_font_face_hash_table == NULL))
-    {
-	cairo_win32_font_face_hash_table =
-	_cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
-
-	if (unlikely (cairo_win32_font_face_hash_table == NULL)) {
-	    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	    return NULL;
-	}
-    }
-
-    return cairo_win32_font_face_hash_table;
-}
-
-static void
-_cairo_win32_font_face_hash_table_unlock (void)
-{
-    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
-}
-
-static void
-_cairo_win32_font_face_destroy (void *abstract_face)
-{
-    cairo_win32_font_face_t *font_face = abstract_face;
-    cairo_hash_table_t *hash_table;
-
-    hash_table = _cairo_win32_font_face_hash_table_lock ();
-    /* All created objects must have been mapped in the hash table. */
-    assert (hash_table != NULL);
-
-    if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
-	/* somebody recreated the font whilst we waited for the lock */
-	_cairo_win32_font_face_hash_table_unlock ();
-	return;
-    }
-
-    /* Font faces in SUCCESS status are guaranteed to be in the
-     * hashtable. Font faces in an error status are removed from the
-     * hashtable if they are found during a lookup, thus they should
-     * only be removed if they are in the hashtable. */
-    if (likely (font_face->base.status == CAIRO_STATUS_SUCCESS) ||
-	_cairo_hash_table_lookup (hash_table, &font_face->base.hash_entry) == font_face)
-	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
-
-    _cairo_win32_font_face_hash_table_unlock ();
-}
-
-static void
-_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
-				 LOGFONTW                *logfont,
-				 HFONT                    font)
-{
-    unsigned long hash = _CAIRO_HASH_INIT_VALUE;
-
-    key->logfont = *logfont;
-    key->hfont = font;
-
-    hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName));
-    hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight));
-    hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic));
-
-    key->base.hash_entry.hash = hash;
-}
-
-static int
-_cairo_win32_font_face_keys_equal (const void *key_a,
-				   const void *key_b)
-{
-    const cairo_win32_font_face_t *face_a = key_a;
-    const cairo_win32_font_face_t *face_b = key_b;
-
-    if (face_a->logfont.lfWeight         == face_b->logfont.lfWeight &&
-	face_a->logfont.lfItalic         == face_b->logfont.lfItalic &&
-	face_a->logfont.lfUnderline      == face_b->logfont.lfUnderline &&
-	face_a->logfont.lfStrikeOut      == face_b->logfont.lfStrikeOut &&
-	face_a->logfont.lfCharSet        == face_b->logfont.lfCharSet &&
-	face_a->logfont.lfOutPrecision   == face_b->logfont.lfOutPrecision &&
-	face_a->logfont.lfClipPrecision  == face_b->logfont.lfClipPrecision &&
-	face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily &&
-	(wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0))
-	return TRUE;
-    else
-	return FALSE;
-}
-
-/**
- * cairo_win32_font_face_create_for_logfontw_hfont:
- * @logfont: A #LOGFONTW structure specifying the font to use.
- *   If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement
- *   fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
- *   lfEscapement must be zero.
- * @font: An #HFONT that can be used when the font matrix is a scale by
- *   -lfHeight and the CTM is identity.
- *
- * Creates a new font for the Win32 font backend based on a
- * #LOGFONT. This font can then be used with
- * cairo_set_font_face() or cairo_scaled_font_create().
- * The #cairo_scaled_font_t
- * returned from cairo_scaled_font_create() is also for the Win32 backend
- * and can be used with functions such as cairo_win32_scaled_font_select_font().
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- *  cairo_font_face_destroy() when you are done using it.
- **/
-cairo_font_face_t *
-cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
-{
-    cairo_win32_font_face_t *font_face, key;
-    cairo_hash_table_t *hash_table;
-    cairo_status_t status;
-
-    hash_table = _cairo_win32_font_face_hash_table_lock ();
-    if (unlikely (hash_table == NULL)) {
-        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_font_face_t *)&_cairo_font_face_nil;
-    }
-
-    _cairo_win32_font_face_init_key (&key, logfont, font);
-
-    /* Return existing unscaled font if it exists in the hash table. */
-    font_face = _cairo_hash_table_lookup (hash_table,
-					 &key.base.hash_entry);
-    if (font_face != NULL) {
-	if (font_face->base.status == CAIRO_STATUS_SUCCESS) {
-	    cairo_font_face_reference (&font_face->base);
-	    _cairo_win32_font_face_hash_table_unlock ();
-	    return &font_face->base;
-	}
-
-	/* remove the bad font from the hash table */
-	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
-    }
-
-    /* Otherwise create it and insert into hash table. */
-    font_face = malloc (sizeof (cairo_win32_font_face_t));
-    if (!font_face) {
-        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL;
-    }
-
-    _cairo_win32_font_face_init_key (font_face, logfont, font);
-    _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
-
-    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
-    status = _cairo_hash_table_insert (hash_table,
-				       &font_face->base.hash_entry);
-    if (unlikely (status))
-	goto FAIL;
-
-    _cairo_win32_font_face_hash_table_unlock ();
-    return &font_face->base;
-
-FAIL:
-    _cairo_win32_font_face_hash_table_unlock ();
-    return (cairo_font_face_t *)&_cairo_font_face_nil;
-}
-
-/**
- * cairo_win32_font_face_create_for_logfontw:
- * @logfont: A #LOGFONTW structure specifying the font to use.
- *   The lfHeight, lfWidth, lfOrientation and lfEscapement
- *   fields of this structure are ignored.
- *
- * Creates a new font for the Win32 font backend based on a
- * #LOGFONT. This font can then be used with
- * cairo_set_font_face() or cairo_scaled_font_create().
- * The #cairo_scaled_font_t
- * returned from cairo_scaled_font_create() is also for the Win32 backend
- * and can be used with functions such as cairo_win32_scaled_font_select_font().
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- *  cairo_font_face_destroy() when you are done using it.
- **/
-cairo_font_face_t *
-cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
-{
-    return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
-}
-
-/**
- * cairo_win32_font_face_create_for_hfont:
- * @font: An #HFONT structure specifying the font to use.
- *
- * Creates a new font for the Win32 font backend based on a
- * #HFONT. This font can then be used with
- * cairo_set_font_face() or cairo_scaled_font_create().
- * The #cairo_scaled_font_t
- * returned from cairo_scaled_font_create() is also for the Win32 backend
- * and can be used with functions such as cairo_win32_scaled_font_select_font().
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- *  cairo_font_face_destroy() when you are done using it.
- **/
-cairo_font_face_t *
-cairo_win32_font_face_create_for_hfont (HFONT font)
-{
-    LOGFONTW logfont;
-    GetObjectW (font, sizeof(logfont), &logfont);
-
-    if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
-        logfont.lfWidth != 0) {
-        /* We can't use this font because that optimization requires that
-         * lfEscapement, lfOrientation and lfWidth be zero. */
-        font = NULL;
-    }
-
-    return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
-}
-
-static cairo_bool_t
-_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
-{
-    return scaled_font->backend == &_cairo_win32_scaled_font_backend;
-}
-
-/**
- * cairo_win32_scaled_font_select_font:
- * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an
- *   object can be created with cairo_win32_scaled_font_create_for_logfontw().
- * @hdc: a device context
- *
- * Selects the font into the given device context and changes the
- * map mode and world transformation of the device context to match
- * that of the font. This function is intended for use when using
- * layout APIs such as Uniscribe to do text layout with the
- * cairo font. After finishing using the device context, you must call
- * cairo_win32_scaled_font_done_font() to release any resources allocated
- * by this function.
- *
- * See cairo_win32_scaled_font_get_metrics_factor() for converting logical
- * coordinates from the device context to font space.
- *
- * Normally, calls to SaveDC() and RestoreDC() would be made around
- * the use of this function to preserve the original graphics state.
- *
- * Return value: %CAIRO_STATUS_SUCCESS if the operation succeeded.
- *   otherwise an error such as %CAIRO_STATUS_NO_MEMORY and
- *   the device context is unchanged.
- **/
-cairo_status_t
-cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
-				     HDC                  hdc)
-{
-    cairo_status_t status;
-    HFONT hfont;
-    HFONT old_hfont = NULL;
-    int old_mode;
-
-    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
-	return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
-    }
-
-    if (scaled_font->status)
-	return scaled_font->status;
-
-    status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont);
-    if (status)
-	return status;
-
-    old_hfont = SelectObject (hdc, hfont);
-    if (!old_hfont)
-	return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
-
-    old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
-    if (!old_mode) {
-	status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
-	SelectObject (hdc, old_hfont);
-	return status;
-    }
-
-    status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc);
-    if (status) {
-	SetGraphicsMode (hdc, old_mode);
-	SelectObject (hdc, old_hfont);
-	return status;
-    }
-
-    SetMapMode (hdc, MM_TEXT);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/**
- * cairo_win32_scaled_font_done_font:
- * @scaled_font: A scaled font from the Win32 font backend.
- *
- * Releases any resources allocated by cairo_win32_scaled_font_select_font()
- **/
-void
-cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
-{
-    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
-	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
-    }
-}
-
-/**
- * cairo_win32_scaled_font_get_metrics_factor:
- * @scaled_font: a scaled font from the Win32 font backend
- *
- * Gets a scale factor between logical coordinates in the coordinate
- * space used by cairo_win32_scaled_font_select_font() (that is, the
- * coordinate system used by the Windows functions to return metrics) and
- * font space coordinates.
- *
- * Return value: factor to multiply logical units by to get font space
- *               coordinates.
- **/
-double
-cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
-{
-    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
-	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
-	return 1.;
-    }
-    return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
-}
-
-/**
- * cairo_win32_scaled_font_get_logical_to_device:
- * @scaled_font: a scaled font from the Win32 font backend
- * @logical_to_device: matrix to return
- *
- * Gets the transformation mapping the logical space used by @scaled_font
- * to device space.
- *
- * Since: 1.4
- **/
-void
-cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
-					       cairo_matrix_t *logical_to_device)
-{
-    cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
-    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
-	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
-	cairo_matrix_init_identity (logical_to_device);
-	return;
-    }
-    *logical_to_device = win_font->logical_to_device;
-}
-
-/**
- * cairo_win32_scaled_font_get_device_to_logical:
- * @scaled_font: a scaled font from the Win32 font backend
- * @device_to_logical: matrix to return
- *
- * Gets the transformation mapping device space to the logical space
- * used by @scaled_font.
- *
- * Since: 1.4
- **/
-void
-cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
-					       cairo_matrix_t *device_to_logical)
-{
-    cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
-    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
-	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
-	cairo_matrix_init_identity (device_to_logical);
-	return;
-    }
-    *device_to_logical = win_font->device_to_logical;
-}
-
-void
-_cairo_win32_font_reset_static_data (void)
-{
-    _cairo_win32_font_face_hash_table_destroy ();
-}
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
deleted file mode 100644
index 17a68f7..0000000
--- a/src/cairo-win32-printing-surface.c
+++ /dev/null
@@ -1,1915 +0,0 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2007, 2008 Adrian Johnson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Adrian Johnson.
- *
- * Contributor(s):
- *      Adrian Johnson <ajohnson at redneon.com>
- *      Vladimir Vukicevic <vladimir at pobox.com>
- */
-
-#define WIN32_LEAN_AND_MEAN
-/* We require Windows 2000 features such as ETO_PDY */
-#if !defined(WINVER) || (WINVER < 0x0500)
-# define WINVER 0x0500
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-# define _WIN32_WINNT 0x0500
-#endif
-
-#include "cairoint.h"
-
-#include "cairo-default-context-private.h"
-#include "cairo-error-private.h"
-#include "cairo-paginated-private.h"
-
-#include "cairo-clip-private.h"
-#include "cairo-win32-private.h"
-#include "cairo-recording-surface-private.h"
-#include "cairo-scaled-font-subsets-private.h"
-#include "cairo-image-info-private.h"
-#include "cairo-image-surface-private.h"
-#include "cairo-surface-backend-private.h"
-#include "cairo-surface-clipper-private.h"
-
-#include <windows.h>
-
-#if !defined(POSTSCRIPT_IDENTIFY)
-# define POSTSCRIPT_IDENTIFY 0x1015
-#endif
-
-#if !defined(PSIDENT_GDICENTRIC)
-# define PSIDENT_GDICENTRIC 0x0000
-#endif
-
-#if !defined(GET_PS_FEATURESETTING)
-# define GET_PS_FEATURESETTING 0x1019
-#endif
-
-#if !defined(FEATURESETTING_PSLEVEL)
-# define FEATURESETTING_PSLEVEL 0x0002
-#endif
-
-#if !defined(GRADIENT_FILL_RECT_H)
-# define GRADIENT_FILL_RECT_H 0x00
-#endif
-
-#if !defined(CHECKJPEGFORMAT)
-# define CHECKJPEGFORMAT 0x1017
-#endif
-
-#if !defined(CHECKPNGFORMAT)
-# define CHECKPNGFORMAT 0x1018
-#endif
-
-#define PELS_72DPI  ((LONG)(72. / 0.0254))
-
-static const char *_cairo_win32_printing_supported_mime_types[] =
-{
-    CAIRO_MIME_TYPE_JPEG,
-    CAIRO_MIME_TYPE_PNG,
-    NULL
-};
-
-static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
-static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend;
-
-static void
-_cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface)
-{
-    DWORD word;
-    INT ps_feature, ps_level;
-
-    word = PSIDENT_GDICENTRIC;
-    if (ExtEscape (surface->dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0)
-	return;
-
-    ps_feature = FEATURESETTING_PSLEVEL;
-    if (ExtEscape (surface->dc, GET_PS_FEATURESETTING, sizeof(INT),
-		   (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0)
-	return;
-
-    if (ps_level >= 3)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
-}
-
-static void
-_cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface)
-{
-    DWORD word;
-
-    word = CHECKJPEGFORMAT;
-    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
-
-    word = CHECKPNGFORMAT;
-    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
-	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG;
-}
-
-/* When creating an EMF file, ExtTextOut with ETO_GLYPH_INDEX does not
- * work unless the GDI function GdiInitializeLanguagePack() has been
- * called.
- *
- *   http://m-a-tech.blogspot.com/2009/04/emf-buffer-idiocracy.html
- *
- * The only information I could find on the how to use this
- * undocumented function is the use in:
- *
- * http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/render_process.cc?view=markup
- *
- * to solve the same problem. The above code first checks if LPK.DLL
- * is already loaded. If it is not it calls
- * GdiInitializeLanguagePack() using the prototype
- *   BOOL GdiInitializeLanguagePack (int)
- * and argument 0.
- */
-static void
-_cairo_win32_printing_surface_init_language_pack (cairo_win32_surface_t *surface)
-{
-    typedef BOOL (WINAPI *gdi_init_lang_pack_func_t)(int);
-    gdi_init_lang_pack_func_t gdi_init_lang_pack;
-    HMODULE module;
-
-    if (GetModuleHandleW (L"LPK.DLL"))
-	return;
-
-    module = GetModuleHandleW (L"GDI32.DLL");
-    if (module) {
-	gdi_init_lang_pack = (gdi_init_lang_pack_func_t)
-	    GetProcAddress (module, "GdiInitializeLanguagePack");
-	if (gdi_init_lang_pack)
-	    gdi_init_lang_pack (0);
-    }
-}
-
-static cairo_int_status_t
-analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern)
-{
-    cairo_image_surface_t  *image;
-    void		   *image_extra;
-    cairo_int_status_t      status;
-    cairo_image_transparency_t transparency;
-
-    status = _cairo_surface_acquire_source_image (pattern->surface,
-						  &image,
-						  &image_extra);
-    if (status)
-	return status;
-
-    transparency = _cairo_image_analyze_transparency (image);
-    switch (transparency) {
-    case CAIRO_IMAGE_UNKNOWN:
-	ASSERT_NOT_REACHED;
-    case CAIRO_IMAGE_IS_OPAQUE:
-	status = CAIRO_STATUS_SUCCESS;
-	break;
-
-    case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
-    case CAIRO_IMAGE_HAS_ALPHA:
-	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
-	break;
-    }
-
-    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
-
-    return status;
-}
-
-static cairo_bool_t
-surface_pattern_supported (const cairo_surface_pattern_t *pattern)
-{
-    if (_cairo_surface_is_recording (pattern->surface))
-	return TRUE;
-
-    if (cairo_surface_get_type (pattern->surface) != CAIRO_SURFACE_TYPE_WIN32 &&
-	pattern->surface->backend->acquire_source_image == NULL)
-    {
-	return FALSE;
-    }
-
-    return TRUE;
-}
-
-static cairo_bool_t
-pattern_supported (cairo_win32_surface_t *surface, const cairo_pattern_t *pattern)
-{
-    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
-	return TRUE;
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
-	return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
-	return surface->flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
-
-    return FALSE;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface,
-                                                 cairo_operator_t       op,
-                                                 const cairo_pattern_t *pattern)
-{
-    if (! pattern_supported (surface, pattern))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (!(op == CAIRO_OPERATOR_SOURCE ||
-	  op == CAIRO_OPERATOR_OVER ||
-	  op == CAIRO_OPERATOR_CLEAR))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
-
-	if ( _cairo_surface_is_recording (surface_pattern->surface))
-	    return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
-    }
-
-    if (op == CAIRO_OPERATOR_SOURCE ||
-	op == CAIRO_OPERATOR_CLEAR)
-	return CAIRO_STATUS_SUCCESS;
-
-    /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
-     * the pattern contains transparency, we return
-     * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
-     * surface. If the analysis surface determines that there is
-     * anything drawn under this operation, a fallback image will be
-     * used. Otherwise the operation will be replayed during the
-     * render stage and we blend the transarency into the white
-     * background to convert the pattern to opaque.
-     */
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
-
-	return analyze_surface_pattern_transparency (surface_pattern);
-    }
-
-    if (_cairo_pattern_is_opaque (pattern, NULL))
-	return CAIRO_STATUS_SUCCESS;
-    else
-	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
-}
-
-static cairo_bool_t
-_cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surface,
-                                                   cairo_operator_t       op,
-                                                   const cairo_pattern_t *pattern)
-{
-    if (_cairo_win32_printing_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
-	return TRUE;
-    else
-	return FALSE;
-}
-
-static void
-_cairo_win32_printing_surface_init_clear_color (cairo_win32_surface_t *surface,
-						cairo_solid_pattern_t *color)
-{
-    if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
-	_cairo_pattern_init_solid (color, CAIRO_COLOR_WHITE);
-    else
-	_cairo_pattern_init_solid (color, CAIRO_COLOR_BLACK);
-}
-
-static COLORREF
-_cairo_win32_printing_surface_flatten_transparency (cairo_win32_surface_t *surface,
-						    const cairo_color_t   *color)
-{
-    COLORREF c;
-    BYTE red, green, blue;
-
-    red   = color->red_short   >> 8;
-    green = color->green_short >> 8;
-    blue  = color->blue_short  >> 8;
-
-    if (!CAIRO_COLOR_IS_OPAQUE(color)) {
-	if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
-	    /* Blend into white */
-	    uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
-
-	    red   = (color->red_short   >> 8) + one_minus_alpha;
-	    green = (color->green_short >> 8) + one_minus_alpha;
-	    blue  = (color->blue_short  >> 8) + one_minus_alpha;
-	} else {
-	    /* Blend into black */
-	    red   = (color->red_short   >> 8);
-	    green = (color->green_short >> 8);
-	    blue  = (color->blue_short  >> 8);
-	}
-    }
-    c = RGB (red, green, blue);
-
-    return c;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface,
-                                                  const cairo_pattern_t *source)
-{
-    cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source;
-    COLORREF color;
-
-    color = _cairo_win32_printing_surface_flatten_transparency (surface,
-								&pattern->color);
-    surface->brush = CreateSolidBrush (color);
-    if (!surface->brush)
-	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)");
-    surface->old_brush = SelectObject (surface->dc, surface->brush);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_win32_printing_surface_done_solid_brush (cairo_win32_surface_t *surface)
-{
-    if (surface->old_brush) {
-	SelectObject (surface->dc, surface->old_brush);
-	DeleteObject (surface->brush);
-	surface->old_brush = NULL;
-    }
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface,
-						RECT                  *clip)
-{
-    XFORM xform;
-
-    _cairo_matrix_to_win32_xform (&surface->ctm, &xform);
-    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
-	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform");
-    GetClipBox (surface->dc, clip);
-
-    _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
-    if (!SetWorldTransform (surface->dc, &xform))
-	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface,
-                                                   const cairo_pattern_t *pattern)
-{
-    RECT clip;
-    cairo_status_t status;
-
-    GetClipBox (surface->dc, &clip);
-    status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern);
-    if (status)
-	return status;
-
-    FillRect (surface->dc, &clip, surface->brush);
-    _cairo_win32_printing_surface_done_solid_brush (surface);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *surface,
-						       cairo_surface_pattern_t *pattern)
-{
-    cairo_content_t old_content;
-    cairo_matrix_t old_ctm;
-    cairo_bool_t old_has_ctm;
-    cairo_rectangle_int_t recording_extents;
-    cairo_status_t status;
-    cairo_extend_t extend;
-    cairo_matrix_t p2d;
-    XFORM xform;
-    int x_tile, y_tile, left, right, top, bottom;
-    RECT clip;
-    cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) pattern->surface;
-    cairo_box_t bbox;
-
-    extend = cairo_pattern_get_extend (&pattern->base);
-
-    p2d = pattern->base.matrix;
-    status = cairo_matrix_invert (&p2d);
-    /* _cairo_pattern_set_matrix guarantees invertibility */
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    old_ctm = surface->ctm;
-    old_has_ctm = surface->has_ctm;
-    cairo_matrix_multiply (&p2d, &p2d, &surface->ctm);
-    surface->ctm = p2d;
-    SaveDC (surface->dc);
-    _cairo_matrix_to_win32_xform (&p2d, &xform);
-
-    status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
-    if (status)
-	return status;
-
-    _cairo_box_round_to_rectangle (&bbox, &recording_extents);
-
-    status = _cairo_win32_printing_surface_get_ctm_clip_box (surface, &clip);
-    if (status)
-	return status;
-
-    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
-	left = floor (clip.left / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
-	right = ceil (clip.right / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
-	top = floor (clip.top / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
-	bottom = ceil (clip.bottom / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
-    } else {
-	left = 0;
-	right = 1;
-	top = 0;
-	bottom = 1;
-    }
-
-    old_content = surface->content;
-    if (recording_surface->base.content == CAIRO_CONTENT_COLOR) {
-	surface->content = CAIRO_CONTENT_COLOR;
-	status = _cairo_win32_printing_surface_paint_solid_pattern (surface,
-								    &_cairo_pattern_black.base);
-	if (status)
-	    return status;
-    }
-
-    for (y_tile = top; y_tile < bottom; y_tile++) {
-	for (x_tile = left; x_tile < right; x_tile++) {
-	    cairo_matrix_t m;
-	    double x, y;
-
-	    SaveDC (surface->dc);
-	    m = p2d;
-	    cairo_matrix_translate (&m,
-				    x_tile*recording_extents.width,
-				    y_tile*recording_extents.height);
-	    if (extend == CAIRO_EXTEND_REFLECT) {
-		if (x_tile % 2) {
-		    cairo_matrix_translate (&m, recording_extents.width, 0);
-		    cairo_matrix_scale (&m, -1, 1);
-		}
-		if (y_tile % 2) {
-		    cairo_matrix_translate (&m, 0, recording_extents.height);
-		    cairo_matrix_scale (&m, 1, -1);
-		}
-	    }
-	    surface->ctm = m;
-	    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
-
-	    /* Set clip path around bbox of the pattern. */
-	    BeginPath (surface->dc);
-
-	    x = 0;
-	    y = 0;
-	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    MoveToEx (surface->dc, (int) x, (int) y, NULL);
-
-	    x = recording_extents.width;
-	    y = 0;
-	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
-
-	    x = recording_extents.width;
-	    y = recording_extents.height;
-	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
-
-	    x = 0;
-	    y = recording_extents.height;
-	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
-	    LineTo (surface->dc, (int) x, (int) y);
-
-	    CloseFigure (surface->dc);
-	    EndPath (surface->dc);
-	    SelectClipPath (surface->dc, RGN_AND);
-
-	    SaveDC (surface->dc); /* Allow clip path to be reset during replay */
-	    status = _cairo_recording_surface_replay_region (&recording_surface->base, NULL,
-							     &surface->base,
-							     CAIRO_RECORDING_REGION_NATIVE);
-	    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
-	    /* Restore both the clip save and our earlier path SaveDC */
-	    RestoreDC (surface->dc, -2);
-
-	    if (status)
-		return status;
-	}
-    }
-
-    surface->content = old_content;
-    surface->ctm = old_ctm;
-    surface->has_ctm = old_has_ctm;
-    RestoreDC (surface->dc, -1);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
-					  cairo_surface_t         *source,
-					  const unsigned char    **data,
-					  unsigned long           *length,
-					  cairo_image_info_t      *info)
-{
-    const unsigned char *mime_data;
-    unsigned long mime_data_length;
-    cairo_int_status_t status;
-    DWORD result;
-
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
-				 &mime_data, &mime_data_length);
-    if (mime_data == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_image_info_get_jpeg_info (info, mime_data, mime_data_length);
-    if (status)
-	return status;
-
-    result = 0;
-    if (ExtEscape(surface->dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data,
-		  sizeof(result), (char *) &result) <= 0)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (result != 1)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    *data = mime_data;
-    *length = mime_data_length;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
-					 cairo_surface_t         *source,
-					 const unsigned char    **data,
-					 unsigned long           *length,
-					 cairo_image_info_t      *info)
-{
-    const unsigned char *mime_data;
-    unsigned long mime_data_length;
-
-    cairo_int_status_t status;
-    DWORD result;
-
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_PNG,
-				 &mime_data, &mime_data_length);
-    if (mime_data == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_image_info_get_png_info (info, mime_data, mime_data_length);
-    if (status)
-	return status;
-
-    result = 0;
-    if (ExtEscape(surface->dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data,
-		  sizeof(result), (char *) &result) <= 0)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (result != 1)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    *data = mime_data;
-    *length = mime_data_length;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surface,
-						   cairo_surface_pattern_t *pattern)
-{
-    cairo_status_t status;
-    cairo_extend_t extend;
-    cairo_image_surface_t *image;
-    void *image_extra;
-    cairo_image_surface_t *opaque_image = NULL;
-    BITMAPINFO bi;
-    cairo_matrix_t m;
-    int oldmode;
-    XFORM xform;
-    int x_tile, y_tile, left, right, top, bottom;
-    RECT clip;
-    const cairo_color_t *background_color;
-    const unsigned char *mime_data;
-    unsigned long mime_size;
-    cairo_image_info_t mime_info;
-    cairo_bool_t use_mime;
-    DWORD mime_type;
-
-    /* If we can't use StretchDIBits with this surface, we can't do anything
-     * here.
-     */
-    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
-	background_color = CAIRO_COLOR_WHITE;
-    else
-	background_color = CAIRO_COLOR_BLACK;
-
-    extend = cairo_pattern_get_extend (&pattern->base);
-
-    status = _cairo_surface_acquire_source_image (pattern->surface,
-						  &image, &image_extra);
-    if (status)
-	return status;
-
-    if (image->base.status) {
-	status = image->base.status;
-	goto CLEANUP_IMAGE;
-    }
-
-    if (image->width == 0 || image->height == 0) {
-	status = CAIRO_STATUS_SUCCESS;
-	goto CLEANUP_IMAGE;
-    }
-
-    mime_type = BI_JPEG;
-    status = _cairo_win32_printing_surface_check_jpeg (surface,
-						       pattern->surface,
-						       &mime_data,
-						       &mime_size,
-						       &mime_info);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	mime_type = BI_PNG;
-	status = _cairo_win32_printing_surface_check_png (surface,
-							  pattern->surface,
-							  &mime_data,
-							  &mime_size,
-							  &mime_info);
-    }
-    if (_cairo_status_is_error (status))
-	return status;
-
-    use_mime = (status == CAIRO_STATUS_SUCCESS);
-
-    if (!use_mime && image->format != CAIRO_FORMAT_RGB24) {
-	cairo_surface_t *opaque_surface;
-	cairo_surface_pattern_t image_pattern;
-	cairo_solid_pattern_t background_pattern;
-
-	opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
-						     image->width,
-						     image->height);
-	if (opaque_surface->status) {
-	    status = opaque_surface->status;
-	    goto CLEANUP_OPAQUE_IMAGE;
-	}
-
-	_cairo_pattern_init_solid (&background_pattern,
-				   background_color);
-	status = _cairo_surface_paint (opaque_surface,
-				       CAIRO_OPERATOR_SOURCE,
-				       &background_pattern.base,
-				       NULL);
-	if (status)
-	    goto CLEANUP_OPAQUE_IMAGE;
-
-	_cairo_pattern_init_for_surface (&image_pattern, &image->base);
-	status = _cairo_surface_paint (opaque_surface,
-				       CAIRO_OPERATOR_OVER,
-				       &image_pattern.base,
-				       NULL);
-	_cairo_pattern_fini (&image_pattern.base);
-	if (status)
-	    goto CLEANUP_OPAQUE_IMAGE;
-
-	opaque_image = (cairo_image_surface_t *) opaque_surface;
-    } else {
-	opaque_image = image;
-    }
-
-    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    bi.bmiHeader.biWidth = use_mime ? mime_info.width : opaque_image->width;
-    bi.bmiHeader.biHeight = use_mime ? - mime_info.height : -opaque_image->height;
-    bi.bmiHeader.biSizeImage = use_mime ? mime_size : 0;
-    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
-    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
-    bi.bmiHeader.biPlanes = 1;
-    bi.bmiHeader.biBitCount = 32;
-    bi.bmiHeader.biCompression = use_mime ? mime_type : BI_RGB;
-    bi.bmiHeader.biClrUsed = 0;
-    bi.bmiHeader.biClrImportant = 0;
-
-    m = pattern->base.matrix;
-    status = cairo_matrix_invert (&m);
-    /* _cairo_pattern_set_matrix guarantees invertibility */
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    cairo_matrix_multiply (&m, &m, &surface->gdi_ctm);
-    SaveDC (surface->dc);
-    _cairo_matrix_to_win32_xform (&m, &xform);
-
-    if (! SetWorldTransform (surface->dc, &xform)) {
-	status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern");
-	goto CLEANUP_OPAQUE_IMAGE;
-    }
-
-    oldmode = SetStretchBltMode(surface->dc, HALFTONE);
-
-    GetClipBox (surface->dc, &clip);
-    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
-	left = floor ( clip.left / (double) opaque_image->width);
-	right = ceil (clip.right / (double) opaque_image->width);
-	top = floor (clip.top / (double) opaque_image->height);
-	bottom = ceil (clip.bottom / (double) opaque_image->height);
-    } else {
-	left = 0;
-	right = 1;
-	top = 0;
-	bottom = 1;
-    }
-
-    for (y_tile = top; y_tile < bottom; y_tile++) {
-	for (x_tile = left; x_tile < right; x_tile++) {
-	    if (!StretchDIBits (surface->dc,
-				x_tile*opaque_image->width,
-				y_tile*opaque_image->height,
-				opaque_image->width,
-				opaque_image->height,
-				0,
-				0,
-				use_mime ? mime_info.width : opaque_image->width,
-				use_mime ? mime_info.height : opaque_image->height,
-				use_mime ? mime_data : opaque_image->data,
-				&bi,
-				DIB_RGB_COLORS,
-				SRCCOPY))
-	    {
-		status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
-		goto CLEANUP_OPAQUE_IMAGE;
-	    }
-	}
-    }
-    SetStretchBltMode(surface->dc, oldmode);
-    RestoreDC (surface->dc, -1);
-
-CLEANUP_OPAQUE_IMAGE:
-    if (opaque_image != image)
-	cairo_surface_destroy (&opaque_image->base);
-CLEANUP_IMAGE:
-    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
-
-    return status;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t   *surface,
-                                                     cairo_surface_pattern_t *pattern)
-{
-    if (_cairo_surface_is_recording (pattern->surface)) {
-	return _cairo_win32_printing_surface_paint_recording_pattern (surface,
-								      pattern);
-    } else {
-	return _cairo_win32_printing_surface_paint_image_pattern (surface,
-								  pattern);
-    }
-}
-
-static void
-vertex_set_color (TRIVERTEX *vert, cairo_color_stop_t *color)
-{
-    /* MSDN says that the range here is 0x0000 .. 0xff00;
-     * that may well be a typo, but just chop the low bits
-     * here. */
-    vert->Alpha = 0xff00;
-    vert->Red   = color->red_short & 0xff00;
-    vert->Green = color->green_short & 0xff00;
-    vert->Blue  = color->blue_short & 0xff00;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surface,
-                                                    cairo_linear_pattern_t *pattern)
-{
-    TRIVERTEX *vert;
-    GRADIENT_RECT *rect;
-    RECT clip;
-    XFORM xform;
-    int i, num_stops;
-    cairo_matrix_t mat, rot;
-    double p1x, p1y, p2x, p2y, xd, yd, d, sn, cs;
-    cairo_extend_t extend;
-    int range_start, range_stop, num_ranges, num_rects, stop;
-    int total_verts, total_rects;
-    cairo_status_t status;
-
-    extend = cairo_pattern_get_extend (&pattern->base.base);
-    SaveDC (surface->dc);
-
-    mat = pattern->base.base.matrix;
-    status = cairo_matrix_invert (&mat);
-    /* _cairo_pattern_set_matrix guarantees invertibility */
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    cairo_matrix_multiply (&mat, &surface->ctm, &mat);
-
-    p1x = pattern->pd1.x;
-    p1y = pattern->pd1.y;
-    p2x = pattern->pd2.x;
-    p2y = pattern->pd2.y;
-    cairo_matrix_translate (&mat, p1x, p1y);
-
-    xd = p2x - p1x;
-    yd = p2y - p1y;
-    d = sqrt (xd*xd + yd*yd);
-    sn = yd/d;
-    cs = xd/d;
-    cairo_matrix_init (&rot,
-		       cs, sn,
-		       -sn, cs,
-		        0, 0);
-    cairo_matrix_multiply (&mat, &rot, &mat);
-
-    _cairo_matrix_to_win32_xform (&mat, &xform);
-
-    if (!SetWorldTransform (surface->dc, &xform))
-	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2");
-
-    GetClipBox (surface->dc, &clip);
-
-    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
-	range_start = floor (clip.left / d);
-	range_stop = ceil (clip.right / d);
-    } else {
-	range_start = 0;
-	range_stop = 1;
-    }
-    num_ranges = range_stop - range_start;
-    num_stops = pattern->base.n_stops;
-    num_rects = num_stops - 1;
-
-    /* Add an extra four points and two rectangles for EXTEND_PAD */
-    vert = malloc (sizeof (TRIVERTEX) * (num_rects*2*num_ranges + 4));
-    rect = malloc (sizeof (GRADIENT_RECT) * (num_rects*num_ranges + 2));
-
-    for (i = 0; i < num_ranges*num_rects; i++) {
-	vert[i*2].y = (LONG) clip.top;
-	if (i%num_rects == 0) {
-	    stop = 0;
-	    if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
-		stop = num_rects;
-	    vert[i*2].x = (LONG)(d*(range_start + i/num_rects));
-	    vertex_set_color (&vert[i*2], &pattern->base.stops[stop].color);
-	} else {
-	    vert[i*2].x = vert[i*2-1].x;
-	    vert[i*2].Red = vert[i*2-1].Red;
-	    vert[i*2].Green = vert[i*2-1].Green;
-	    vert[i*2].Blue = vert[i*2-1].Blue;
-	    vert[i*2].Alpha = vert[i*2-1].Alpha;
-	}
-
-	stop = i%num_rects + 1;
-	vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset));
-	vert[i*2+1].y = (LONG) clip.bottom;
-	if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
-	    stop = num_rects - stop;
-	vertex_set_color (&vert[i*2+1], &pattern->base.stops[stop].color);
-
-	rect[i].UpperLeft = i*2;
-	rect[i].LowerRight = i*2 + 1;
-    }
-    total_verts = 2*num_ranges*num_rects;
-    total_rects = num_ranges*num_rects;
-
-    if (extend == CAIRO_EXTEND_PAD) {
-	vert[i*2].x = vert[i*2-1].x;
-	vert[i*2].y = (LONG) clip.top;
-	vert[i*2].Red = vert[i*2-1].Red;
-	vert[i*2].Green = vert[i*2-1].Green;
-	vert[i*2].Blue = vert[i*2-1].Blue;
-	vert[i*2].Alpha = 0xff00;
-	vert[i*2+1].x = clip.right;
-	vert[i*2+1].y = (LONG) clip.bottom;
-	vert[i*2+1].Red = vert[i*2-1].Red;
-	vert[i*2+1].Green = vert[i*2-1].Green;
-	vert[i*2+1].Blue = vert[i*2-1].Blue;
-	vert[i*2+1].Alpha = 0xff00;
-	rect[i].UpperLeft = i*2;
-	rect[i].LowerRight = i*2 + 1;
-
-	i++;
-
-	vert[i*2].x = clip.left;
-	vert[i*2].y = (LONG) clip.top;
-	vert[i*2].Red = vert[0].Red;
-	vert[i*2].Green = vert[0].Green;
-	vert[i*2].Blue = vert[0].Blue;
-	vert[i*2].Alpha = 0xff00;
-	vert[i*2+1].x = vert[0].x;
-	vert[i*2+1].y = (LONG) clip.bottom;
-	vert[i*2+1].Red = vert[0].Red;
-	vert[i*2+1].Green = vert[0].Green;
-	vert[i*2+1].Blue = vert[0].Blue;
-	vert[i*2+1].Alpha = 0xff00;
-	rect[i].UpperLeft = i*2;
-	rect[i].LowerRight = i*2 + 1;
-
-	total_verts += 4;
-	total_rects += 2;
-    }
-
-    if (!GradientFill (surface->dc,
-		       vert, total_verts,
-		       rect, total_rects,
-		       GRADIENT_FILL_RECT_H))
-	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill");
-
-    free (rect);
-    free (vert);
-    RestoreDC (surface->dc, -1);
-
-    return 0;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
-                                             const cairo_pattern_t *pattern)
-{
-    cairo_status_t status;
-
-    switch (pattern->type) {
-    case CAIRO_PATTERN_TYPE_SOLID:
-	status = _cairo_win32_printing_surface_paint_solid_pattern (surface, pattern);
-	if (status)
-	    return status;
-	break;
-
-    case CAIRO_PATTERN_TYPE_SURFACE:
-	status = _cairo_win32_printing_surface_paint_surface_pattern (surface,
-                                                                      (cairo_surface_pattern_t *) pattern);
-	if (status)
-	    return status;
-	break;
-
-    case CAIRO_PATTERN_TYPE_LINEAR:
-	status = _cairo_win32_printing_surface_paint_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
-	if (status)
-	    return status;
-	break;
-
-    case CAIRO_PATTERN_TYPE_RADIAL:
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-	break;
-
-    case CAIRO_PATTERN_TYPE_MESH:
-	ASSERT_NOT_REACHED;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-typedef struct _win32_print_path_info {
-    cairo_win32_surface_t *surface;
-} win32_path_info_t;
-
-static cairo_status_t
-_cairo_win32_printing_surface_path_move_to (void *closure,
-					    const cairo_point_t *point)
-{
-    win32_path_info_t *path_info = closure;
-
-    if (path_info->surface->has_ctm) {
-	double x, y;
-
-	x = _cairo_fixed_to_double (point->x);
-	y = _cairo_fixed_to_double (point->y);
-	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	MoveToEx (path_info->surface->dc, (int) x, (int) y, NULL);
-    } else {
-	MoveToEx (path_info->surface->dc,
-		  _cairo_fixed_integer_part (point->x),
-		  _cairo_fixed_integer_part (point->y),
-		  NULL);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_path_line_to (void *closure,
-					    const cairo_point_t *point)
-{
-    win32_path_info_t *path_info = closure;
-
-    path_info->surface->path_empty = FALSE;
-    if (path_info->surface->has_ctm) {
-	double x, y;
-
-	x = _cairo_fixed_to_double (point->x);
-	y = _cairo_fixed_to_double (point->y);
-	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	LineTo (path_info->surface->dc, (int) x, (int) y);
-    } else {
-	LineTo (path_info->surface->dc,
-		_cairo_fixed_integer_part (point->x),
-		_cairo_fixed_integer_part (point->y));
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_path_curve_to (void          *closure,
-                                             const cairo_point_t *b,
-                                             const cairo_point_t *c,
-                                             const cairo_point_t *d)
-{
-    win32_path_info_t *path_info = closure;
-    POINT points[3];
-
-    path_info->surface->path_empty = FALSE;
-    if (path_info->surface->has_ctm) {
-	double x, y;
-
-	x = _cairo_fixed_to_double (b->x);
-	y = _cairo_fixed_to_double (b->y);
-	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	points[0].x = (LONG) x;
-	points[0].y = (LONG) y;
-
-	x = _cairo_fixed_to_double (c->x);
-	y = _cairo_fixed_to_double (c->y);
-	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	points[1].x = (LONG) x;
-	points[1].y = (LONG) y;
-
-	x = _cairo_fixed_to_double (d->x);
-	y = _cairo_fixed_to_double (d->y);
-	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
-	points[2].x = (LONG) x;
-	points[2].y = (LONG) y;
-    } else {
-	points[0].x = _cairo_fixed_integer_part (b->x);
-	points[0].y = _cairo_fixed_integer_part (b->y);
-	points[1].x = _cairo_fixed_integer_part (c->x);
-	points[1].y = _cairo_fixed_integer_part (c->y);
-	points[2].x = _cairo_fixed_integer_part (d->x);
-	points[2].y = _cairo_fixed_integer_part (d->y);
-    }
-    PolyBezierTo (path_info->surface->dc, points, 3);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_path_close_path (void *closure)
-{
-    win32_path_info_t *path_info = closure;
-
-    CloseFigure (path_info->surface->dc);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_emit_path (cairo_win32_surface_t    *surface,
-					 const cairo_path_fixed_t *path)
-{
-    win32_path_info_t path_info;
-
-    path_info.surface = surface;
-    return _cairo_path_fixed_interpret (path,
-					_cairo_win32_printing_surface_path_move_to,
-					_cairo_win32_printing_surface_path_line_to,
-					_cairo_win32_printing_surface_path_curve_to,
-					_cairo_win32_printing_surface_path_close_path,
-					&path_info);
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_show_page (void *abstract_surface)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    /* Undo both SaveDC's that we did in start_page */
-    RestoreDC (surface->dc, -2);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
-                                                   cairo_path_fixed_t *path,
-                                                   cairo_fill_rule_t   fill_rule,
-                                                   double	       tolerance,
-                                                   cairo_antialias_t   antialias)
-{
-    cairo_win32_surface_t *surface = cairo_container_of (clipper,
-							 cairo_win32_surface_t,
-							 clipper);
-    cairo_status_t status;
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (path == NULL) {
-	RestoreDC (surface->dc, -1);
-	SaveDC (surface->dc);
-
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    BeginPath (surface->dc);
-    status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
-
-    switch (fill_rule) {
-    case CAIRO_FILL_RULE_WINDING:
-	SetPolyFillMode (surface->dc, WINDING);
-	break;
-    case CAIRO_FILL_RULE_EVEN_ODD:
-	SetPolyFillMode (surface->dc, ALTERNATE);
-	break;
-    default:
-	ASSERT_NOT_REACHED;
-    }
-
-    SelectClipPath (surface->dc, RGN_AND);
-
-    return status;
-}
-
-static void
-_cairo_win32_printing_surface_get_font_options (void                  *abstract_surface,
-                                                cairo_font_options_t  *options)
-{
-    _cairo_font_options_init_default (options);
-
-    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
-    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
-    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
-    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_paint (void			*abstract_surface,
-                                     cairo_operator_t		 op,
-                                     const cairo_pattern_t	*source,
-				     const cairo_clip_t      *clip)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_solid_pattern_t clear;
-    cairo_status_t status;
-
-    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
-    if (status)
-	return status;
-
-    if (op == CAIRO_OPERATOR_CLEAR) {
-	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
-	source = (cairo_pattern_t*) &clear;
-	op = CAIRO_OPERATOR_SOURCE;
-    }
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
-
-    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
-
-    return _cairo_win32_printing_surface_paint_pattern (surface, source);
-}
-
-static int
-_cairo_win32_line_cap (cairo_line_cap_t cap)
-{
-    switch (cap) {
-    case CAIRO_LINE_CAP_BUTT:
-	return PS_ENDCAP_FLAT;
-    case CAIRO_LINE_CAP_ROUND:
-	return PS_ENDCAP_ROUND;
-    case CAIRO_LINE_CAP_SQUARE:
-	return PS_ENDCAP_SQUARE;
-    default:
-	ASSERT_NOT_REACHED;
-	return 0;
-    }
-}
-
-static int
-_cairo_win32_line_join (cairo_line_join_t join)
-{
-    switch (join) {
-    case CAIRO_LINE_JOIN_MITER:
-	return PS_JOIN_MITER;
-    case CAIRO_LINE_JOIN_ROUND:
-	return PS_JOIN_ROUND;
-    case CAIRO_LINE_JOIN_BEVEL:
-	return PS_JOIN_BEVEL;
-    default:
-	ASSERT_NOT_REACHED;
-	return 0;
-    }
-}
-
-static void
-_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
-{
-    double s;
-
-    s = fabs (m->xx);
-    if (fabs (m->xy) > s)
-	s = fabs (m->xy);
-    if (fabs (m->yx) > s)
-	s = fabs (m->yx);
-    if (fabs (m->yy) > s)
-	s = fabs (m->yy);
-    *scale = s;
-    s = 1.0/s;
-    cairo_matrix_scale (m, s, s);
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_stroke (void			*abstract_surface,
-                                      cairo_operator_t		 op,
-                                      const cairo_pattern_t	*source,
-                                      const cairo_path_fixed_t	*path,
-                                      const cairo_stroke_style_t *style,
-                                      const cairo_matrix_t	*stroke_ctm,
-                                      const cairo_matrix_t	*stroke_ctm_inverse,
-                                      double			tolerance,
-                                      cairo_antialias_t		antialias,
-				      const cairo_clip_t    *clip)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_int_status_t status;
-    HPEN pen;
-    LOGBRUSH brush;
-    COLORREF color;
-    XFORM xform;
-    DWORD pen_style;
-    DWORD *dash_array;
-    HGDIOBJ obj;
-    unsigned int i;
-    cairo_solid_pattern_t clear;
-    cairo_matrix_t mat;
-    double scale;
-
-    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
-    if (status)
-	return status;
-
-    if (op == CAIRO_OPERATOR_CLEAR) {
-	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
-	source = (cairo_pattern_t*) &clear;
-	op = CAIRO_OPERATOR_SOURCE;
-    }
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
-	/* Win32 does not support a dash offset. */
-	if (style->num_dashes > 0 && style->dash_offset != 0.0)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
-    }
-
-    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
-    assert (!(style->num_dashes > 0 && style->dash_offset != 0.0));
-
-    cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm);
-    _cairo_matrix_factor_out_scale (&mat, &scale);
-
-    pen_style = PS_GEOMETRIC;
-    dash_array = NULL;
-    if (style->num_dashes) {
-	pen_style |= PS_USERSTYLE;
-	dash_array = calloc (sizeof (DWORD), style->num_dashes);
-	for (i = 0; i < style->num_dashes; i++) {
-	    dash_array[i] = (DWORD) (scale * style->dash[i]);
-	}
-    } else {
-	pen_style |= PS_SOLID;
-    }
-
-    SetMiterLimit (surface->dc, (FLOAT) (style->miter_limit), NULL);
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-
-
-	color = _cairo_win32_printing_surface_flatten_transparency (surface,
-								    &solid->color);
-    } else {
-	/* Color not used as the pen will only be used by WidenPath() */
-	color = RGB (0,0,0);
-    }
-    brush.lbStyle = BS_SOLID;
-    brush.lbColor = color;
-    brush.lbHatch = 0;
-    pen_style |= _cairo_win32_line_cap (style->line_cap);
-    pen_style |= _cairo_win32_line_join (style->line_join);
-    pen = ExtCreatePen(pen_style,
-		       scale * style->line_width,
-		       &brush,
-		       style->num_dashes,
-		       dash_array);
-    if (pen == NULL)
-	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen");
-    obj = SelectObject (surface->dc, pen);
-    if (obj == NULL)
-	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject");
-
-    BeginPath (surface->dc);
-    status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
-    if (status)
-	return status;
-
-    /*
-     * Switch to user space to set line parameters
-     */
-    SaveDC (surface->dc);
-
-    _cairo_matrix_to_win32_xform (&mat, &xform);
-    xform.eDx = 0.0f;
-    xform.eDy = 0.0f;
-
-    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
-	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform");
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	StrokePath (surface->dc);
-    } else {
-	if (!WidenPath (surface->dc))
-	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath");
-	if (!SelectClipPath (surface->dc, RGN_AND))
-	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath");
-
-	/* Return to device space to paint the pattern */
-	_cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
-	if (!SetWorldTransform (surface->dc, &xform))
-	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform");
-	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
-    }
-    RestoreDC (surface->dc, -1);
-    DeleteObject (pen);
-    free (dash_array);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_fill (void		        *abstract_surface,
-				    cairo_operator_t		 op,
-				    const cairo_pattern_t	*source,
-				    const cairo_path_fixed_t	*path,
-				    cairo_fill_rule_t		 fill_rule,
-				    double			 tolerance,
-				    cairo_antialias_t		 antialias,
-				    const cairo_clip_t		*clip)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_int_status_t status;
-    cairo_solid_pattern_t clear;
-
-    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
-    if (status)
-	return status;
-
-    if (op == CAIRO_OPERATOR_CLEAR) {
-	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
-	source = (cairo_pattern_t*) &clear;
-	op = CAIRO_OPERATOR_SOURCE;
-    }
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
-
-    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
-
-    surface->path_empty = TRUE;
-    BeginPath (surface->dc);
-    status = _cairo_win32_printing_surface_emit_path (surface, path);
-    EndPath (surface->dc);
-
-    switch (fill_rule) {
-    case CAIRO_FILL_RULE_WINDING:
-	SetPolyFillMode (surface->dc, WINDING);
-	break;
-    case CAIRO_FILL_RULE_EVEN_ODD:
-	SetPolyFillMode (surface->dc, ALTERNATE);
-	break;
-    default:
-	ASSERT_NOT_REACHED;
-    }
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
-	if (status)
-	    return status;
-
-	FillPath (surface->dc);
-	_cairo_win32_printing_surface_done_solid_brush (surface);
-    } else if (surface->path_empty == FALSE) {
-	SaveDC (surface->dc);
-	SelectClipPath (surface->dc, RGN_AND);
-	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
-	RestoreDC (surface->dc, -1);
-    }
-
-    fflush(stderr);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t 	*surface,
-						 cairo_operator_t	 op,
-						 const cairo_pattern_t  *source,
-						 cairo_glyph_t        	*glyphs,
-						 int			 num_glyphs,
-						 cairo_scaled_font_t  	*scaled_font,
-						 const cairo_clip_t	*clip)
-{
-    cairo_matrix_t ctm;
-    cairo_glyph_t  *unicode_glyphs;
-    cairo_scaled_font_subsets_glyph_t subset_glyph;
-    int i, first;
-    cairo_bool_t sequence_is_unicode;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    /* Where possible reverse the glyph indices back to unicode
-     * characters. Strings of glyphs that could not be reversed to
-     * unicode will be printed with ETO_GLYPH_INDEX.
-     *
-     * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
-     * operation, the font subsetting function
-     * _cairo_scaled_font_subsets_map_glyph() is used to obtain
-     * the unicode value because it caches the reverse mapping in
-     * the subsets.
-     */
-
-    if (surface->has_ctm) {
-	for (i = 0; i < num_glyphs; i++)
-	    cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y);
-	cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm);
-	scaled_font = cairo_scaled_font_create (scaled_font->font_face,
-						&scaled_font->font_matrix,
-						&ctm,
-						&scaled_font->options);
-    }
-
-    unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-    if (unicode_glyphs == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    memcpy (unicode_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
-    for (i = 0; i < num_glyphs; i++) {
-	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
-						       scaled_font,
-						       glyphs[i].index,
-						       NULL, 0,
-						       &subset_glyph);
-	if (status)
-	    goto fail;
-
-	unicode_glyphs[i].index = subset_glyph.unicode;
-    }
-
-    i = 0;
-    first = 0;
-    sequence_is_unicode = unicode_glyphs[0].index <= 0xffff;
-    while (i < num_glyphs) {
-	if (i == num_glyphs - 1 ||
-	    ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode))
-	{
-	    status = _cairo_win32_surface_show_glyphs_internal (
-		surface,
-		op,
-		source,
-		sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
-		i - first + 1,
-		scaled_font,
-		clip,
-		! sequence_is_unicode);
-	    first = i + 1;
-	    if (i < num_glyphs - 1)
-		sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff;
-	}
-	i++;
-    }
-
-fail:
-    if (surface->has_ctm)
-	cairo_scaled_font_destroy (scaled_font);
-
-    free (unicode_glyphs);
-
-    return status;
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_show_glyphs (void                 *abstract_surface,
-                                           cairo_operator_t	 op,
-                                           const cairo_pattern_t *source,
-                                           cairo_glyph_t        *glyphs,
-                                           int			 num_glyphs,
-                                           cairo_scaled_font_t  *scaled_font,
-					   const cairo_clip_t	*clip)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    cairo_scaled_glyph_t *scaled_glyph;
-    cairo_pattern_t *opaque = NULL;
-    int i;
-    cairo_matrix_t old_ctm;
-    cairo_bool_t old_has_ctm;
-    cairo_solid_pattern_t clear;
-
-    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
-    if (status)
-	return status;
-
-    if (op == CAIRO_OPERATOR_CLEAR) {
-	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
-	source = (cairo_pattern_t*) &clear;
-	op = CAIRO_OPERATOR_SOURCE;
-    }
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
-	/* When printing bitmap fonts to a printer DC, Windows may
-	 * substitute an outline font for bitmap font. As the win32
-	 * font backend always uses a screen DC when obtaining the
-	 * font metrics the metrics of the substituted font will not
-	 * match the metrics that the win32 font backend returns.
-	 *
-	 * If we are printing a bitmap font, use fallback images to
-	 * ensure the font is not substituted.
-	 */
-#if CAIRO_HAS_WIN32_FONT
-	if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
-	    if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-	    else
-		return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
-	}
-#endif
-
-	/* For non win32 fonts we need to check that each glyph has a
-	 * path available. If a path is not available,
-	 * _cairo_scaled_glyph_lookup() will return
-	 * CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be
-	 * used.
-	 */
-	for (i = 0; i < num_glyphs; i++) {
-	    status = _cairo_scaled_glyph_lookup (scaled_font,
-						 glyphs[i].index,
-						 CAIRO_SCALED_GLYPH_INFO_PATH,
-						 &scaled_glyph);
-	    if (status)
-		return status;
-	}
-
-	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
-    }
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-	COLORREF color;
-
-	color = _cairo_win32_printing_surface_flatten_transparency (surface,
-								    &solid->color);
-	opaque = cairo_pattern_create_rgb (GetRValue (color) / 255.0,
-					   GetGValue (color) / 255.0,
-					   GetBValue (color) / 255.0);
-	if (opaque->status)
-	    return opaque->status;
-	source = opaque;
-    }
-
-#if CAIRO_HAS_WIN32_FONT
-    if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
-	source->type == CAIRO_PATTERN_TYPE_SOLID)
-    {
-	return _cairo_win32_printing_surface_emit_win32_glyphs (surface,
-								op,
-								source,
-								glyphs,
-								num_glyphs,
-								scaled_font,
-								clip);
-    }
-#endif
-
-    SaveDC (surface->dc);
-    old_ctm = surface->ctm;
-    old_has_ctm = surface->has_ctm;
-    surface->has_ctm = TRUE;
-    surface->path_empty = TRUE;
-    BeginPath (surface->dc);
-    for (i = 0; i < num_glyphs; i++) {
-	status = _cairo_scaled_glyph_lookup (scaled_font,
-					     glyphs[i].index,
-					     CAIRO_SCALED_GLYPH_INFO_PATH,
-					     &scaled_glyph);
-	if (status)
-	    break;
-	surface->ctm = old_ctm;
-	cairo_matrix_translate (&surface->ctm, glyphs[i].x, glyphs[i].y);
-	status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path);
-    }
-    EndPath (surface->dc);
-    surface->ctm = old_ctm;
-    surface->has_ctm = old_has_ctm;
-    if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
-	if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	    status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
-	    if (status)
-		return status;
-
-	    SetPolyFillMode (surface->dc, WINDING);
-	    FillPath (surface->dc);
-	    _cairo_win32_printing_surface_done_solid_brush (surface);
-	} else {
-	    SelectClipPath (surface->dc, RGN_AND);
-	    status = _cairo_win32_printing_surface_paint_pattern (surface, source);
-	}
-    }
-    RestoreDC (surface->dc, -1);
-
-    if (opaque)
-	cairo_pattern_destroy (opaque);
-
-    return status;
-}
-
-static const char **
-_cairo_win32_printing_surface_get_supported_mime_types (void	  *abstract_surface)
-{
-    return _cairo_win32_printing_supported_mime_types;
-}
-
-static cairo_surface_t *
-_cairo_win32_printing_surface_create_similar (void		*abstract_surface,
-					      cairo_content_t	 content,
-					      int		 width,
-					      int		 height)
-{
-    cairo_rectangle_t extents;
-
-    extents.x = extents.y = 0;
-    extents.width  = width;
-    extents.height = height;
-    return cairo_recording_surface_create (content, &extents);
-}
-
-static cairo_int_status_t
-_cairo_win32_printing_surface_start_page (void *abstract_surface)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    XFORM xform;
-    double x_res, y_res;
-    cairo_matrix_t inverse_ctm;
-    cairo_status_t status;
-
-    SaveDC (surface->dc); /* Save application context first, before doing MWT */
-
-    /* As the logical coordinates used by GDI functions (eg LineTo)
-     * are integers we need to do some additional work to prevent
-     * rounding errors. For example the obvious way to paint a recording
-     * pattern is to:
-     *
-     *   SaveDC()
-     *   transform the device context DC by the pattern to device matrix
-     *   replay the recording surface
-     *   RestoreDC()
-     *
-     * The problem here is that if the pattern to device matrix is
-     * [100 0 0 100 0 0], coordinates in the recording pattern such as
-     * (1.56, 2.23) which correspond to (156, 223) in device space
-     * will be rounded to (100, 200) due to (1.56, 2.23) being
-     * truncated to integers.
-     *
-     * This is solved by saving the current GDI CTM in surface->ctm,
-     * switch the GDI CTM to identity, and transforming all
-     * coordinates by surface->ctm before passing them to GDI. When
-     * painting a recording pattern, surface->ctm is transformed by the
-     * pattern to device matrix.
-     *
-     * For printing device contexts where 1 unit is 1 dpi, switching
-     * the GDI CTM to identity maximises the possible resolution of
-     * coordinates.
-     *
-     * If the device context is an EMF file, using an identity
-     * transform often provides insufficent resolution. The workaround
-     * is to set the GDI CTM to a scale < 1 eg [1.0/16 0 0 1/0/16 0 0]
-     * and scale the cairo CTM by [16 0 0 16 0 0]. The
-     * SetWorldTransform function call to scale the GDI CTM by 1.0/16
-     * will be recorded in the EMF followed by all the graphics
-     * functions by their coordinateds multiplied by 16.
-     *
-     * To support allowing the user to set a GDI CTM with scale < 1,
-     * we avoid switching to an identity CTM if the CTM xx and yy is < 1.
-     */
-    SetGraphicsMode (surface->dc, GM_ADVANCED);
-    GetWorldTransform(surface->dc, &xform);
-    if (xform.eM11 < 1 && xform.eM22 < 1) {
-	cairo_matrix_init_identity (&surface->ctm);
-	surface->gdi_ctm.xx = xform.eM11;
-	surface->gdi_ctm.xy = xform.eM21;
-	surface->gdi_ctm.yx = xform.eM12;
-	surface->gdi_ctm.yy = xform.eM22;
-	surface->gdi_ctm.x0 = xform.eDx;
-	surface->gdi_ctm.y0 = xform.eDy;
-    } else {
-	surface->ctm.xx = xform.eM11;
-	surface->ctm.xy = xform.eM21;
-	surface->ctm.yx = xform.eM12;
-	surface->ctm.yy = xform.eM22;
-	surface->ctm.x0 = xform.eDx;
-	surface->ctm.y0 = xform.eDy;
-	cairo_matrix_init_identity (&surface->gdi_ctm);
-	if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY))
-	    return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform");
-    }
-
-    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
-    surface->has_gdi_ctm = !_cairo_matrix_is_identity (&surface->gdi_ctm);
-    inverse_ctm = surface->ctm;
-    status = cairo_matrix_invert (&inverse_ctm);
-    if (status)
-	return status;
-
-    x_res = GetDeviceCaps (surface->dc, LOGPIXELSX);
-    y_res = GetDeviceCaps (surface->dc, LOGPIXELSY);
-    cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res);
-    _cairo_surface_set_resolution (&surface->base, x_res, y_res);
-
-    SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
-                                                  cairo_paginated_mode_t paginated_mode)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    surface->paginated_mode = paginated_mode;
-}
-
-static cairo_bool_t
-_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface)
-{
-    return TRUE;
-}
-
-/**
- * cairo_win32_printing_surface_create:
- * @hdc: the DC to create a surface for
- *
- * Creates a cairo surface that targets the given DC.  The DC will be
- * queried for its initial clip extents, and this will be used as the
- * size of the cairo surface.  The DC should be a printing DC;
- * antialiasing will be ignored, and GDI will be used as much as
- * possible to draw to the surface.
- *
- * The returned surface will be wrapped using the paginated surface to
- * provide correct complex rendering behaviour; cairo_surface_show_page() and
- * associated methods must be used for correct output.
- *
- * Return value: the newly created surface
- *
- * Since: 1.6
- **/
-cairo_surface_t *
-cairo_win32_printing_surface_create (HDC hdc)
-{
-    cairo_win32_surface_t *surface;
-    cairo_surface_t *paginated;
-    RECT rect;
-
-    surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
-	free (surface);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    _cairo_surface_clipper_init (&surface->clipper,
-				 _cairo_win32_printing_surface_clipper_intersect_clip_path);
-
-    surface->image = NULL;
-    surface->format = CAIRO_FORMAT_RGB24;
-    surface->content = CAIRO_CONTENT_COLOR_ALPHA;
-
-    surface->dc = hdc;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-    surface->saved_dc_bitmap = NULL;
-    surface->brush = NULL;
-    surface->old_brush = NULL;
-    surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
-    if (surface->font_subsets == NULL) {
-	free (surface);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    GetClipBox(hdc, &rect);
-    surface->extents.x = rect.left;
-    surface->extents.y = rect.top;
-    surface->extents.width = rect.right - rect.left;
-    surface->extents.height = rect.bottom - rect.top;
-
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-    surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
-
-    _cairo_win32_printing_surface_init_ps_mode (surface);
-    _cairo_win32_printing_surface_init_image_support (surface);
-    _cairo_win32_printing_surface_init_language_pack (surface);
-    _cairo_surface_init (&surface->base,
-			 &cairo_win32_printing_surface_backend,
-			 NULL, /* device */
-                         CAIRO_CONTENT_COLOR_ALPHA);
-
-    paginated = _cairo_paginated_surface_create (&surface->base,
-						 CAIRO_CONTENT_COLOR_ALPHA,
-						 &cairo_win32_surface_paginated_backend);
-
-    /* paginated keeps the only reference to surface now, drop ours */
-    cairo_surface_destroy (&surface->base);
-
-    return paginated;
-}
-
-cairo_bool_t
-_cairo_surface_is_win32_printing (cairo_surface_t *surface)
-{
-    return surface->backend == &cairo_win32_printing_surface_backend;
-}
-
-static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
-    CAIRO_SURFACE_TYPE_WIN32_PRINTING,
-    _cairo_win32_surface_finish,
-
-    _cairo_default_context_create,
-
-    _cairo_win32_printing_surface_create_similar,
-    NULL, /* create similar image */
-    NULL, /* map to image */
-    NULL, /* unmap image */
-
-    _cairo_surface_default_source,
-    NULL, /* acquire_source_image */
-    NULL, /* release_source_image */
-    NULL, /* snapshot */
-
-    NULL, /* copy_page */
-    _cairo_win32_printing_surface_show_page,
-
-    _cairo_win32_surface_get_extents,
-    _cairo_win32_printing_surface_get_font_options,
-
-    NULL, /* flush */
-    NULL, /* mark_dirty_rectangle */
-
-    _cairo_win32_printing_surface_paint,
-    NULL, /* mask */
-    _cairo_win32_printing_surface_stroke,
-    _cairo_win32_printing_surface_fill,
-    NULL, /* fill/stroke */
-    _cairo_win32_printing_surface_show_glyphs,
-    NULL, /* has_show_text_glyphs */
-    NULL, /* show_text_glyphs */
-    _cairo_win32_printing_surface_get_supported_mime_types,
-};
-
-static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend = {
-    _cairo_win32_printing_surface_start_page,
-    _cairo_win32_printing_surface_set_paginated_mode,
-    NULL, /* set_bounding_box */
-    NULL, /* _cairo_win32_printing_surface_has_fallback_images, */
-    _cairo_win32_printing_surface_supports_fine_grained_fallbacks,
-};
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
deleted file mode 100644
index 07830dc..0000000
--- a/src/cairo-win32-private.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- *	Owen Taylor <otaylor at redhat.com>
- */
-
-#ifndef CAIRO_WIN32_PRIVATE_H
-#define CAIRO_WIN32_PRIVATE_H
-
-#include "cairo-win32.h"
-#include "cairoint.h"
-#include "cairo-surface-clipper-private.h"
-
-#ifndef SHADEBLENDCAPS
-#define SHADEBLENDCAPS 120
-#endif
-#ifndef SB_NONE
-#define SB_NONE 0
-#endif
-
-#define WIN32_FONT_LOGICAL_SCALE 32
-
-typedef struct _cairo_win32_surface {
-    cairo_surface_t base;
-
-    cairo_format_t format;
-
-    HDC dc;
-
-    /* We create off-screen surfaces as DIBs or DDBs, based on what we created
-     * originally*/
-    HBITMAP bitmap;
-    cairo_bool_t is_dib;
-
-    /* Used to save the initial 1x1 monochrome bitmap for the DC to
-     * select back into the DC before deleting the DC and our
-     * bitmap. For Windows XP, this doesn't seem to be necessary
-     * ... we can just delete the DC and that automatically unselects
-     * out bitmap. But it's standard practice so apparently is needed
-     * on some versions of Windows.
-     */
-    HBITMAP saved_dc_bitmap;
-
-    cairo_surface_t *image;
-
-    /* We use the x and y parts of extents for situations where
-     * we're not supposed to draw to the entire surface.
-     * For example, during a paint event a program will get
-     * a DC that has been clipped to the dirty region.
-     * A cairo surface constructed for that DC will have extents
-     * that match bounds of the clipped region.
-     *
-     * jrmuizel: I'm not sure if storing these extents instead
-     * of just using the size is better... */
-    cairo_rectangle_int_t extents;
-
-    /* Initial clip bits
-     * We need these kept around so that we maintain
-     * whatever clip was set on the original DC at creation
-     * time when cairo is asked to reset the surface clip.
-     */
-    cairo_rectangle_int_t clip_rect;
-    HRGN initial_clip_rgn;
-    cairo_bool_t had_simple_clip;
-    cairo_region_t *clip_region;
-
-    /* For path clipping to the printing-surface */
-    cairo_surface_clipper_t clipper;
-
-    /* Surface DC flags */
-    uint32_t flags;
-
-    /* printing surface bits */
-    cairo_paginated_mode_t paginated_mode;
-    cairo_content_t content;
-    cairo_bool_t path_empty;
-    cairo_bool_t has_ctm;
-    cairo_matrix_t ctm;
-    cairo_bool_t has_gdi_ctm;
-    cairo_matrix_t gdi_ctm;
-    HBRUSH brush, old_brush;
-    cairo_scaled_font_subsets_t *font_subsets;
-} cairo_win32_surface_t;
-
-/* Surface DC flag values */
-enum {
-    /* If this is a surface created for printing or not */
-    CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
-
-    /* Whether the DC is a display DC or not */
-    CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
-
-    /* Whether we can use BitBlt with this surface */
-    CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
-
-    /* Whether we can use AlphaBlend with this surface */
-    CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
-
-    /* Whether we can use StretchBlt with this surface */
-    CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
-
-    /* Whether we can use StretchDIBits with this surface */
-    CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5),
-
-    /* Whether we can use GradientFill rectangles with this surface */
-    CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
-
-    /* Whether we can use the CHECKJPEGFORMAT escape function */
-    CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
-
-    /* Whether we can use the CHECKJPEGFORMAT escape function */
-    CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
-};
-
-cairo_status_t
-_cairo_win32_print_gdi_error (const char *context);
-
-cairo_bool_t
-_cairo_surface_is_win32 (cairo_surface_t *surface);
-
-cairo_bool_t
-_cairo_surface_is_win32_printing (cairo_surface_t *surface);
-
-cairo_status_t
-_cairo_win32_surface_finish (void *abstract_surface);
-
-cairo_bool_t
-_cairo_win32_surface_get_extents (void		          *abstract_surface,
-				  cairo_rectangle_int_t   *rectangle);
-
-uint32_t
-_cairo_win32_flags_for_dc (HDC dc);
-
-cairo_status_t
-_cairo_win32_surface_set_clip_region (void           *abstract_surface,
-				      cairo_region_t *region);
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs_internal (void			 *surface,
-					   cairo_operator_t	  op,
-					   const cairo_pattern_t *source,
-					   cairo_glyph_t	 *glyphs,
-					   int			  num_glyphs,
-					   cairo_scaled_font_t	 *scaled_font,
-					   const cairo_clip_t	 *clip,
-					   cairo_bool_t		  glyph_indices);
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs (void			*surface,
-				  cairo_operator_t	 op,
-				  const cairo_pattern_t	*source,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font,
-				  const cairo_clip_t	*clip);
-
-cairo_surface_t *
-_cairo_win32_surface_create_similar (void	    *abstract_src,
-				     cairo_content_t content,
-				     int	     width,
-				     int	     height);
-
-static inline void
-_cairo_matrix_to_win32_xform (const cairo_matrix_t *m,
-                              XFORM *xform)
-{
-    xform->eM11 = (FLOAT) m->xx;
-    xform->eM21 = (FLOAT) m->xy;
-    xform->eM12 = (FLOAT) m->yx;
-    xform->eM22 = (FLOAT) m->yy;
-    xform->eDx = (FLOAT) m->x0;
-    xform->eDy = (FLOAT) m->y0;
-}
-
-cairo_int_status_t
-_cairo_win32_save_initial_clip (HDC dc, cairo_win32_surface_t *surface);
-
-cairo_int_status_t
-_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface);
-
-void
-_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header);
-
-cairo_bool_t
-_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
-
-cairo_bool_t
-_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font);
-
-#endif /* CAIRO_WIN32_PRIVATE_H */
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
deleted file mode 100644
index 244abc0..0000000
--- a/src/cairo-win32-surface.c
+++ /dev/null
@@ -1,2098 +0,0 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- *	Owen Taylor <otaylor at redhat.com>
- *	Stuart Parmenter <stuart at mozilla.com>
- *	Vladimir Vukicevic <vladimir at pobox.com>
- */
-
-#define WIN32_LEAN_AND_MEAN
-/* We require Windows 2000 features such as ETO_PDY */
-#if !defined(WINVER) || (WINVER < 0x0500)
-# define WINVER 0x0500
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-# define _WIN32_WINNT 0x0500
-#endif
-
-#include "cairoint.h"
-
-#include "cairo-clip-private.h"
-#include "cairo-composite-rectangles-private.h"
-#include "cairo-default-context-private.h"
-#include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
-#include "cairo-paginated-private.h"
-#include "cairo-pattern-private.h"
-#include "cairo-win32-private.h"
-#include "cairo-scaled-font-subsets-private.h"
-#include "cairo-surface-fallback-private.h"
-#include "cairo-surface-backend-private.h"
-
-#include <wchar.h>
-#include <windows.h>
-
-#if defined(__MINGW32__) && !defined(ETO_PDY)
-# define ETO_PDY 0x2000
-#endif
-
-#undef DEBUG_COMPOSITE
-
-/* for older SDKs */
-#ifndef SHADEBLENDCAPS
-#define SHADEBLENDCAPS  120
-#endif
-#ifndef SB_NONE
-#define SB_NONE         0x00000000
-#endif
-
-#define PELS_72DPI  ((LONG)(72. / 0.0254))
-
-/**
- * SECTION:cairo-win32
- * @Title: Win32 Surfaces
- * @Short_Description: Microsoft Windows surface support
- * @See_Also: #cairo_surface_t
- *
- * The Microsoft Windows surface is used to render cairo graphics to
- * Microsoft Windows windows, bitmaps, and printing device contexts.
- *
- * The surface returned by cairo_win32_printing_surface_create() is of surface
- * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface
- * type.
- *
- * The surface returned by the other win32 constructors is of surface type
- * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type.
- */
-
-/**
- * CAIRO_HAS_WIN32_SURFACE:
- *
- * Defined if the Microsoft Windows surface backend is available.
- * This macro can be used to conditionally compile backend-specific code.
- */
-
-static const cairo_surface_backend_t cairo_win32_surface_backend;
-
-/**
- * _cairo_win32_print_gdi_error:
- * @context: context string to display along with the error
- *
- * Helper function to dump out a human readable form of the
- * current error code.
- *
- * Return value: A cairo status code for the error code
- **/
-cairo_status_t
-_cairo_win32_print_gdi_error (const char *context)
-{
-    void *lpMsgBuf;
-    DWORD last_error = GetLastError ();
-
-    if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
-			 FORMAT_MESSAGE_FROM_SYSTEM,
-			 NULL,
-			 last_error,
-			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
-			 (LPWSTR) &lpMsgBuf,
-			 0, NULL)) {
-	fprintf (stderr, "%s: Unknown GDI error", context);
-    } else {
-	fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf);
-
-	LocalFree (lpMsgBuf);
-    }
-
-    fflush (stderr);
-
-    /* We should switch off of last_status, but we'd either return
-     * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there
-     * is no CAIRO_STATUS_UNKNOWN_ERROR.
-     */
-
-    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-}
-
-uint32_t
-_cairo_win32_flags_for_dc (HDC dc)
-{
-    uint32_t flags = 0;
-
-    if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
-	flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY;
-
-	/* These will always be possible, but the actual GetDeviceCaps
-	 * calls will return whether they're accelerated or not.
-	 * We may want to use our own (pixman) routines sometimes
-	 * if they're eventually faster, but for now have GDI do
-	 * everything.
-	 */
-	flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
-	flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
-	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
-	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
-    } else {
-	int cap;
-
-	cap = GetDeviceCaps(dc, SHADEBLENDCAPS);
-	if (cap != SB_NONE)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
-
-	cap = GetDeviceCaps(dc, RASTERCAPS);
-	if (cap & RC_BITBLT)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
-	if (cap & RC_STRETCHBLT)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
-	if (cap & RC_STRETCHDIB)
-	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
-    }
-
-    return flags;
-}
-
-static cairo_status_t
-_create_dc_and_bitmap (cairo_win32_surface_t *surface,
-		       HDC                    original_dc,
-		       cairo_format_t         format,
-		       int                    width,
-		       int                    height,
-		       unsigned char        **bits_out,
-		       int                   *rowstride_out)
-{
-    cairo_status_t status;
-
-    BITMAPINFO *bitmap_info = NULL;
-    struct {
-	BITMAPINFOHEADER bmiHeader;
-	RGBQUAD bmiColors[2];
-    } bmi_stack;
-    void *bits;
-
-    int num_palette = 0;	/* Quiet GCC */
-    int i;
-
-    surface->dc = NULL;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-
-    switch (format) {
-    default:
-    case CAIRO_FORMAT_INVALID:
-	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-    case CAIRO_FORMAT_ARGB32:
-    case CAIRO_FORMAT_RGB24:
-	num_palette = 0;
-	break;
-
-    case CAIRO_FORMAT_A8:
-	num_palette = 256;
-	break;
-
-    case CAIRO_FORMAT_A1:
-	num_palette = 2;
-	break;
-    }
-
-    if (num_palette > 2) {
-	bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
-	if (!bitmap_info)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    } else {
-	bitmap_info = (BITMAPINFO *)&bmi_stack;
-    }
-
-    bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-    bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
-    bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
-    bitmap_info->bmiHeader.biSizeImage = 0;
-    bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
-    bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
-    bitmap_info->bmiHeader.biPlanes = 1;
-
-    switch (format) {
-    /* We can't create real RGB24 bitmaps because something seems to
-     * break if we do, especially if we don't set up an image
-     * fallback.  It could be a bug with using a 24bpp pixman image
-     * (and creating one with masks).  So treat them like 32bpp.
-     * Note: This causes problems when using BitBlt/AlphaBlend/etc!
-     * see end of file.
-     */
-    case CAIRO_FORMAT_RGB24:
-    case CAIRO_FORMAT_ARGB32:
-	bitmap_info->bmiHeader.biBitCount = 32;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 0;	/* unused */
-	bitmap_info->bmiHeader.biClrImportant = 0;
-	break;
-
-    case CAIRO_FORMAT_A8:
-	bitmap_info->bmiHeader.biBitCount = 8;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 256;
-	bitmap_info->bmiHeader.biClrImportant = 0;
-
-	for (i = 0; i < 256; i++) {
-	    bitmap_info->bmiColors[i].rgbBlue = i;
-	    bitmap_info->bmiColors[i].rgbGreen = i;
-	    bitmap_info->bmiColors[i].rgbRed = i;
-	    bitmap_info->bmiColors[i].rgbReserved = 0;
-	}
-
-	break;
-
-    case CAIRO_FORMAT_A1:
-	bitmap_info->bmiHeader.biBitCount = 1;
-	bitmap_info->bmiHeader.biCompression = BI_RGB;
-	bitmap_info->bmiHeader.biClrUsed = 2;
-	bitmap_info->bmiHeader.biClrImportant = 0;
-
-	for (i = 0; i < 2; i++) {
-	    bitmap_info->bmiColors[i].rgbBlue = i * 255;
-	    bitmap_info->bmiColors[i].rgbGreen = i * 255;
-	    bitmap_info->bmiColors[i].rgbRed = i * 255;
-	    bitmap_info->bmiColors[i].rgbReserved = 0;
-	}
-
-	break;
-    }
-
-    surface->dc = CreateCompatibleDC (original_dc);
-    if (!surface->dc)
-	goto FAIL;
-
-    surface->bitmap = CreateDIBSection (surface->dc,
-			                bitmap_info,
-			                DIB_RGB_COLORS,
-			                &bits,
-			                NULL, 0);
-    if (!surface->bitmap)
-	goto FAIL;
-
-    surface->is_dib = TRUE;
-
-    GdiFlush();
-
-    surface->saved_dc_bitmap = SelectObject (surface->dc,
-					     surface->bitmap);
-    if (!surface->saved_dc_bitmap)
-	goto FAIL;
-
-    if (bitmap_info && num_palette > 2)
-	free (bitmap_info);
-
-    if (bits_out)
-	*bits_out = bits;
-
-    if (rowstride_out) {
-	/* Windows bitmaps are padded to 32-bit (dword) boundaries */
-	switch (format) {
-	case CAIRO_FORMAT_ARGB32:
-	case CAIRO_FORMAT_RGB24:
-	    *rowstride_out = 4 * width;
-	    break;
-
-	case CAIRO_FORMAT_A8:
-	    *rowstride_out = (width + 3) & ~3;
-	    break;
-
-	case CAIRO_FORMAT_A1:
-	    *rowstride_out = ((width + 31) & ~31) / 8;
-	    break;
-	}
-    }
-
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-
-    return CAIRO_STATUS_SUCCESS;
-
- FAIL:
-    status = _cairo_win32_print_gdi_error ("_create_dc_and_bitmap");
-
-    if (bitmap_info && num_palette > 2)
-	free (bitmap_info);
-
-    if (surface->saved_dc_bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	surface->saved_dc_bitmap = NULL;
-    }
-
-    if (surface->bitmap) {
-	DeleteObject (surface->bitmap);
-	surface->bitmap = NULL;
-    }
-
-    if (surface->dc) {
- 	DeleteDC (surface->dc);
-	surface->dc = NULL;
-    }
-
-    return status;
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_create_for_dc (HDC             original_dc,
-				    cairo_format_t  format,
-				    int	            width,
-				    int	            height)
-{
-    cairo_status_t status;
-    cairo_win32_surface_t *surface;
-    unsigned char *bits;
-    int rowstride;
-
-    if (! CAIRO_FORMAT_VALID (format))
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-
-    surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    surface->clip_region = NULL;
-
-    status = _create_dc_and_bitmap (surface, original_dc, format,
-				    width, height,
-				    &bits, &rowstride);
-    if (status)
-	goto FAIL;
-
-    surface->image = cairo_image_surface_create_for_data (bits, format,
-							  width, height, rowstride);
-    status = surface->image->status;
-    if (status)
-	goto FAIL;
-
-    surface->format = format;
-
-    surface->clip_rect.x = 0;
-    surface->clip_rect.y = 0;
-    surface->clip_rect.width = width;
-    surface->clip_rect.height = height;
-
-    surface->initial_clip_rgn = NULL;
-    surface->had_simple_clip = FALSE;
-
-    surface->extents = surface->clip_rect;
-    surface->font_subsets = NULL;
-
-    _cairo_surface_init (&surface->base,
-			 &cairo_win32_surface_backend,
-			 NULL, /* device */
-			 _cairo_content_from_format (format));
-
-    return &surface->base;
-
- FAIL:
-    if (surface->bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	DeleteObject (surface->bitmap);
-	DeleteDC (surface->dc);
-    }
-    free (surface);
-
-    return _cairo_surface_create_in_error (status);
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_create_similar_internal (void	    *abstract_src,
-					      cairo_content_t content,
-					      int	     width,
-					      int	     height,
-					      cairo_bool_t   force_dib)
-{
-    cairo_win32_surface_t *src = abstract_src;
-    cairo_format_t format = _cairo_format_from_content (content);
-    cairo_surface_t *new_surf = NULL;
-
-    /* We force a DIB always if:
-     * - we need alpha; or
-     * - the parent is a DIB; or
-     * - the parent is for printing (because we don't care about the bit depth at that point)
-     *
-     * We also might end up with a DIB even if a DDB is requested if DDB creation failed
-     * due to out of memory.
-     */
-    if (src->is_dib ||
-	(content & CAIRO_CONTENT_ALPHA) ||
-	src->base.backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
-    {
-	force_dib = TRUE;
-    }
-
-    if (!force_dib) {
-	/* try to create a ddb */
-	new_surf = cairo_win32_surface_create_with_ddb (src->dc, CAIRO_FORMAT_RGB24, width, height);
-
-	if (new_surf->status != CAIRO_STATUS_SUCCESS)
-	    new_surf = NULL;
-    }
-
-    if (new_surf == NULL) {
-	new_surf = _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
-    }
-
-    return new_surf;
-}
-
-cairo_surface_t *
-_cairo_win32_surface_create_similar (void	    *abstract_src,
-				     cairo_content_t content,
-				     int	     width,
-				     int	     height)
-{
-    return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE);
-}
-
-cairo_status_t
-_cairo_win32_surface_finish (void *abstract_surface)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    if (surface->image)
-	cairo_surface_destroy (surface->image);
-
-    /* If we created the Bitmap and DC, destroy them */
-    if (surface->bitmap) {
-	SelectObject (surface->dc, surface->saved_dc_bitmap);
-	DeleteObject (surface->bitmap);
-	DeleteDC (surface->dc);
-    } else {
-	_cairo_win32_restore_initial_clip (surface);
-    }
-
-    if (surface->initial_clip_rgn)
-	DeleteObject (surface->initial_clip_rgn);
-
-    if (surface->font_subsets != NULL)
-	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
-				   int                     x,
-				   int                     y,
-				   int                     width,
-				   int                     height,
-				   cairo_win32_surface_t **local_out)
-{
-    cairo_win32_surface_t *local;
-    cairo_int_status_t status;
-    cairo_content_t content = _cairo_content_from_format (surface->format);
-
-    local =
-	(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
-	(surface, content, width, height, TRUE);
-    if (local == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (local->base.status)
-	return local->base.status;
-
-    status = CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Only BitBlt if the source surface supports it. */
-    if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
-	BitBlt (local->dc,
-		0, 0,
-		width, height,
-		surface->dc,
-		x, y,
-		SRCCOPY))
-    {
-	status = CAIRO_STATUS_SUCCESS;
-    }
-
-    if (status) {
-	/* If we failed here, most likely the source or dest doesn't
-	 * support BitBlt/AlphaBlend (e.g. a printer).
-	 * You can't reliably get bits from a printer DC, so just fill in
-	 * the surface as white (common case for printing).
-	 */
-
-	RECT r;
-	r.left = r.top = 0;
-	r.right = width;
-	r.bottom = height;
-	FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
-    }
-
-    *local_out = local;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_surface_t *
-_cairo_win32_surface_map_to_image (void                    *abstract_surface,
-				   const cairo_rectangle_int_t   *extents)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local = NULL;
-    cairo_status_t status;
-
-    if (surface->image) {
-	GdiFlush();
-	return _cairo_surface_create_for_rectangle_int (surface->image,
-							extents);
-    }
-
-    status = _cairo_win32_surface_get_subimage (abstract_surface,
-						extents->x,
-						extents->y,
-						extents->width,
-						extents->height,
-						&local);
-    if (unlikely (status))
-	return _cairo_surface_create_in_error (status);
-
-    status = cairo_surface_set_user_data (local->image,
-					  (const cairo_user_data_key_t *)surface->image,
-					  local, NULL);
-    if (unlikely (status)) {
-	cairo_surface_destroy (&local->base);
-	return _cairo_surface_create_in_error (status);
-    }
-
-    cairo_surface_set_device_offset (local->image, -extents->x, -extents->y);
-    return local->image;
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_unmap_image (void                    *abstract_surface,
-				  cairo_image_surface_t   *image)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local;
-
-    local = cairo_surface_get_user_data (&image->base,
-					 (const cairo_user_data_key_t *) surface->image);
-    if (!local)
-	return CAIRO_INT_STATUS_SUCCESS;
-
-    if (!BitBlt (surface->dc,
-		 image->base.device_transform.x0,
-		 image->base.device_transform.y0,
-		 image->width, image->height,
-		 local->dc,
-		 0, 0,
-		 SRCCOPY))
-	_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
-					   cairo_image_surface_t  **image_out,
-					   void                   **image_extra)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local;
-    cairo_status_t status;
-
-    if (surface->image) {
-	*image_out = (cairo_image_surface_t *)surface->image;
-	*image_extra = NULL;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
-						surface->extents.width,
-						surface->extents.height, &local);
-    if (status)
-	return status;
-
-    *image_out = (cairo_image_surface_t *)local->image;
-    *image_extra = local;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_win32_surface_release_source_image (void                   *abstract_surface,
-					   cairo_image_surface_t  *image,
-					   void                   *image_extra)
-{
-    cairo_win32_surface_t *local = image_extra;
-
-    if (local)
-	cairo_surface_destroy ((cairo_surface_t *)local);
-}
-
-cairo_status_t
-_cairo_win32_surface_set_clip_region (void           *abstract_surface,
-				      cairo_region_t *region)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    if (surface->clip_region == region)
-	return CAIRO_STATUS_SUCCESS;
-
-    cairo_region_destroy (surface->clip_region);
-    surface->clip_region = cairo_region_reference (region);
-
-    /* The semantics we want is that any clip set by cairo combines
-     * is intersected with the clip on device context that the
-     * surface was created for. To implement this, we need to
-     * save the original clip when first setting a clip on surface.
-     */
-
-    /* Clear any clip set by cairo, return to the original first */
-    status = _cairo_win32_restore_initial_clip (surface);
-
-    /* Then combine any new region with it */
-    if (region) {
-	cairo_rectangle_int_t extents;
-	int num_rects;
-	RGNDATA *data;
-	size_t data_size;
-	RECT *rects;
-	int i;
-	HRGN gdi_region;
-
-	/* Create a GDI region for the cairo region */
-
-	cairo_region_get_extents (region, &extents);
-	num_rects = cairo_region_num_rectangles (region);
-	/* XXX see notes in _cairo_win32_save_initial_clip --
-	 * this code will interact badly with a HDC which had an initial
-	 * world transform -- we should probably manually transform the
-	 * region rects, because SelectClipRgn takes device units, not
-	 * logical units (unlike IntersectClipRect).
-	 */
-
-	data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
-	data = malloc (data_size);
-	if (!data)
-	    return _cairo_error(CAIRO_STATUS_NO_MEMORY);
-	rects = (RECT *)data->Buffer;
-
-	data->rdh.dwSize = sizeof (RGNDATAHEADER);
-	data->rdh.iType = RDH_RECTANGLES;
-	data->rdh.nCount = num_rects;
-	data->rdh.nRgnSize = num_rects * sizeof (RECT);
-	data->rdh.rcBound.left = extents.x;
-	data->rdh.rcBound.top = extents.y;
-	data->rdh.rcBound.right = extents.x + extents.width;
-	data->rdh.rcBound.bottom = extents.y + extents.height;
-
-	for (i = 0; i < num_rects; i++) {
-	    cairo_rectangle_int_t rect;
-
-	    cairo_region_get_rectangle (region, i, &rect);
-
-	    rects[i].left   = rect.x;
-	    rects[i].top    = rect.y;
-	    rects[i].right  = rect.x + rect.width;
-	    rects[i].bottom = rect.y + rect.height;
-	}
-
-	gdi_region = ExtCreateRegion (NULL, data_size, data);
-	free (data);
-
-	if (!gdi_region)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	/* AND the new region into our DC */
-	if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
-	    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
-
-	DeleteObject (gdi_region);
-    }
-
-    return status;
-}
-
-#if !defined(AC_SRC_OVER)
-#define AC_SRC_OVER                 0x00
-#pragma pack(1)
-typedef struct {
-    BYTE   BlendOp;
-    BYTE   BlendFlags;
-    BYTE   SourceConstantAlpha;
-    BYTE   AlphaFormat;
-}BLENDFUNCTION;
-#pragma pack()
-#endif
-
-/* for compatibility with VC++ 6 */
-#ifndef AC_SRC_ALPHA
-#define AC_SRC_ALPHA                0x01
-#endif
-
-typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest,
-						 int nXOriginDest,
-						 int nYOriginDest,
-						 int nWidthDest,
-						 int hHeightDest,
-						 HDC hdcSrc,
-						 int nXOriginSrc,
-						 int nYOriginSrc,
-						 int nWidthSrc,
-						 int nHeightSrc,
-						 BLENDFUNCTION blendFunction);
-
-static cairo_int_status_t
-_composite_alpha_blend (cairo_win32_surface_t *dst,
-			cairo_win32_surface_t *src,
-			int                    alpha,
-			int                    src_x,
-			int                    src_y,
-			int                    src_w,
-			int                    src_h,
-			int                    dst_x,
-			int                    dst_y,
-			int                    dst_w,
-			int                    dst_h)
-{
-    static unsigned alpha_blend_checked = FALSE;
-    static cairo_alpha_blend_func_t alpha_blend = NULL;
-
-    BLENDFUNCTION blend_function;
-
-    /* Check for AlphaBlend dynamically to allow compiling on
-     * MSVC 6 and use on older windows versions
-     */
-    if (!alpha_blend_checked) {
-	OSVERSIONINFO os;
-
-	os.dwOSVersionInfoSize = sizeof (os);
-	GetVersionEx (&os);
-
-	/* If running on Win98, disable using AlphaBlend()
-	 * to avoid Win98 AlphaBlend() bug */
-	if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
-	    os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
-	{
-	    HMODULE msimg32_dll = LoadLibraryW (L"msimg32");
-
-	    if (msimg32_dll != NULL)
-		alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,
-									"AlphaBlend");
-	}
-
-	alpha_blend_checked = TRUE;
-    }
-
-    if (alpha_blend == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    blend_function.BlendOp = AC_SRC_OVER;
-    blend_function.BlendFlags = 0;
-    blend_function.SourceConstantAlpha = alpha;
-    blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
-
-    if (!alpha_blend (dst->dc,
-		      dst_x, dst_y,
-		      dst_w, dst_h,
-		      src->dc,
-		      src_x, src_y,
-		      src_w, src_h,
-		      blend_function))
-	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
-				      cairo_image_surface_t *src_image,
-				      cairo_win32_surface_t *dst,
-				      cairo_rectangle_int_t src_extents,
-				      cairo_rectangle_int_t src_r,
-				      cairo_rectangle_int_t dst_r,
-				      int alpha,
-				      cairo_bool_t needs_alpha,
-				      cairo_bool_t needs_scale)
-{
-    /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
-    if (src_image) {
-	if (needs_alpha || needs_scale)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
-	    BITMAPINFO bi;
-	    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-	    bi.bmiHeader.biWidth = src_image->width;
-	    bi.bmiHeader.biHeight = - src_image->height;
-	    bi.bmiHeader.biSizeImage = 0;
-	    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
-	    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
-	    bi.bmiHeader.biPlanes = 1;
-	    bi.bmiHeader.biBitCount = 32;
-	    bi.bmiHeader.biCompression = BI_RGB;
-	    bi.bmiHeader.biClrUsed = 0;
-	    bi.bmiHeader.biClrImportant = 0;
-
-	    /* StretchDIBits is broken with top-down dibs; you need to do some
-	     * special munging to make the coordinate space work (basically,
-	     * need to address everything based on the bottom left, instead of top left,
-	     * and need to tell it to flip the resulting image.
-	     *
-	     * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
-	     */
-	    if (!StretchDIBits (dst->dc,
-				/* dst x,y,w,h */
-				dst_r.x, dst_r.y + dst_r.height - 1,
-				dst_r.width, - (int) dst_r.height,
-				/* src x,y,w,h */
-				src_r.x, src_extents.height - src_r.y + 1,
-				src_r.width, - (int) src_r.height,
-				src_image->data,
-				&bi,
-				DIB_RGB_COLORS,
-				SRCCOPY))
-		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
-	}
-    } else if (!needs_alpha) {
-	/* BitBlt or StretchBlt? */
-	if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
-	    if (!BitBlt (dst->dc,
-			 dst_r.x, dst_r.y,
-			 dst_r.width, dst_r.height,
-			 src->dc,
-			 src_r.x, src_r.y,
-			 SRCCOPY))
-		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
-	} else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
-	    /* StretchBlt? */
-	    /* XXX check if we want HALFTONE, based on the src filter */
-	    BOOL success;
-	    int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
-	    success = StretchBlt(dst->dc,
-				 dst_r.x, dst_r.y,
-				 dst_r.width, dst_r.height,
-				 src->dc,
-				 src_r.x, src_r.y,
-				 src_r.width, src_r.height,
-				 SRCCOPY);
-	    SetStretchBltMode(dst->dc, oldmode);
-
-	    if (!success)
-		return _cairo_win32_print_gdi_error ("StretchBlt");
-	}
-    } else if (needs_alpha && !needs_scale) {
-  	return _composite_alpha_blend (dst, src, alpha,
-				       src_r.x, src_r.y, src_r.width, src_r.height,
-				       dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* from pixman-private.h */
-#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
-
-static cairo_int_status_t
-_cairo_win32_surface_composite (cairo_operator_t	op,
-				const cairo_pattern_t	*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,
-				cairo_region_t	       *clip_region)
-{
-    cairo_win32_surface_t *dst = abstract_dst;
-    cairo_win32_surface_t *src;
-    cairo_surface_pattern_t *src_surface_pattern;
-    int alpha;
-    double scalex, scaley;
-    cairo_fixed_t x0_fixed, y0_fixed;
-    cairo_int_status_t status;
-
-    cairo_bool_t needs_alpha, needs_scale, needs_repeat;
-    cairo_image_surface_t *src_image = NULL;
-
-    cairo_format_t src_format;
-    cairo_rectangle_int_t src_extents;
-
-    cairo_rectangle_int_t src_r = { src_x, src_y, width, height };
-    cairo_rectangle_int_t dst_r = { dst_x, dst_y, width, height };
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "+++ composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
-	     op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
-#endif
-
-    /* If the destination can't do any of these, then
-     * we may as well give up, since this is what we'll
-     * look to for optimization.
-     */
-    if ((dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT |
-		       CAIRO_WIN32_SURFACE_CAN_ALPHABLEND |
-		       CAIRO_WIN32_SURFACE_CAN_STRETCHBLT |
-		       CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
-	== 0)
-    {
-	goto UNSUPPORTED;
-    }
-
-    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
-	goto UNSUPPORTED;
-
-    if (pattern->extend != CAIRO_EXTEND_NONE &&
-	pattern->extend != CAIRO_EXTEND_REPEAT)
-	goto UNSUPPORTED;
-
-    if (mask_pattern) {
-	/* FIXME: When we fully support RENDER style 4-channel
-	 * masks we need to check r/g/b != 1.0.
-	 */
-	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
-    } else {
-	alpha = 255;
-    }
-
-    src_surface_pattern = (cairo_surface_pattern_t *)pattern;
-    src = (cairo_win32_surface_t *)src_surface_pattern->surface;
-
-    if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE &&
-	dst->flags & (CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
-    {
-	/* In some very limited cases, we can use StretchDIBits to draw
-	 * an image surface directly:
-	 *  - source is CAIRO_FORMAT_ARGB32
-	 *  - dest is CAIRO_FORMAT_ARGB32
-	 *  - alpha is 255
-	 *  - operator is SOURCE or OVER
-	 *  - image stride is 4*width
-	 */
-	src_image = (cairo_image_surface_t*) src;
-
-	if (src_image->format != CAIRO_FORMAT_RGB24 ||
-	    dst->format != CAIRO_FORMAT_RGB24 ||
-	    alpha != 255 ||
-	    (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
-	    src_image->stride != (src_image->width * 4))
-	{
-	    goto UNSUPPORTED;
-	}
-
-	src_format = src_image->format;
-	src_extents.x = 0;
-	src_extents.y = 0;
-	src_extents.width = src_image->width;
-	src_extents.height = src_image->height;
-    } else if (src->base.backend != dst->base.backend) {
-	goto UNSUPPORTED;
-    } else {
-	src_format = src->format;
-	src_extents = src->extents;
-    }
-
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "Before check: src size: (%d %d) xy [%d %d] -> dst [%d %d %d %d] {srcmat %f %f %f %f}\n",
-	     src_extents.width, src_extents.height,
-	     src_x, src_y,
-	     dst_x, dst_y, width, height,
-	     pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy);
-#endif
-
-    /* We can only use GDI functions if the source and destination rectangles
-     * are on integer pixel boundaries.  Figure that out here.
-     */
-    x0_fixed = _cairo_fixed_from_double(pattern->matrix.x0 / pattern->matrix.xx);
-    y0_fixed = _cairo_fixed_from_double(pattern->matrix.y0 / pattern->matrix.yy);
-
-    if (pattern->matrix.yx != 0.0 ||
-	pattern->matrix.xy != 0.0 ||
-	!_cairo_fixed_is_integer(x0_fixed) ||
-	!_cairo_fixed_is_integer(y0_fixed))
-    {
-	goto UNSUPPORTED;
-    }
-
-    scalex = pattern->matrix.xx;
-    scaley = pattern->matrix.yy;
-
-    src_r.x += _cairo_fixed_integer_part(x0_fixed);
-    src_r.y += _cairo_fixed_integer_part(y0_fixed);
-
-    /* Success, right? */
-    if (scalex == 0.0 || scaley == 0.0)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (scalex != 1.0 || scaley != 1.0)
-	goto UNSUPPORTED;
-
-    /* If the src coordinates are outside of the source surface bounds,
-     * we have to fix them up, because this is an error for the GDI
-     * functions.
-     */
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "before: [%d %d %d %d] -> [%d %d %d %d]\n",
-	     src_r.x, src_r.y, src_r.width, src_r.height,
-	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    fflush (stderr);
-#endif
-
-    /* If the src rectangle doesn't wholly lie within the src extents,
-     * fudge things.  We really need to do fixup on the unpainted
-     * region -- e.g. the SOURCE operator is broken for areas outside
-     * of the extents, because it won't clear that area to transparent
-     * black.
-     */
-
-    if (pattern->extend != CAIRO_EXTEND_REPEAT) {
-	needs_repeat = FALSE;
-
-	/* If the src rect and the extents of the source image don't overlap at all,
-	 * we can't do anything useful here.
-	 */
-	if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
-	    (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
-	{
-	    if (op == CAIRO_OPERATOR_OVER)
-		return CAIRO_STATUS_SUCCESS;
-	    goto UNSUPPORTED;
-	}
-
-	if (src_r.x < 0) {
-	    src_r.width += src_r.x;
-	    src_r.x = 0;
-
-	    dst_r.width += src_r.x;
-	    dst_r.x -= src_r.x;
-	}
-
-	if (src_r.y < 0) {
-	    src_r.height += src_r.y;
-	    src_r.y = 0;
-
-	    dst_r.height += dst_r.y;
-	    dst_r.y -= src_r.y;
-	}
-
-	if (src_r.x + src_r.width > src_extents.width) {
-	    src_r.width = src_extents.width - src_r.x;
-	    dst_r.width = src_r.width;
-	}
-
-	if (src_r.y + src_r.height > src_extents.height) {
-	    src_r.height = src_extents.height - src_r.y;
-	    dst_r.height = src_r.height;
-	}
-    } else {
-	needs_repeat = TRUE;
-    }
-
-    /*
-     * Operations that we can do:
-     *
-     *  RGB OVER  RGB -> BitBlt (same as SOURCE)
-     *  RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
-     * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
-     * ARGB OVER  RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
-     * 
-     *  RGB OVER  RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
-     *  RGB OVER ARGB + mask -> UNSUPPORTED
-     * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
-     * ARGB OVER  RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
-     * 
-     *  RGB SOURCE  RGB -> BitBlt
-     *  RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
-     * ARGB SOURCE ARGB -> BitBlt
-     * ARGB SOURCE  RGB -> BitBlt
-     * 
-     *  RGB SOURCE  RGB + mask -> unsupported
-     *  RGB SOURCE ARGB + mask -> unsupported
-     * ARGB SOURCE ARGB + mask -> unsupported
-     * ARGB SOURCE  RGB + mask -> unsupported
-     */
-
-    /*
-     * Figure out what action to take.
-     */
-    if (op == CAIRO_OPERATOR_OVER) {
-	if (alpha == 0)
-	    return CAIRO_STATUS_SUCCESS;
-
-	if (src_format == dst->format) {
-	    if (alpha == 255 && src_format == CAIRO_FORMAT_RGB24) {
-		needs_alpha = FALSE;
-	    } else {
-		needs_alpha = TRUE;
-	    }
-	} else if (src_format == CAIRO_FORMAT_ARGB32 &&
-		   dst->format == CAIRO_FORMAT_RGB24)
-	{
-	    needs_alpha = TRUE;
-	} else {
-	    goto UNSUPPORTED;
-	}
-    } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
-	if ((src_format == dst->format) ||
-	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
-	{
-	    needs_alpha = FALSE;
-	} else {
-	    goto UNSUPPORTED;
-	}
-    } else {
-	goto UNSUPPORTED;
-    }
-
-    if (scalex == 1.0 && scaley == 1.0) {
-	needs_scale = FALSE;
-    } else {
-	/* Should never be reached until we turn StretchBlt back on */
-	needs_scale = TRUE;
-    }
-
-#ifdef DEBUG_COMPOSITE
-    fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
-	     src_r.x, src_r.y, src_r.width, src_r.height,
-	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
-    fflush (stderr);
-#endif
-
-    status = _cairo_win32_surface_set_clip_region (dst, clip_region);
-    if (status)
-	return status;
-
-    /* If we need to repeat, we turn the repeated blit into
-     * a bunch of piece-by-piece blits.
-     */
-    if (needs_repeat) {
-	cairo_rectangle_int_t piece_src_r, piece_dst_r;
-	uint32_t rendered_width = 0, rendered_height = 0;
-	uint32_t to_render_height, to_render_width;
-	int32_t piece_x, piece_y;
-	int32_t src_start_x = MOD(src_r.x, src_extents.width);
-	int32_t src_start_y = MOD(src_r.y, src_extents.height);
-
-	if (needs_scale)
-	    goto UNSUPPORTED;
-
-	/* If both the src and dest have an image, we may as well fall
-	 * back, because it will be faster than our separate blits.
-	 * Our blit code will be fastest when the src is a DDB and the
-	 * destination is a DDB.
-	 */
-	if ((src_image || src->image) && dst->image)
-	    goto UNSUPPORTED;
-
-	/* If the src is not a bitmap but an on-screen (or unknown)
-	 * DC, chances are that fallback will be faster.
-	 */
-	if (src->bitmap == NULL)
-	    goto UNSUPPORTED;
-
-	/* If we can use PatBlt, just do so */
-	if (!src_image && !needs_alpha)
-	{
-	    HBRUSH brush;
-	    HGDIOBJ old_brush;
-	    POINT old_brush_origin;
-
-	    /* Set up the brush with our bitmap */
-	    brush = CreatePatternBrush (src->bitmap);
-
-	    /* SetBrushOrgEx sets the coordinates in the destination DC of where the
-	     * pattern should start.
-	     */
-	    SetBrushOrgEx (dst->dc, dst_r.x - src_start_x,
-			   dst_r.y - src_start_y, &old_brush_origin);
-
-	    old_brush = SelectObject (dst->dc, brush);
-
-	    PatBlt (dst->dc, dst_r.x, dst_r.y, dst_r.width, dst_r.height, PATCOPY);
-
-	    /* Restore the old brush and pen */
-	    SetBrushOrgEx (dst->dc, old_brush_origin.x, old_brush_origin.y, NULL);
-	    SelectObject (dst->dc, old_brush);
-	    DeleteObject (brush);
-
-	    return CAIRO_STATUS_SUCCESS;
-	}
-
-	/* If we were not able to use PatBlt, then manually expand out the blit */
-
-	/* Arbitrary factor; we think that going through
-	 * fallback will be faster if we have to do more
-	 * than this amount of blits in either direction.
-	 */
-	if (dst_r.width / src_extents.width > 5 ||
-	    dst_r.height / src_extents.height > 5)
-	    goto UNSUPPORTED;
-
-	for (rendered_height = 0;
-	     rendered_height < dst_r.height;
-	     rendered_height += to_render_height)
-	{
-	    piece_y = (src_start_y + rendered_height) % src_extents.height;
-	    to_render_height = src_extents.height - piece_y;
-
-	    if (rendered_height + to_render_height > dst_r.height)
-		to_render_height = dst_r.height - rendered_height;
-
-	    for (rendered_width = 0;
-		 rendered_width < dst_r.width;
-		 rendered_width += to_render_width)
-	    {
-		piece_x = (src_start_x + rendered_width) % src_extents.width;
-		to_render_width = src_extents.width - piece_x;
-
-		if (rendered_width + to_render_width > dst_r.width)
-		    to_render_width = dst_r.width - rendered_width;
-
-		piece_src_r.x = piece_x;
-		piece_src_r.y = piece_y;
-		piece_src_r.width = to_render_width;
-		piece_src_r.height = to_render_height;
-
-		piece_dst_r.x = dst_r.x + rendered_width;
-		piece_dst_r.y = dst_r.y + rendered_height;
-		piece_dst_r.width = to_render_width;
-		piece_dst_r.height = to_render_height;
-
-		status = _cairo_win32_surface_composite_inner (src, src_image, dst,
-							       src_extents, piece_src_r, piece_dst_r,
-							       alpha, needs_alpha, needs_scale);
-		if (status != CAIRO_STATUS_SUCCESS) {
-		    /* Uh oh.  If something failed, and it's the first
-		     * piece, then we can jump to UNSUPPORTED. 
-		     * Otherwise, this is bad times, because part of the
-		     * rendering was already done. */
-		    if (rendered_width == 0 &&
-			rendered_height == 0)
-		    {
-			goto UNSUPPORTED;
-		    }
-
-		    return status;
-		}
-	    }
-	}
-    } else {
-	status = _cairo_win32_surface_composite_inner (src, src_image, dst,
-						       src_extents, src_r, dst_r,
-						       alpha, needs_alpha, needs_scale);
-    }
-
-    if (status == CAIRO_STATUS_SUCCESS)
-	return status;
-
-UNSUPPORTED:
-    /* Fall back to image surface directly, if this is a DIB surface */
-    if (dst->image) {
-	GdiFlush();
-
-#if 0
-	return dst->image->backend->composite (op, pattern, mask_pattern,
-					       dst->image,
-					       src_x, src_y,
-					       mask_x, mask_y,
-					       dst_x, dst_y,
-					       width, height,
-					       clip_region);
-#endif
-    }
-
-    return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-/* This big function tells us how to optimize operators for the
- * case of solid destination and constant-alpha source
- *
- * Note: This function needs revisiting if we add support for
- *       super-luminescent colors (a == 0, r,g,b > 0)
- */
-static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED }
-categorize_solid_dest_operator (cairo_operator_t op,
-				unsigned short   alpha)
-{
-    enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source;
-
-    if (alpha >= 0xff00)
-	source = SOURCE_SOLID;
-    else if (alpha < 0x100)
-	source = SOURCE_TRANSPARENT;
-    else
-	source = SOURCE_OTHER;
-
-    switch (op) {
-    case CAIRO_OPERATOR_CLEAR:    /* 0                 0 */
-    case CAIRO_OPERATOR_OUT:      /* 1 - Ab            0 */
-	return DO_CLEAR;
-	break;
-
-    case CAIRO_OPERATOR_SOURCE:   /* 1                 0 */
-    case CAIRO_OPERATOR_IN:       /* Ab                0 */
-	return DO_SOURCE;
-	break;
-
-    case CAIRO_OPERATOR_OVER:     /* 1            1 - Aa */
-    case CAIRO_OPERATOR_ATOP:     /* Ab           1 - Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_SOURCE;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_DEST_OUT: /* 0            1 - Aa */
-    case CAIRO_OPERATOR_XOR:      /* 1 - Ab       1 - Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_CLEAR;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-    	break;
-
-    case CAIRO_OPERATOR_DEST:     /* 0                 1 */
-    case CAIRO_OPERATOR_DEST_OVER:/* 1 - Ab            1 */
-    case CAIRO_OPERATOR_SATURATE: /* min(1,(1-Ab)/Aa)  1 */
-	return DO_NOTHING;
-	break;
-
-    case CAIRO_OPERATOR_DEST_IN:  /* 0                Aa */
-    case CAIRO_OPERATOR_DEST_ATOP:/* 1 - Ab           Aa */
-	if (source == SOURCE_SOLID)
-	    return DO_NOTHING;
-	else if (source == SOURCE_TRANSPARENT)
-	    return DO_CLEAR;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_ADD:	  /* 1                1 */
-	if (source == SOURCE_TRANSPARENT)
-	    return DO_NOTHING;
-	else
-	    return DO_UNSUPPORTED;
-	break;
-
-    case CAIRO_OPERATOR_MULTIPLY:
-    case CAIRO_OPERATOR_SCREEN:
-    case CAIRO_OPERATOR_OVERLAY:
-    case CAIRO_OPERATOR_DARKEN:
-    case CAIRO_OPERATOR_LIGHTEN:
-    case CAIRO_OPERATOR_COLOR_DODGE:
-    case CAIRO_OPERATOR_COLOR_BURN:
-    case CAIRO_OPERATOR_HARD_LIGHT:
-    case CAIRO_OPERATOR_SOFT_LIGHT:
-    case CAIRO_OPERATOR_DIFFERENCE:
-    case CAIRO_OPERATOR_EXCLUSION:
-    case CAIRO_OPERATOR_HSL_HUE:
-    case CAIRO_OPERATOR_HSL_SATURATION:
-    case CAIRO_OPERATOR_HSL_COLOR:
-    case CAIRO_OPERATOR_HSL_LUMINOSITY:
-	return DO_UNSUPPORTED;
-
-    default:
-	ASSERT_NOT_REACHED;
-	return DO_UNSUPPORTED;
-    }
-}
-
-static cairo_int_status_t
-_cairo_win32_surface_fill_rectangles (void			*abstract_surface,
-				      cairo_operator_t		op,
-				      const cairo_color_t	*color,
-				      cairo_rectangle_int_t	*rects,
-				      int			num_rects)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-    cairo_status_t status;
-    COLORREF new_color;
-    HBRUSH new_brush;
-    int i;
-
-    /* XXXperf If it's not RGB24, we need to do a little more checking
-     * to figure out when we can use GDI.  We don't have that checking
-     * anywhere at the moment, so just bail and use the fallback
-     * paths. */
-    if (surface->format != CAIRO_FORMAT_RGB24)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_win32_surface_set_clip_region (surface, NULL);
-    if (status)
-	return status;
-
-    /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
-     * surfaces with alpha.)
-     */
-    switch (categorize_solid_dest_operator (op, color->alpha_short)) {
-    case DO_CLEAR:
-	new_color = RGB (0, 0, 0);
-	break;
-    case DO_SOURCE:
-	new_color = RGB (color->red_short >> 8, color->green_short >> 8, color->blue_short >> 8);
-	break;
-    case DO_NOTHING:
-	return CAIRO_STATUS_SUCCESS;
-    case DO_UNSUPPORTED:
-    default:
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    new_brush = CreateSolidBrush (new_color);
-    if (!new_brush)
-	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
-
-    for (i = 0; i < num_rects; i++) {
-	RECT rect;
-
-	rect.left = rects[i].x;
-	rect.top = rects[i].y;
-	rect.right = rects[i].x + rects[i].width;
-	rect.bottom = rects[i].y + rects[i].height;
-
-	if (!FillRect (surface->dc, &rect, new_brush))
-	    goto FAIL;
-    }
-
-    DeleteObject (new_brush);
-
-    return CAIRO_STATUS_SUCCESS;
-
- FAIL:
-    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
-
-    DeleteObject (new_brush);
-
-    return status;
-}
-
-cairo_bool_t
-_cairo_win32_surface_get_extents (void		          *abstract_surface,
-				  cairo_rectangle_int_t   *rectangle)
-{
-    cairo_win32_surface_t *surface = abstract_surface;
-
-    *rectangle = surface->extents;
-    return TRUE;
-}
-
-static cairo_status_t
-_cairo_win32_surface_flush (void *abstract_surface)
-{
-    return _cairo_win32_surface_set_clip_region (abstract_surface, NULL);
-}
-
-#define STACK_GLYPH_SIZE 256
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs_internal (void			 *surface,
-					   cairo_operator_t	  op,
-					   const cairo_pattern_t *source,
-					   cairo_glyph_t	 *glyphs,
-					   int			  num_glyphs,
-					   cairo_scaled_font_t	 *scaled_font,
-					   const cairo_clip_t	 *clip,
-					   cairo_bool_t		  glyph_indexing)
-{
-#if CAIRO_HAS_WIN32_FONT
-    cairo_win32_surface_t *dst = surface;
-
-    WORD glyph_buf_stack[STACK_GLYPH_SIZE];
-    WORD *glyph_buf = glyph_buf_stack;
-    int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
-    int *dxy_buf = dxy_buf_stack;
-
-    BOOL win_result = 0;
-    int i, j;
-
-    cairo_solid_pattern_t *solid_pattern;
-    COLORREF color;
-
-    cairo_matrix_t device_to_logical;
-
-    int start_x, start_y;
-    double user_x, user_y;
-    int logical_x, logical_y;
-    unsigned int glyph_index_option;
-
-    /* We can only handle win32 fonts */
-    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* We can only handle opaque solid color sources */
-    if (!_cairo_pattern_is_opaque_solid(source))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* We can only handle operator SOURCE or OVER with the destination
-     * having no alpha */
-    if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
-	(dst->format != CAIRO_FORMAT_RGB24))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* If we have a fallback mask clip set on the dst, we have
-     * to go through the fallback path, but only if we're not
-     * doing this for printing */
-    if (clip != NULL) {
-	if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) {
-	    if (! _cairo_clip_is_region (clip))
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	    _cairo_win32_surface_set_clip_region (surface,
-						  _cairo_clip_get_region (clip));
-	}
-    }
-
-    solid_pattern = (cairo_solid_pattern_t *)source;
-    color = RGB(((int)solid_pattern->color.red_short) >> 8,
-		((int)solid_pattern->color.green_short) >> 8,
-		((int)solid_pattern->color.blue_short) >> 8);
-
-    cairo_win32_scaled_font_get_device_to_logical(scaled_font, &device_to_logical);
-
-    SaveDC(dst->dc);
-
-    cairo_win32_scaled_font_select_font(scaled_font, dst->dc);
-    SetTextColor(dst->dc, color);
-    SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT);
-    SetBkMode(dst->dc, TRANSPARENT);
-
-    if (num_glyphs > STACK_GLYPH_SIZE) {
-	glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
-        dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
-    }
-
-    /* It is vital that dx values for dxy_buf are calculated from the delta of
-     * _logical_ x coordinates (not user x coordinates) or else the sum of all
-     * previous dx values may start to diverge from the current glyph's x
-     * coordinate due to accumulated rounding error. As a result strings could
-     * be painted shorter or longer than expected. */
-
-    user_x = glyphs[0].x;
-    user_y = glyphs[0].y;
-
-    cairo_matrix_transform_point(&device_to_logical,
-                                 &user_x, &user_y);
-
-    logical_x = _cairo_lround (user_x);
-    logical_y = _cairo_lround (user_y);
-
-    start_x = logical_x;
-    start_y = logical_y;
-
-    for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
-        glyph_buf[i] = (WORD) glyphs[i].index;
-        if (i == num_glyphs - 1) {
-            dxy_buf[j] = 0;
-            dxy_buf[j+1] = 0;
-        } else {
-            double next_user_x = glyphs[i+1].x;
-            double next_user_y = glyphs[i+1].y;
-            int next_logical_x, next_logical_y;
-
-            cairo_matrix_transform_point(&device_to_logical,
-                                         &next_user_x, &next_user_y);
-
-            next_logical_x = _cairo_lround (next_user_x);
-            next_logical_y = _cairo_lround (next_user_y);
-
-            dxy_buf[j] = _cairo_lround (next_logical_x - logical_x);
-            dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y);
-
-            logical_x = next_logical_x;
-            logical_y = next_logical_y;
-        }
-    }
-
-    if (glyph_indexing)
-	glyph_index_option = ETO_GLYPH_INDEX;
-    else
-	glyph_index_option = 0;
-
-    win_result = ExtTextOutW(dst->dc,
-                             start_x,
-                             start_y,
-                             glyph_index_option | ETO_PDY,
-                             NULL,
-                             glyph_buf,
-                             num_glyphs,
-                             dxy_buf);
-    if (!win_result) {
-        _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
-    }
-
-    RestoreDC(dst->dc, -1);
-
-    if (glyph_buf != glyph_buf_stack) {
-	free(glyph_buf);
-        free(dxy_buf);
-    }
-    return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
-#else
-    return CAIRO_INT_STATUS_UNSUPPORTED;
-#endif
-}
-
-#undef STACK_GLYPH_SIZE
-
-cairo_int_status_t
-_cairo_win32_surface_show_glyphs (void			*surface,
-				  cairo_operator_t	 op,
-				  const cairo_pattern_t *source,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font,
-				  const cairo_clip_t    *clip)
-{
-    return _cairo_win32_surface_show_glyphs_internal (surface,
-						      op,
-						      source,
-						      glyphs,
-						      num_glyphs,
-						      scaled_font,
-						      clip,
-						      TRUE);
-}
-
-
-/**
- * cairo_win32_surface_create:
- * @hdc: the DC to create a surface for
- *
- * Creates a cairo surface that targets the given DC.  The DC will be
- * queried for its initial clip extents, and this will be used as the
- * size of the cairo surface.  The resulting surface will always be of
- * format %CAIRO_FORMAT_RGB24; should you need another surface format,
- * you will need to create one through
- * cairo_win32_surface_create_with_dib().
- *
- * Return value: the newly created surface
- **/
-cairo_surface_t *
-cairo_win32_surface_create (HDC hdc)
-{
-    cairo_win32_surface_t *surface;
-
-    cairo_format_t format;
-    RECT rect;
-
-    /* Assume that everything coming in as a HDC is RGB24 */
-    format = CAIRO_FORMAT_RGB24;
-
-    surface = malloc (sizeof (cairo_win32_surface_t));
-    if (surface == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
-	free (surface);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    surface->clip_region = NULL;
-    surface->image = NULL;
-    surface->format = format;
-
-    surface->dc = hdc;
-    surface->bitmap = NULL;
-    surface->is_dib = FALSE;
-    surface->saved_dc_bitmap = NULL;
-    surface->brush = NULL;
-    surface->old_brush = NULL;
-    surface->font_subsets = NULL;
-
-    GetClipBox(hdc, &rect);
-    surface->extents.x = rect.left;
-    surface->extents.y = rect.top;
-    surface->extents.width = rect.right - rect.left;
-    surface->extents.height = rect.bottom - rect.top;
-
-    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
-
-    _cairo_surface_init (&surface->base,
-			 &cairo_win32_surface_backend,
-			 NULL, /* device */
-			 _cairo_content_from_format (format));
-
-    return (cairo_surface_t *)surface;
-}
-
-/**
- * cairo_win32_surface_create_with_dib:
- * @format: format of pixels in the surface to create
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
- *
- * Creates a device-independent-bitmap surface not associated with
- * any particular existing surface or device context. The created
- * bitmap will be uninitialized.
- *
- * Return value: the newly created surface
- *
- * Since: 1.2
- **/
-cairo_surface_t *
-cairo_win32_surface_create_with_dib (cairo_format_t format,
-				     int	    width,
-				     int	    height)
-{
-    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
-}
-
-/**
- * cairo_win32_surface_create_with_ddb:
- * @hdc: a DC compatible with the surface to create
- * @format: format of pixels in the surface to create
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
- *
- * Creates a device-dependent-bitmap surface not associated with
- * any particular existing surface or device context. The created
- * bitmap will be uninitialized.
- *
- * Return value: the newly created surface
- *
- * Since: 1.4
- **/
-cairo_surface_t *
-cairo_win32_surface_create_with_ddb (HDC hdc,
-				     cairo_format_t format,
-				     int width,
-				     int height)
-{
-    cairo_win32_surface_t *new_surf;
-    HBITMAP ddb;
-    HDC screen_dc, ddb_dc;
-    HBITMAP saved_dc_bitmap;
-
-    if (format != CAIRO_FORMAT_RGB24)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-/* XXX handle these eventually
-	format != CAIRO_FORMAT_A8 ||
-	format != CAIRO_FORMAT_A1)
-*/
-
-    if (!hdc) {
-	screen_dc = GetDC (NULL);
-	hdc = screen_dc;
-    } else {
-	screen_dc = NULL;
-    }
-
-    ddb_dc = CreateCompatibleDC (hdc);
-    if (ddb_dc == NULL) {
-	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-	goto FINISH;
-    }
-
-    ddb = CreateCompatibleBitmap (hdc, width, height);
-    if (ddb == NULL) {
-	DeleteDC (ddb_dc);
-
-	/* Note that if an app actually does hit this out of memory
-	 * condition, it's going to have lots of other issues, as
-	 * video memory is probably exhausted.  However, it can often
-	 * continue using DIBs instead of DDBs.
-	 */
-	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-	goto FINISH;
-    }
-
-    saved_dc_bitmap = SelectObject (ddb_dc, ddb);
-
-    new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
-    new_surf->bitmap = ddb;
-    new_surf->saved_dc_bitmap = saved_dc_bitmap;
-    new_surf->is_dib = FALSE;
-
-FINISH:
-    if (screen_dc)
-	ReleaseDC (NULL, screen_dc);
-
-    return (cairo_surface_t*) new_surf;
-}
-
-/**
- * _cairo_surface_is_win32:
- * @surface: a #cairo_surface_t
- *
- * Checks if a surface is a win32 surface.  This will
- * return False if this is a win32 printing surface; use
- * _cairo_surface_is_win32_printing() to check for that.
- *
- * Return value: True if the surface is an win32 surface
- **/
-int
-_cairo_surface_is_win32 (cairo_surface_t *surface)
-{
-    return surface->backend == &cairo_win32_surface_backend;
-}
-
-/**
- * cairo_win32_surface_get_dc
- * @surface: a #cairo_surface_t
- *
- * Returns the HDC associated with this surface, or %NULL if none.
- * Also returns %NULL if the surface is not a win32 surface.
- *
- * A call to cairo_surface_flush() is required before using the HDC to
- * ensure that all pending drawing operations are finished and to
- * restore any temporary modification cairo has made to its state. A
- * call to cairo_surface_mark_dirty() is required after the state or
- * the content of the HDC has been modified.
- *
- * Return value: HDC or %NULL if no HDC available.
- *
- * Since: 1.2
- **/
-HDC
-cairo_win32_surface_get_dc (cairo_surface_t *surface)
-{
-    cairo_win32_surface_t *winsurf;
-
-    if (_cairo_surface_is_win32 (surface)){
-	winsurf = (cairo_win32_surface_t *) surface;
-
-	return winsurf->dc;
-    }
-
-    if (_cairo_surface_is_paginated (surface)) {
-	cairo_surface_t *target;
-
-	target = _cairo_paginated_surface_get_target (surface);
-
-	if (_cairo_surface_is_win32_printing (target)) {
-	    winsurf = (cairo_win32_surface_t *) target;
-
-	    return winsurf->dc;
-	}
-    }
-
-    return NULL;
-}
-
-/**
- * cairo_win32_surface_get_image
- * @surface: a #cairo_surface_t
- *
- * Returns a #cairo_surface_t image surface that refers to the same bits
- * as the DIB of the Win32 surface.  If the passed-in win32 surface
- * is not a DIB surface, %NULL is returned.
- *
- * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t),
- * or %NULL if the win32 surface is not a DIB.
- *
- * Since: 1.4
- */
-cairo_surface_t *
-cairo_win32_surface_get_image (cairo_surface_t *surface)
-{
-    if (!_cairo_surface_is_win32(surface))
-	return NULL;
-
-    return ((cairo_win32_surface_t*)surface)->image;
-}
-
-static const cairo_surface_backend_t cairo_win32_surface_backend = {
-    CAIRO_SURFACE_TYPE_WIN32,
-    _cairo_win32_surface_finish,
-
-    _cairo_default_context_create,
-
-    _cairo_win32_surface_create_similar,
-    NULL,
-    _cairo_win32_surface_map_to_image,
-    _cairo_win32_surface_unmap_image,
-
-    _cairo_surface_default_source,
-    _cairo_win32_surface_acquire_source_image,
-    _cairo_win32_surface_release_source_image,
-    NULL,  /* snapshot */
-
-    NULL, /* copy_page */
-    NULL, /* show_page */
-
-    _cairo_win32_surface_get_extents,
-    NULL, /* get_font_options */
-
-    _cairo_win32_surface_flush,
-    NULL, /* mark_dirty_rectangle */
-
-    NULL, /* paint */
-    NULL, /* mask */
-    NULL, /* stroke */
-    NULL, /* fill */
-    NULL, /* fill/stroke */
-    _cairo_win32_surface_show_glyphs,
-};
-
-/* Notes:
- *
- * Win32 alpha-understanding functions
- *
- * BitBlt - will copy full 32 bits from a 32bpp DIB to result
- *          (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
- *          (but not safe going RGB24->ARGB32, if RGB24 is also represented
- *           as a 32bpp DIB, since the alpha isn't discarded!)
- *
- * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
- *              it will still copy over the src alpha, because the SCA value (255) will be
- *              multiplied by all the src components.
- */
-
-
-cairo_int_status_t
-_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
-{
-    RECT rect;
-    int clipBoxType;
-    int gm;
-    XFORM saved_xform;
-
-    /* GetClipBox/GetClipRgn and friends interact badly with a world transform
-     * set.  GetClipBox returns values in logical (transformed) coordinates;
-     * it's unclear what GetClipRgn returns, because the region is empty in the
-     * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates.
-     * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn
-     * works in device units.
-     *
-     * So, avoid the whole mess and get rid of the world transform
-     * while we store our initial data and when we restore initial coordinates.
-     *
-     * XXX we may need to modify x/y by the ViewportOrg or WindowOrg
-     * here in GM_COMPATIBLE; unclear.
-     */
-    gm = GetGraphicsMode (hdc);
-    if (gm == GM_ADVANCED) {
-	GetWorldTransform (hdc, &saved_xform);
-	ModifyWorldTransform (hdc, NULL, MWT_IDENTITY);
-    }
-
-    clipBoxType = GetClipBox (hdc, &rect);
-    if (clipBoxType == ERROR) {
-	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
-	SetGraphicsMode (hdc, gm);
-	/* XXX: Can we make a more reasonable guess at the error cause here? */
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    surface->clip_rect.x = rect.left;
-    surface->clip_rect.y = rect.top;
-    surface->clip_rect.width = rect.right - rect.left;
-    surface->clip_rect.height = rect.bottom - rect.top;
-
-    surface->initial_clip_rgn = NULL;
-    surface->had_simple_clip = FALSE;
-
-    if (clipBoxType == COMPLEXREGION) {
-	surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
-	if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
-	    DeleteObject(surface->initial_clip_rgn);
-	    surface->initial_clip_rgn = NULL;
-	}
-    } else if (clipBoxType == SIMPLEREGION) {
-	surface->had_simple_clip = TRUE;
-    }
-
-    if (gm == GM_ADVANCED)
-	SetWorldTransform (hdc, &saved_xform);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface)
-{
-    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
-
-    XFORM saved_xform;
-    int gm = GetGraphicsMode (surface->dc);
-    if (gm == GM_ADVANCED) {
-	GetWorldTransform (surface->dc, &saved_xform);
-	ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY);
-    }
-
-    /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */
-    SelectClipRgn (surface->dc, surface->initial_clip_rgn);
-
-    if (surface->had_simple_clip) {
-	/* then if we had a simple clip, intersect */
-	IntersectClipRect (surface->dc,
-			   surface->clip_rect.x,
-			   surface->clip_rect.y,
-			   surface->clip_rect.x + surface->clip_rect.width,
-			   surface->clip_rect.y + surface->clip_rect.height);
-    }
-
-    if (gm == GM_ADVANCED)
-	SetWorldTransform (surface->dc, &saved_xform);
-
-    return status;
-}
-
-void
-_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
-{
-    RGNDATA *rd;
-    unsigned int z;
-
-    if (header)
-	fprintf (stderr, "%s\n", header);
-
-    if (rgn == NULL) {
-	fprintf (stderr, " NULL\n");
-    }
-
-    z = GetRegionData(rgn, 0, NULL);
-    rd = (RGNDATA*) malloc(z);
-    z = GetRegionData(rgn, z, rd);
-
-    fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n",
-	     rd->rdh.nCount,
-	     rd->rdh.rcBound.left,
-	     rd->rdh.rcBound.top,
-	     rd->rdh.rcBound.right - rd->rdh.rcBound.left,
-	     rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
-
-    for (z = 0; z < rd->rdh.nCount; z++) {
-	RECT r = ((RECT*)rd->Buffer)[z];
-	fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n",
-		 z, r.left, r.top, r.right - r.left, r.bottom - r.top);
-    }
-
-    free(rd);
-    fflush (stderr);
-}
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
new file mode 100644
index 0000000..73fc052
--- /dev/null
+++ b/src/win32/cairo-win32-font.c
@@ -0,0 +1,2437 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as GetGlyphIndices */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-win32-private.h"
+
+#include "cairo-array-private.h"
+#include "cairo-error-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+
+#include <wchar.h>
+
+#ifndef SPI_GETFONTSMOOTHINGTYPE
+#define SPI_GETFONTSMOOTHINGTYPE 0x200a
+#endif
+#ifndef FE_FONTSMOOTHINGCLEARTYPE
+#define FE_FONTSMOOTHINGCLEARTYPE 2
+#endif
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+#ifndef TT_PRIM_CSPLINE
+#define TT_PRIM_CSPLINE 3
+#endif
+
+#define CMAP_TAG 0x70616d63
+
+/**
+ * SECTION:cairo-win32-fonts
+ * @Title: Win32 Fonts
+ * @Short_Description: Font support for Microsoft Windows
+ * @See_Also: #cairo_font_face_t
+ *
+ * The Microsoft Windows font backend is primarily used to render text on
+ * Microsoft Windows systems.
+ */
+
+/**
+ * CAIRO_HAS_WIN32_FONT:
+ *
+ * Defined if the Microsoft Windows font backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ */
+
+const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend;
+
+typedef struct {
+    cairo_scaled_font_t base;
+
+    LOGFONTW logfont;
+
+    BYTE quality;
+
+    /* We do drawing and metrics computation in a "logical space" which
+     * is similar to font space, except that it is scaled by a factor
+     * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication
+     * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision.
+     */
+    double logical_scale;
+
+    /* The size we should actually request the font at from Windows; differs
+     * from the logical_scale because it is quantized for orthogonal
+     * transformations
+     */
+    double logical_size;
+
+    /* Transformations from device <=> logical space
+     */
+    cairo_matrix_t logical_to_device;
+    cairo_matrix_t device_to_logical;
+
+    /* We special case combinations of 90-degree-rotations, scales and
+     * flips ... that is transformations that take the axes to the
+     * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y
+     * encode the 8 possibilities for orientation (4 rotation angles with
+     * and without a flip), and scale_x, scale_y the scale components.
+     */
+    cairo_bool_t preserve_axes;
+    cairo_bool_t swap_axes;
+    cairo_bool_t swap_x;
+    cairo_bool_t swap_y;
+    double x_scale;
+    double y_scale;
+
+    /* The size of the design unit of the font
+     */
+    int em_square;
+
+    HFONT scaled_hfont;
+    HFONT unscaled_hfont;
+
+    cairo_bool_t is_bitmap;
+    cairo_bool_t is_type1;
+    cairo_bool_t delete_scaled_hfont;
+    cairo_bool_t has_type1_notdef_index;
+    unsigned long type1_notdef_index;
+} cairo_win32_scaled_font_t;
+
+static cairo_status_t
+_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
+					     cairo_scaled_glyph_t      *scaled_glyph);
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
+                                             cairo_scaled_glyph_t      *scaled_glyph);
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
+					  cairo_scaled_glyph_t      *scaled_glyph);
+
+static void
+_cairo_win32_font_face_destroy (void *abstract_face);
+
+
+#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
+
+static HDC
+_get_global_font_dc (void)
+{
+    static HDC hdc;
+
+    if (!hdc) {
+	hdc = CreateCompatibleDC (NULL);
+	if (!hdc) {
+	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
+	    return NULL;
+	}
+
+	if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
+	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
+	    DeleteDC (hdc);
+	    return NULL;
+	}
+    }
+
+    return hdc;
+}
+
+static cairo_status_t
+_compute_transform (cairo_win32_scaled_font_t *scaled_font,
+		    cairo_matrix_t            *sc)
+{
+    cairo_status_t status;
+
+    if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy) &&
+	    !NEARLY_ZERO(sc->xx) && !NEARLY_ZERO(sc->yy)) {
+	scaled_font->preserve_axes = TRUE;
+	scaled_font->x_scale = sc->xx;
+	scaled_font->swap_x = (sc->xx < 0);
+	scaled_font->y_scale = sc->yy;
+	scaled_font->swap_y = (sc->yy < 0);
+	scaled_font->swap_axes = FALSE;
+
+    } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy) &&
+	    !NEARLY_ZERO(sc->yx) && !NEARLY_ZERO(sc->xy)) {
+	scaled_font->preserve_axes = TRUE;
+	scaled_font->x_scale = sc->yx;
+	scaled_font->swap_x = (sc->yx < 0);
+	scaled_font->y_scale = sc->xy;
+	scaled_font->swap_y = (sc->xy < 0);
+	scaled_font->swap_axes = TRUE;
+
+    } else {
+	scaled_font->preserve_axes = FALSE;
+	scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE;
+    }
+
+    if (scaled_font->preserve_axes) {
+	if (scaled_font->swap_x)
+	    scaled_font->x_scale = - scaled_font->x_scale;
+	if (scaled_font->swap_y)
+	    scaled_font->y_scale = - scaled_font->y_scale;
+
+	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
+	scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
+                                    _cairo_lround (scaled_font->y_scale);
+    }
+
+    /* The font matrix has x and y "scale" components which we extract and
+     * use as character scale values.
+     */
+    cairo_matrix_init (&scaled_font->logical_to_device,
+		       sc->xx, sc->yx, sc->xy, sc->yy, 0, 0);
+
+    if (!scaled_font->preserve_axes) {
+	status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device,
+						      &scaled_font->x_scale, &scaled_font->y_scale,
+						      TRUE);	/* XXX: Handle vertical text */
+	if (status)
+	    return status;
+
+	scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
+                                                   scaled_font->y_scale);
+	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
+    }
+
+    cairo_matrix_scale (&scaled_font->logical_to_device,
+			1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
+
+    scaled_font->device_to_logical = scaled_font->logical_to_device;
+
+    status = cairo_matrix_invert (&scaled_font->device_to_logical);
+    if (status)
+	cairo_matrix_init_identity (&scaled_font->device_to_logical);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_have_cleartype_quality (void)
+{
+    OSVERSIONINFO version_info;
+
+    version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+
+    if (!GetVersionEx (&version_info)) {
+	_cairo_win32_print_gdi_error ("_have_cleartype_quality");
+	return FALSE;
+    }
+
+    return (version_info.dwMajorVersion > 5 ||
+	    (version_info.dwMajorVersion == 5 &&
+	     version_info.dwMinorVersion >= 1));	/* XP or newer */
+}
+
+static BYTE
+_get_system_quality (void)
+{
+    BOOL font_smoothing;
+    UINT smoothing_type;
+
+    if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
+	_cairo_win32_print_gdi_error ("_get_system_quality");
+	return DEFAULT_QUALITY;
+    }
+
+    if (font_smoothing) {
+	if (_have_cleartype_quality ()) {
+	    if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE,
+				       0, &smoothing_type, 0)) {
+		_cairo_win32_print_gdi_error ("_get_system_quality");
+		return DEFAULT_QUALITY;
+	    }
+
+	    if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
+		return CLEARTYPE_QUALITY;
+	}
+
+	return ANTIALIASED_QUALITY;
+    } else {
+	return DEFAULT_QUALITY;
+    }
+}
+
+/* If face_hfont is non-%NULL then font_matrix must be a simple scale by some
+ * factor S, ctm must be the identity, logfont->lfHeight must be -S,
+ * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
+ * all be 0, and face_hfont is the result of calling CreateFontIndirectW on
+ * logfont.
+ */
+static cairo_status_t
+_win32_scaled_font_create (LOGFONTW                   *logfont,
+			   HFONT                      face_hfont,
+			   cairo_font_face_t	      *font_face,
+			   const cairo_matrix_t       *font_matrix,
+			   const cairo_matrix_t       *ctm,
+			   const cairo_font_options_t *options,
+			   cairo_scaled_font_t       **font_out)
+{
+    HDC hdc;
+    cairo_win32_scaled_font_t *f;
+    cairo_matrix_t scale;
+    cairo_status_t status;
+
+    hdc = _get_global_font_dc ();
+    if (hdc == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    f = malloc (sizeof(cairo_win32_scaled_font_t));
+    if (f == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    f->logfont = *logfont;
+
+    /* We don't have any control over the hinting style or subpixel
+     * order in the Win32 font API, so we ignore those parts of
+     * cairo_font_options_t. We use the 'antialias' field to set
+     * the 'quality'.
+     *
+     * XXX: The other option we could pay attention to, but don't
+     *      here is the hint_metrics options.
+     */
+    if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
+	f->quality = _get_system_quality ();
+    else {
+	switch (options->antialias) {
+	case CAIRO_ANTIALIAS_NONE:
+	    f->quality = NONANTIALIASED_QUALITY;
+	    break;
+	case CAIRO_ANTIALIAS_GRAY:
+	case CAIRO_ANTIALIAS_FAST:
+	case CAIRO_ANTIALIAS_GOOD:
+	    f->quality = ANTIALIASED_QUALITY;
+	    break;
+	case CAIRO_ANTIALIAS_SUBPIXEL:
+	case CAIRO_ANTIALIAS_BEST:
+	    if (_have_cleartype_quality ())
+		f->quality = CLEARTYPE_QUALITY;
+	    else
+		f->quality = ANTIALIASED_QUALITY;
+	    break;
+	case CAIRO_ANTIALIAS_DEFAULT:
+	    ASSERT_NOT_REACHED;
+	}
+    }
+
+    f->em_square = 0;
+    f->scaled_hfont = NULL;
+    f->unscaled_hfont = NULL;
+    f->has_type1_notdef_index = FALSE;
+
+    if (f->quality == logfont->lfQuality ||
+        (logfont->lfQuality == DEFAULT_QUALITY &&
+         options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
+        /* If face_hfont is non-NULL, then we can use it to avoid creating our
+         * own --- because the constraints on face_hfont mentioned above
+         * guarantee it was created in exactly the same way that
+         * _win32_scaled_font_get_scaled_hfont would create it.
+         */
+        f->scaled_hfont = face_hfont;
+    }
+    /* don't delete the hfont if we're using the one passed in to us */
+    f->delete_scaled_hfont = !f->scaled_hfont;
+
+    cairo_matrix_multiply (&scale, font_matrix, ctm);
+    status = _compute_transform (f, &scale);
+    if (status)
+	goto FAIL;
+
+    status = _cairo_scaled_font_init (&f->base, font_face,
+				      font_matrix, ctm, options,
+				      &_cairo_win32_scaled_font_backend);
+    if (status)
+	goto FAIL;
+
+    status = _cairo_win32_scaled_font_set_metrics (f);
+    if (status) {
+	_cairo_scaled_font_fini (&f->base);
+	goto FAIL;
+    }
+
+    *font_out = &f->base;
+    return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+    free (f);
+    return status;
+}
+
+static cairo_status_t
+_win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
+					HDC                        hdc)
+{
+    XFORM xform;
+
+    _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
+
+    if (!SetWorldTransform (hdc, &xform))
+	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_win32_scaled_font_set_identity_transform (HDC hdc)
+{
+    if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY))
+	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font,
+				     HFONT *hfont_out)
+{
+    if (!scaled_font->scaled_hfont) {
+	LOGFONTW logfont = scaled_font->logfont;
+	logfont.lfHeight = -scaled_font->logical_size;
+	logfont.lfWidth = 0;
+	logfont.lfEscapement = 0;
+	logfont.lfOrientation = 0;
+	logfont.lfQuality = scaled_font->quality;
+
+	scaled_font->scaled_hfont = CreateFontIndirectW (&logfont);
+	if (!scaled_font->scaled_hfont)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont");
+    }
+
+    *hfont_out = scaled_font->scaled_hfont;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
+				       HDC                        hdc,
+				       HFONT			 *hfont_out)
+{
+    if (scaled_font->unscaled_hfont == NULL) {
+	OUTLINETEXTMETRIC *otm;
+	unsigned int otm_size;
+	HFONT scaled_hfont;
+	LOGFONTW logfont;
+	cairo_status_t status;
+
+	status = _win32_scaled_font_get_scaled_hfont (scaled_font,
+						      &scaled_hfont);
+	if (status)
+	    return status;
+
+	if (! SelectObject (hdc, scaled_hfont))
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
+
+	otm_size = GetOutlineTextMetrics (hdc, 0, NULL);
+	if (! otm_size)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
+
+	otm = malloc (otm_size);
+	if (otm == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	if (! GetOutlineTextMetrics (hdc, otm_size, otm)) {
+	    status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
+	    free (otm);
+	    return status;
+	}
+
+	scaled_font->em_square = otm->otmEMSquare;
+	free (otm);
+
+	logfont = scaled_font->logfont;
+	logfont.lfHeight = -scaled_font->em_square;
+	logfont.lfWidth = 0;
+	logfont.lfEscapement = 0;
+	logfont.lfOrientation = 0;
+	logfont.lfQuality = scaled_font->quality;
+
+	scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont);
+	if (! scaled_font->unscaled_hfont)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");
+    }
+
+    *hfont_out = scaled_font->unscaled_hfont;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
+					       HDC                  hdc)
+{
+    cairo_status_t status;
+    HFONT hfont;
+    HFONT old_hfont = NULL;
+
+    status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont);
+    if (status)
+	return status;
+
+    old_hfont = SelectObject (hdc, hfont);
+    if (!old_hfont)
+	return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
+
+    status = _win32_scaled_font_set_identity_transform (hdc);
+    if (status) {
+	SelectObject (hdc, old_hfont);
+	return status;
+    }
+
+    SetMapMode (hdc, MM_TEXT);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_bool_t
+_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
+{
+    cairo_win32_scaled_font_t *win32_scaled_font;
+
+    win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
+
+    return win32_scaled_font->is_type1;
+}
+
+cairo_bool_t
+_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font)
+{
+    cairo_win32_scaled_font_t *win32_scaled_font;
+
+    win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
+
+    return win32_scaled_font->is_bitmap;
+}
+
+static void
+_cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
+{
+}
+
+/* implement the font backend interface */
+
+static cairo_status_t
+_cairo_win32_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				       cairo_font_face_t      **font_face)
+{
+    LOGFONTW logfont;
+    uint16_t *face_name;
+    int face_name_len;
+    cairo_status_t status;
+
+    status = _cairo_utf8_to_utf16 (toy_face->family, -1,
+				   &face_name, &face_name_len);
+    if (status)
+	return status;
+
+    if (face_name_len > LF_FACESIZE - 1)
+	face_name_len = LF_FACESIZE - 1;
+
+    memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * face_name_len);
+    logfont.lfFaceName[face_name_len] = 0;
+    free (face_name);
+
+    logfont.lfHeight = 0;	/* filled in later */
+    logfont.lfWidth = 0;	/* filled in later */
+    logfont.lfEscapement = 0;	/* filled in later */
+    logfont.lfOrientation = 0;	/* filled in later */
+
+    switch (toy_face->weight) {
+    case CAIRO_FONT_WEIGHT_NORMAL:
+    default:
+	logfont.lfWeight = FW_NORMAL;
+	break;
+    case CAIRO_FONT_WEIGHT_BOLD:
+	logfont.lfWeight = FW_BOLD;
+	break;
+    }
+
+    switch (toy_face->slant) {
+    case CAIRO_FONT_SLANT_NORMAL:
+    default:
+	logfont.lfItalic = FALSE;
+	break;
+    case CAIRO_FONT_SLANT_ITALIC:
+    case CAIRO_FONT_SLANT_OBLIQUE:
+	logfont.lfItalic = TRUE;
+	break;
+    }
+
+    logfont.lfUnderline = FALSE;
+    logfont.lfStrikeOut = FALSE;
+    /* The docs for LOGFONT discourage using this, since the
+     * interpretation is locale-specific, but it's not clear what
+     * would be a better alternative.
+     */
+    logfont.lfCharSet = DEFAULT_CHARSET;
+    logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+    logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+    logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */
+    logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+    *font_face = cairo_win32_font_face_create_for_logfontw (&logfont);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_scaled_font_fini (void *abstract_font)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+
+    if (scaled_font == NULL)
+	return;
+
+    if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)
+	DeleteObject (scaled_font->scaled_hfont);
+
+    if (scaled_font->unscaled_hfont)
+	DeleteObject (scaled_font->unscaled_hfont);
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
+					       double		          x,
+					       double		          y,
+					       const char	         *utf8,
+					       cairo_glyph_t            **glyphs,
+					       int		         *num_glyphs)
+{
+    uint16_t *utf16;
+    int n16;
+    int i;
+    WORD *glyph_indices = NULL;
+    cairo_status_t status;
+    double x_pos, y_pos;
+    HDC hdc = NULL;
+    cairo_matrix_t mat;
+
+    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
+    if (status)
+	return status;
+
+    glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
+    if (!glyph_indices) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FAIL1;
+    }
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	goto FAIL2;
+
+    if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
+	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
+	goto FAIL3;
+    }
+
+    *num_glyphs = n16;
+    *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
+    if (!*glyphs) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FAIL3;
+    }
+
+    x_pos = x;
+    y_pos = y;
+
+    mat = scaled_font->base.ctm;
+    status = cairo_matrix_invert (&mat);
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    _cairo_scaled_font_freeze_cache (&scaled_font->base);
+
+    for (i = 0; i < n16; i++) {
+	cairo_scaled_glyph_t *scaled_glyph;
+
+	(*glyphs)[i].index = glyph_indices[i];
+	(*glyphs)[i].x = x_pos;
+	(*glyphs)[i].y = y_pos;
+
+	status = _cairo_scaled_glyph_lookup (&scaled_font->base,
+					     glyph_indices[i],
+					     CAIRO_SCALED_GLYPH_INFO_METRICS,
+					     &scaled_glyph);
+	if (status) {
+	    free (*glyphs);
+	    *glyphs = NULL;
+	    break;
+	}
+
+	x = scaled_glyph->x_advance;
+	y = scaled_glyph->y_advance;
+	cairo_matrix_transform_distance (&mat, &x, &y);
+	x_pos += x;
+	y_pos += y;
+    }
+
+    _cairo_scaled_font_thaw_cache (&scaled_font->base);
+
+FAIL3:
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+FAIL2:
+    free (glyph_indices);
+FAIL1:
+    free (utf16);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_text_to_glyphs (void		*abstract_font,
+					 double		x,
+					 double		y,
+					 const char	*utf8,
+					 cairo_glyph_t **glyphs,
+					 int		*num_glyphs)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    uint16_t *utf16;
+    int n16;
+    GCP_RESULTSW gcp_results;
+    unsigned int buffer_size, i;
+    WCHAR *glyph_indices = NULL;
+    int *dx = NULL;
+    cairo_status_t status;
+    double x_pos, y_pos;
+    double x_incr, y_incr;
+    HDC hdc = NULL;
+
+    /* GetCharacterPlacement() returns utf16 instead of glyph indices
+     * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
+    if (scaled_font->is_type1)
+	 return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
+							       x,
+							       y,
+							       utf8,
+							       glyphs,
+							       num_glyphs);
+
+    /* Compute a vector in user space along the baseline of length one logical space unit */
+    x_incr = 1;
+    y_incr = 0;
+    cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr);
+    x_incr /= scaled_font->logical_scale;
+    y_incr /= scaled_font->logical_scale;
+
+    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
+    if (status)
+	return status;
+
+    gcp_results.lStructSize = sizeof (GCP_RESULTS);
+    gcp_results.lpOutString = NULL;
+    gcp_results.lpOrder = NULL;
+    gcp_results.lpCaretPos = NULL;
+    gcp_results.lpClass = NULL;
+
+    buffer_size = MAX (n16 * 1.2, 16);		/* Initially guess number of chars plus a few */
+    if (buffer_size > INT_MAX) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FAIL1;
+    }
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	goto FAIL1;
+
+    while (TRUE) {
+	free (glyph_indices);
+	glyph_indices = NULL;
+
+	free (dx);
+	dx = NULL;
+
+	glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
+	dx = _cairo_malloc_ab (buffer_size, sizeof (int));
+	if (!glyph_indices || !dx) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto FAIL2;
+	}
+
+	gcp_results.nGlyphs = buffer_size;
+	gcp_results.lpDx = dx;
+	gcp_results.lpGlyphs = glyph_indices;
+
+	if (!GetCharacterPlacementW (hdc, utf16, n16,
+				     0,
+				     &gcp_results,
+				     GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) {
+	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs");
+	    goto FAIL2;
+	}
+
+	if (gcp_results.lpDx && gcp_results.lpGlyphs)
+	    break;
+
+	/* Too small a buffer, try again */
+
+	buffer_size += buffer_size / 2;
+	if (buffer_size > INT_MAX) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto FAIL2;
+	}
+    }
+
+    *num_glyphs = gcp_results.nGlyphs;
+    *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
+    if (!*glyphs) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FAIL2;
+    }
+
+    x_pos = x;
+    y_pos = y;
+
+    for (i = 0; i < gcp_results.nGlyphs; i++) {
+	(*glyphs)[i].index = glyph_indices[i];
+	(*glyphs)[i].x = x_pos ;
+	(*glyphs)[i].y = y_pos;
+
+	x_pos += x_incr * dx[i];
+	y_pos += y_incr * dx[i];
+    }
+
+ FAIL2:
+    free (glyph_indices);
+    free (dx);
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+ FAIL1:
+    free (utf16);
+
+    return status;
+}
+
+static unsigned long
+_cairo_win32_scaled_font_ucs4_to_index (void		*abstract_font,
+					uint32_t	 ucs4)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    wchar_t unicode[2];
+    WORD glyph_index;
+    HDC hdc = NULL;
+    cairo_status_t status;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return 0;
+
+    unicode[0] = ucs4;
+    unicode[1] = 0;
+    if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
+	_cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW");
+	glyph_index = 0;
+    }
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return glyph_index;
+}
+
+static cairo_status_t
+_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
+{
+    cairo_status_t status;
+    cairo_font_extents_t extents;
+
+    TEXTMETRIC metrics;
+    HDC hdc;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) {
+	/* For 90-degree rotations (including 0), we get the metrics
+	 * from the GDI in logical space, then convert back to font space
+	 */
+	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+	GetTextMetrics (hdc, &metrics);
+	cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+	extents.ascent = metrics.tmAscent / scaled_font->logical_scale;
+	extents.descent = metrics.tmDescent / scaled_font->logical_scale;
+
+	extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;
+	extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;
+	extents.max_y_advance = 0;
+
+    } else {
+	/* For all other transformations, we use the design metrics
+	 * of the font. The GDI results from GetTextMetrics() on a
+	 * transformed font are inexplicably large and we want to
+	 * avoid them.
+	 */
+	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+	GetTextMetrics (hdc, &metrics);
+	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
+
+	extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;
+	extents.descent = (double)metrics.tmDescent / scaled_font->em_square;
+	extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
+	extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
+	extents.max_y_advance = 0;
+
+    }
+
+    scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
+
+    /* Need to determine if this is a Type 1 font for the special
+     * handling in _text_to_glyphs.  Unlike TrueType or OpenType,
+     * Type1 fonts do not have a "cmap" table (or any other table).
+     * However GetFontData() will retrieve a Type1 font when
+     * requesting that GetFontData() retrieve data from the start of
+     * the file. This is to distinguish Type1 from stroke fonts such
+     * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant
+     * but improves performance for the most common fonts.
+     */
+    scaled_font->is_type1 = FALSE;
+    if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
+	(metrics.tmPitchAndFamily & TMPF_VECTOR))
+    {
+	 if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
+	     (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
+	 {
+	      scaled_font->is_type1 = TRUE;
+	 }
+    }
+
+    return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
+}
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
+					     cairo_scaled_glyph_t      *scaled_glyph)
+{
+    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
+    GLYPHMETRICS metrics;
+    cairo_status_t status;
+    cairo_text_extents_t extents;
+    HDC hdc;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    if (scaled_font->is_bitmap) {
+	/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
+	cairo_font_extents_t font_extents;
+	INT width = 0;
+	UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
+
+	cairo_scaled_font_extents (&scaled_font->base, &font_extents);
+
+	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+
+	if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
+	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
+	    width = 0;
+	}
+	cairo_win32_scaled_font_done_font (&scaled_font->base);
+	if (status)
+	    return status;
+
+	extents.x_bearing = 0;
+	extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale);
+	extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale);
+	extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
+	extents.x_advance = extents.width;
+	extents.y_advance = 0;
+    } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
+	/* If we aren't rotating / skewing the axes, then we get the metrics
+	 * from the GDI in device space and convert to font space.
+	 */
+	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+
+	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
+			      GGO_METRICS | GGO_GLYPH_INDEX,
+			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
+	    memset (&metrics, 0, sizeof (GLYPHMETRICS));
+	} else {
+	    if (metrics.gmBlackBoxX > 0 && scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE) {
+		/* The bounding box reported by Windows supposedly contains the glyph's "black" area;
+		 * however, antialiasing (especially with ClearType) means that the actual image that
+		 * needs to be rendered may "bleed" into the adjacent pixels, mainly on the right side.
+		 * To avoid clipping the glyphs when drawn by _cairo_surface_fallback_show_glyphs,
+		 * for example, or other code that uses glyph extents to determine the area to update,
+		 * we add a pixel of "slop" to left side of the nominal "black" area returned by GDI,
+		 * and two pixels to the right (as tests show some glyphs bleed into this column).
+		 */
+		metrics.gmptGlyphOrigin.x -= 1;
+		metrics.gmBlackBoxX += 3;
+	    }
+	}
+	cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+	if (scaled_font->swap_axes) {
+	    extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
+	    extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
+	    extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;
+	    extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;
+	    extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;
+	    extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;
+	} else {
+	    extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
+	    extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
+	    extents.width = metrics.gmBlackBoxX / scaled_font->x_scale;
+	    extents.height = metrics.gmBlackBoxY / scaled_font->y_scale;
+	    extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale;
+	    extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale;
+	}
+
+	if (scaled_font->swap_x) {
+	    extents.x_bearing = (- extents.x_bearing - extents.width);
+	    extents.x_advance = - extents.x_advance;
+	}
+
+	if (scaled_font->swap_y) {
+	    extents.y_bearing = (- extents.y_bearing - extents.height);
+	    extents.y_advance = - extents.y_advance;
+	}
+
+    } else {
+	/* For all other transformations, we use the design metrics
+	 * of the font.
+	 */
+	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+
+	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
+	                      GGO_METRICS | GGO_GLYPH_INDEX,
+			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
+	    memset (&metrics, 0, sizeof (GLYPHMETRICS));
+	}
+	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
+
+	extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
+	extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
+	extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
+	extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
+	extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
+	extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
+    }
+
+    _cairo_scaled_glyph_set_metrics (scaled_glyph,
+				     &scaled_font->base,
+				     &extents);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* Not currently used code, but may be useful in the future if we add
+ * back the capability to the scaled font backend interface to get the
+ * actual device space bbox rather than computing it from the
+ * font-space metrics.
+ */
+#if 0
+static cairo_status_t
+_cairo_win32_scaled_font_glyph_bbox (void		 *abstract_font,
+				     const cairo_glyph_t *glyphs,
+				     int                  num_glyphs,
+				     cairo_box_t         *bbox)
+{
+    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+    if (num_glyphs > 0) {
+	HDC hdc;
+	GLYPHMETRICS metrics;
+	cairo_status_t status;
+	int i;
+
+	hdc = _get_global_font_dc ();
+	assert (hdc != NULL);
+
+	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+
+	for (i = 0; i < num_glyphs; i++) {
+	    int x = _cairo_lround (glyphs[i].x);
+	    int y = _cairo_lround (glyphs[i].y);
+
+	    GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
+			     &metrics, 0, NULL, &matrix);
+
+	    if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
+		x1 = x + metrics.gmptGlyphOrigin.x;
+	    if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y)
+		y1 = y - metrics.gmptGlyphOrigin.y;
+	    if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX)
+		x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX;
+	    if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY)
+		y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY;
+	}
+
+	cairo_win32_scaled_font_done_font (&scaled_font->base);
+    }
+
+    bbox->p1.x = _cairo_fixed_from_int (x1);
+    bbox->p1.y = _cairo_fixed_from_int (y1);
+    bbox->p2.x = _cairo_fixed_from_int (x2);
+    bbox->p2.y = _cairo_fixed_from_int (y2);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
+typedef struct {
+    cairo_win32_scaled_font_t *scaled_font;
+    HDC hdc;
+
+    cairo_array_t glyphs;
+    cairo_array_t dx;
+
+    int start_x;
+    int last_x;
+    int last_y;
+} cairo_glyph_state_t;
+
+static void
+_start_glyphs (cairo_glyph_state_t        *state,
+	       cairo_win32_scaled_font_t  *scaled_font,
+	       HDC                         hdc)
+{
+    state->hdc = hdc;
+    state->scaled_font = scaled_font;
+
+    _cairo_array_init (&state->glyphs, sizeof (WCHAR));
+    _cairo_array_init (&state->dx, sizeof (int));
+}
+
+static cairo_status_t
+_flush_glyphs (cairo_glyph_state_t *state)
+{
+    cairo_status_t status;
+    int dx = 0;
+    WCHAR * elements;
+    int * dx_elements;
+
+    status = _cairo_array_append (&state->dx, &dx);
+    if (status)
+	return status;
+
+    elements = _cairo_array_index (&state->glyphs, 0);
+    dx_elements = _cairo_array_index (&state->dx, 0);
+    if (!ExtTextOutW (state->hdc,
+		      state->start_x, state->last_y,
+		      ETO_GLYPH_INDEX,
+		      NULL,
+		      elements,
+		      state->glyphs.num_elements,
+		      dx_elements)) {
+	return _cairo_win32_print_gdi_error ("_flush_glyphs");
+    }
+
+    _cairo_array_truncate (&state->glyphs, 0);
+    _cairo_array_truncate (&state->dx, 0);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_add_glyph (cairo_glyph_state_t *state,
+	    unsigned long        index,
+	    double               device_x,
+	    double               device_y)
+{
+    cairo_status_t status;
+    double user_x = device_x;
+    double user_y = device_y;
+    WCHAR glyph_index = index;
+    int logical_x, logical_y;
+
+    cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
+
+    logical_x = _cairo_lround (user_x);
+    logical_y = _cairo_lround (user_y);
+
+    if (state->glyphs.num_elements > 0) {
+	int dx;
+
+	if (logical_y != state->last_y) {
+	    status = _flush_glyphs (state);
+	    if (status)
+		return status;
+	    state->start_x = logical_x;
+	} else {
+	    dx = logical_x - state->last_x;
+	    status = _cairo_array_append (&state->dx, &dx);
+	    if (status)
+		return status;
+	}
+    } else {
+	state->start_x = logical_x;
+    }
+
+    state->last_x = logical_x;
+    state->last_y = logical_y;
+
+    status = _cairo_array_append (&state->glyphs, &glyph_index);
+    if (status)
+	return status;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_finish_glyphs (cairo_glyph_state_t *state)
+{
+    cairo_status_t status;
+
+    status = _flush_glyphs (state);
+
+    _cairo_array_fini (&state->glyphs);
+    _cairo_array_fini (&state->dx);
+
+    return status;
+}
+
+static cairo_status_t
+_draw_glyphs_on_surface (cairo_win32_surface_t     *surface,
+			 cairo_win32_scaled_font_t *scaled_font,
+			 COLORREF                   color,
+			 int                        x_offset,
+			 int                        y_offset,
+			 const cairo_glyph_t       *glyphs,
+			 int			    num_glyphs)
+{
+    cairo_glyph_state_t state;
+    cairo_status_t status, status2;
+    int i;
+
+    if (!SaveDC (surface->dc))
+	return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
+    if (status)
+	goto FAIL1;
+
+    SetTextColor (surface->dc, color);
+    SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT);
+    SetBkMode (surface->dc, TRANSPARENT);
+
+    _start_glyphs (&state, scaled_font, surface->dc);
+
+    for (i = 0; i < num_glyphs; i++) {
+	status = _add_glyph (&state, glyphs[i].index,
+			     glyphs[i].x - x_offset, glyphs[i].y - y_offset);
+	if (status)
+	    goto FAIL2;
+    }
+
+ FAIL2:
+    status2 = _finish_glyphs (&state);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+ FAIL1:
+    RestoreDC (surface->dc, -1);
+
+    return status;
+}
+
+/* Duplicate the green channel of a 4-channel mask in the alpha channel, then
+ * invert the whole mask.
+ */
+static void
+_compute_argb32_mask_alpha (cairo_win32_surface_t *mask_surface)
+{
+    cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
+    int i, j;
+
+    for (i = 0; i < image->height; i++) {
+	uint32_t *p = (uint32_t *) (image->data + i * image->stride);
+	for (j = 0; j < image->width; j++) {
+	    *p = 0xffffffff ^ (*p | ((*p & 0x0000ff00) << 16));
+	    p++;
+	}
+    }
+}
+
+/* Invert a mask
+ */
+static void
+_invert_argb32_mask (cairo_win32_surface_t *mask_surface)
+{
+    cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
+    int i, j;
+
+    for (i = 0; i < image->height; i++) {
+	uint32_t *p = (uint32_t *) (image->data + i * image->stride);
+	for (j = 0; j < image->width; j++) {
+	    *p = 0xffffffff ^ *p;
+	    p++;
+	}
+    }
+}
+
+/* Compute an alpha-mask from a monochrome RGB24 image
+ */
+static cairo_surface_t *
+_compute_a8_mask (cairo_win32_surface_t *mask_surface)
+{
+    cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
+    cairo_image_surface_t *image8;
+    int i, j;
+
+    if (image24->base.status)
+	return cairo_surface_reference (&image24->base);
+
+    image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
+								  image24->width, image24->height);
+    if (image8->base.status)
+	return &image8->base;
+
+    for (i = 0; i < image24->height; i++) {
+	uint32_t *p = (uint32_t *) (image24->data + i * image24->stride);
+	unsigned char *q = (unsigned char *) (image8->data + i * image8->stride);
+
+	for (j = 0; j < image24->width; j++) {
+	    *q = 255 - ((*p & 0x0000ff00) >> 8);
+	    p++;
+	    q++;
+	}
+    }
+
+    return &image8->base;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_glyph_init (void		       *abstract_font,
+				     cairo_scaled_glyph_t      *scaled_glyph,
+				     cairo_scaled_glyph_info_t  info)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    cairo_status_t status;
+
+    if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
+	status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
+	status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
+	status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+#if 0
+static cairo_int_status_t
+_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,
+				      cairo_region_t		*clip_region,
+				      int			*remaining_glyphs)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
+    cairo_status_t status;
+
+    if (width == 0 || height == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (_cairo_surface_is_win32 (generic_surface) &&
+	surface->format == CAIRO_FORMAT_RGB24 &&
+	op == CAIRO_OPERATOR_OVER &&
+	_cairo_pattern_is_opaque_solid (pattern)) {
+
+	cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern;
+
+	/* When compositing OVER on a GDI-understood surface, with a
+	 * solid opaque color, we can just call ExtTextOut directly.
+	 */
+	COLORREF new_color;
+
+	status = _cairo_win32_surface_set_clip_region (surface, clip_region);
+	if (unlikely (status))
+	    return status;
+
+	new_color = RGB (((int)solid_pattern->color.red_short) >> 8,
+			 ((int)solid_pattern->color.green_short) >> 8,
+			 ((int)solid_pattern->color.blue_short) >> 8);
+
+	return _draw_glyphs_on_surface (surface, scaled_font, new_color,
+					0, 0,
+					glyphs, num_glyphs);
+    } else {
+	/* Otherwise, we need to draw using software fallbacks. We create a mask
+	 * surface by drawing the the glyphs onto a DIB, black-on-white then
+	 * inverting. GDI outputs gamma-corrected images so inverted black-on-white
+	 * is very different from white-on-black. We favor the more common
+	 * case where the final output is dark-on-light.
+	 */
+	cairo_win32_surface_t *tmp_surface;
+	cairo_surface_t *mask_surface;
+	cairo_surface_pattern_t mask;
+	RECT r;
+
+	tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+	if (tmp_surface->base.status)
+	    return tmp_surface->base.status;
+
+	r.left = 0;
+	r.top = 0;
+	r.right = width;
+	r.bottom = height;
+	FillRect (tmp_surface->dc, &r, GetStockObject (WHITE_BRUSH));
+
+	status = _draw_glyphs_on_surface (tmp_surface,
+		                          scaled_font, RGB (0, 0, 0),
+					  dest_x, dest_y,
+					  glyphs, num_glyphs);
+	if (status) {
+	    cairo_surface_destroy (&tmp_surface->base);
+	    return status;
+	}
+
+	if (scaled_font->quality == CLEARTYPE_QUALITY) {
+	    /* For ClearType, we need a 4-channel mask. If we are compositing on
+	     * a surface with alpha, we need to compute the alpha channel of
+	     * the mask (we just copy the green channel). But for a destination
+	     * surface without alpha the alpha channel of the mask is ignored
+	     */
+
+	    if (surface->format != CAIRO_FORMAT_RGB24)
+		_compute_argb32_mask_alpha (tmp_surface);
+	    else
+		_invert_argb32_mask (tmp_surface);
+
+	    mask_surface = &tmp_surface->base;
+	} else {
+	    mask_surface = _compute_a8_mask (tmp_surface);
+	    cairo_surface_destroy (&tmp_surface->base);
+	    status = mask_surface->status;
+	    if (status)
+		return status;
+	}
+
+	/* For op == OVER, no-cleartype, a possible optimization here is to
+	 * draw onto an intermediate ARGB32 surface and alpha-blend that with the
+	 * destination
+	 */
+	_cairo_pattern_init_for_surface (&mask, mask_surface);
+	cairo_surface_destroy (mask_surface);
+
+	if (scaled_font->quality == CLEARTYPE_QUALITY)
+	    mask.base.has_component_alpha = TRUE;
+
+	status = _cairo_surface_mask (&surface->base, op, pattern, &mask.base,
+					   clip_region);
+
+	_cairo_pattern_fini (&mask.base);
+
+	return status;
+    }
+}
+#endif
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_load_truetype_table (void	       *abstract_font,
+                                             unsigned long      tag,
+                                             long               offset,
+                                             unsigned char     *buffer,
+                                             unsigned long     *length)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    HDC hdc;
+    cairo_status_t status;
+    DWORD ret;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return status;
+
+    ret = GetFontData (hdc, tag, offset, buffer, *length);
+    if (ret == GDI_ERROR || (buffer && ret != *length))
+        status = CAIRO_INT_STATUS_UNSUPPORTED;
+    else
+	*length = ret;
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_index_to_ucs4 (void		*abstract_font,
+					unsigned long    index,
+					uint32_t	*ucs4)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    GLYPHSET *glyph_set;
+    uint16_t *utf16 = NULL;
+    WORD *glyph_indices = NULL;
+    HDC hdc = NULL;
+    int res;
+    unsigned int i, j, num_glyphs;
+    cairo_status_t status;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return status;
+
+    res = GetFontUnicodeRanges(hdc, NULL);
+    if (res == 0) {
+	status = _cairo_win32_print_gdi_error (
+	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+	goto exit1;
+    }
+
+    glyph_set = malloc (res);
+    if (glyph_set == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto exit1;
+    }
+
+    res = GetFontUnicodeRanges(hdc, glyph_set);
+    if (res == 0) {
+	status = _cairo_win32_print_gdi_error (
+	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+	goto exit1;
+    }
+
+    *ucs4 = (uint32_t) -1;
+    for (i = 0; i < glyph_set->cRanges; i++) {
+	num_glyphs = glyph_set->ranges[i].cGlyphs;
+
+	utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
+	if (utf16 == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto exit1;
+	}
+
+	glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
+	if (glyph_indices == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto exit2;
+	}
+
+	for (j = 0; j < num_glyphs; j++)
+	    utf16[j] = glyph_set->ranges[i].wcLow + j;
+	utf16[j] = 0;
+
+	if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
+	    status = _cairo_win32_print_gdi_error (
+		"_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
+	    goto exit2;
+	}
+
+	for (j = 0; j < num_glyphs; j++) {
+	    if (glyph_indices[j] == index) {
+		*ucs4 = utf16[j];
+		goto exit2;
+	    }
+	}
+
+	free (glyph_indices);
+	glyph_indices = NULL;
+	free (utf16);
+	utf16 = NULL;
+    }
+
+exit2:
+    free (glyph_indices);
+    free (utf16);
+    free (glyph_set);
+exit1:
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return status;
+}
+
+static cairo_bool_t
+_cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    cairo_status_t status;
+    int	weight;
+    cairo_bool_t bold;
+    cairo_bool_t italic;
+
+    status = _cairo_truetype_get_style (&scaled_font->base,
+					&weight,
+					&bold,
+					&italic);
+    /* If this doesn't work assume it is not synthetic to avoid
+     * unneccessary subsetting fallbacks. */
+    if (status != CAIRO_STATUS_SUCCESS)
+	return FALSE;
+
+    if (scaled_font->logfont.lfWeight != weight ||
+	scaled_font->logfont.lfItalic != italic)
+	return TRUE;
+
+    return FALSE;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_index_to_glyph_name (void	      	*abstract_font,
+					      char             **glyph_names,
+					      int              	 num_glyph_names,
+					      unsigned long      glyph_index,
+					      unsigned long     *glyph_array_index)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    int i;
+
+    /* Windows puts .notdef at index 0 then numbers the remaining
+     * glyphs starting from 1 in the order they appear in the font. */
+
+    /* Find the position of .notdef in the list of glyph names. We
+     * only need to do this once per scaled font. */
+    if (! scaled_font->has_type1_notdef_index) {
+	for (i = 0; i < num_glyph_names; i++) {
+	    if (strcmp (glyph_names[i], ".notdef") == 0) {
+		scaled_font->type1_notdef_index = i;
+		scaled_font->has_type1_notdef_index = TRUE;
+		break;
+	    }
+	}
+	if (! scaled_font->has_type1_notdef_index)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* Once we know the position of .notdef the position of any glyph
+     * in the font can easily be obtained. */
+    if (glyph_index == 0)
+	*glyph_array_index = scaled_font->type1_notdef_index;
+    else if (glyph_index <= scaled_font->type1_notdef_index)
+	*glyph_array_index = glyph_index - 1;
+    else if (glyph_index < num_glyph_names)
+	*glyph_array_index = glyph_index;
+    else
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_load_type1_data (void	            *abstract_font,
+					  long               offset,
+					  unsigned char     *buffer,
+					  unsigned long     *length)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+
+    if (! scaled_font->is_type1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Using the tag 0 retrieves the entire font file. This works with
+     * Type 1 fonts as well as TTF/OTF fonts. */
+    return _cairo_win32_scaled_font_load_truetype_table (scaled_font,
+							 0,
+							 offset,
+							 buffer,
+							 length);
+}
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
+                                             cairo_scaled_glyph_t      *scaled_glyph)
+{
+    cairo_status_t status;
+    cairo_glyph_t glyph;
+    cairo_win32_surface_t *surface;
+    cairo_t *cr;
+    cairo_surface_t *image;
+    int width, height;
+    int x1, y1, x2, y2;
+
+    x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
+    y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
+    x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
+    y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
+    width = x2 - x1;
+    height = y2 - y1;
+
+    surface = (cairo_win32_surface_t *)
+	cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
+
+    cr = cairo_create (&surface->base);
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+    status = cairo_status (cr);
+    cairo_destroy(cr);
+    if (status)
+	goto FAIL;
+
+    glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
+    glyph.x = -x1;
+    glyph.y = -y1;
+    status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
+                                      0, 0, &glyph, 1);
+    if (status)
+	goto FAIL;
+
+    GdiFlush();
+
+    image = _compute_a8_mask (surface);
+    status = image->status;
+    if (status)
+	goto FAIL;
+
+    cairo_surface_set_device_offset (image, -x1, -y1);
+    _cairo_scaled_glyph_set_surface (scaled_glyph,
+                                     &scaled_font->base,
+                                     (cairo_image_surface_t *) image);
+
+  FAIL:
+    cairo_surface_destroy (&surface->base);
+
+    return status;
+}
+
+static void
+_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
+                                       FIXED Fx, FIXED Fy,
+                                       cairo_fixed_t *fx, cairo_fixed_t *fy)
+{
+    double x = Fx.value + Fx.fract / 65536.0;
+    double y = Fy.value + Fy.fract / 65536.0;
+    cairo_matrix_transform_point (matrix, &x, &y);
+    *fx = _cairo_fixed_from_double (x);
+    *fy = _cairo_fixed_from_double (y);
+}
+
+static cairo_status_t
+_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
+					  cairo_scaled_glyph_t      *scaled_glyph)
+{
+    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
+    cairo_status_t status;
+    GLYPHMETRICS metrics;
+    HDC hdc;
+    DWORD bytesGlyph;
+    unsigned char *buffer, *ptr;
+    cairo_path_fixed_t *path;
+    cairo_matrix_t transform;
+    cairo_fixed_t x, y;
+
+    if (scaled_font->is_bitmap)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    path = _cairo_path_fixed_create ();
+    if (!path)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) {
+        status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
+        transform = scaled_font->base.scale;
+        cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square);
+    } else {
+        status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+        cairo_matrix_init_identity(&transform);
+    }
+    if (status)
+        goto CLEANUP_PATH;
+
+    bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
+				   GGO_NATIVE | GGO_GLYPH_INDEX,
+				   &metrics, 0, NULL, &matrix);
+
+    if (bytesGlyph == GDI_ERROR) {
+	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
+	goto CLEANUP_FONT;
+    }
+
+    ptr = buffer = malloc (bytesGlyph);
+    if (!buffer) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_FONT;
+    }
+
+    if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
+			  GGO_NATIVE | GGO_GLYPH_INDEX,
+			  &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
+	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
+	goto CLEANUP_BUFFER;
+    }
+
+    while (ptr < buffer + bytesGlyph) {
+	TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
+	unsigned char *endPoly = ptr + header->cb;
+
+	ptr += sizeof (TTPOLYGONHEADER);
+
+        _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                               header->pfxStart.x,
+                                               header->pfxStart.y,
+                                               &x, &y);
+        status = _cairo_path_fixed_move_to (path, x, y);
+	if (status)
+	    goto CLEANUP_BUFFER;
+
+	while (ptr < endPoly) {
+	    TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
+	    POINTFX *points = curve->apfx;
+	    int i;
+	    switch (curve->wType) {
+	    case TT_PRIM_LINE:
+		for (i = 0; i < curve->cpfx; i++) {
+                    _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                           points[i].x,
+                                                           points[i].y,
+                                                           &x, &y);
+		    status = _cairo_path_fixed_line_to (path, x, y);
+		    if (status)
+			goto CLEANUP_BUFFER;
+		}
+		break;
+	    case TT_PRIM_QSPLINE:
+		for (i = 0; i < curve->cpfx - 1; i++) {
+		    cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
+		    if (! _cairo_path_fixed_get_current_point (path, &p1x, &p1y))
+			goto CLEANUP_BUFFER;
+                    _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                           points[i].x,
+                                                           points[i].y,
+                                                           &cx, &cy);
+
+		    if (i + 1 == curve->cpfx - 1) {
+                        _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                               points[i + 1].x,
+                                                               points[i + 1].y,
+                                                               &p2x, &p2y);
+		    } else {
+			/* records with more than one curve use interpolation for
+			   control points, per http://support.microsoft.com/kb/q87115/ */
+                        _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                               points[i + 1].x,
+                                                               points[i + 1].y,
+                                                               &x, &y);
+                        p2x = (cx + x) / 2;
+			p2y = (cy + y) / 2;
+		    }
+
+		    c1x = 2 * cx / 3 + p1x / 3;
+		    c1y = 2 * cy / 3 + p1y / 3;
+		    c2x = 2 * cx / 3 + p2x / 3;
+		    c2y = 2 * cy / 3 + p2y / 3;
+
+		    status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
+		    if (status)
+			goto CLEANUP_BUFFER;
+		}
+		break;
+	    case TT_PRIM_CSPLINE:
+		for (i = 0; i < curve->cpfx - 2; i += 2) {
+		    cairo_fixed_t x1, y1, x2, y2;
+                    _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                           points[i].x,
+                                                           points[i].y,
+                                                           &x, &y);
+                    _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                           points[i + 1].x,
+                                                           points[i + 1].y,
+                                                           &x1, &y1);
+                    _cairo_win32_transform_FIXED_to_fixed (&transform,
+                                                           points[i + 2].x,
+                                                           points[i + 2].y,
+                                                           &x2, &y2);
+		    status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2);
+		    if (status)
+			goto CLEANUP_BUFFER;
+		}
+		break;
+	    }
+	    ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
+	}
+	status = _cairo_path_fixed_close_path (path);
+	if (status)
+	    goto CLEANUP_BUFFER;
+    }
+
+    _cairo_scaled_glyph_set_path (scaled_glyph,
+				  &scaled_font->base,
+				  path);
+
+ CLEANUP_BUFFER:
+    free (buffer);
+
+ CLEANUP_FONT:
+    if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE)
+	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
+    else
+	cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+ CLEANUP_PATH:
+    if (status != CAIRO_STATUS_SUCCESS)
+	_cairo_path_fixed_destroy (path);
+
+    return status;
+}
+
+const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
+    CAIRO_FONT_TYPE_WIN32,
+    _cairo_win32_scaled_font_fini,
+    _cairo_win32_scaled_font_glyph_init,
+    NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
+    _cairo_win32_scaled_font_ucs4_to_index,
+    _cairo_win32_scaled_font_load_truetype_table,
+    _cairo_win32_scaled_font_index_to_ucs4,
+    _cairo_win32_scaled_font_is_synthetic,
+    _cairo_win32_scaled_font_index_to_glyph_name,
+    _cairo_win32_scaled_font_load_type1_data
+};
+
+/* #cairo_win32_font_face_t */
+
+typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
+
+/* If hfont is non-%NULL then logfont->lfHeight must be -S for some S,
+ * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
+ * all be 0, and hfont is the result of calling CreateFontIndirectW on
+ * logfont.
+ */
+struct _cairo_win32_font_face {
+    cairo_font_face_t base;
+    LOGFONTW logfont;
+    HFONT hfont;
+};
+
+/* implement the platform-specific interface */
+
+static cairo_bool_t
+_is_scale (const cairo_matrix_t *matrix, double scale)
+{
+    return matrix->xx == scale && matrix->yy == scale &&
+           matrix->xy == 0. && matrix->yx == 0. &&
+           matrix->x0 == 0. && matrix->y0 == 0.;
+}
+
+static cairo_status_t
+_cairo_win32_font_face_scaled_font_create (void			*abstract_face,
+					   const cairo_matrix_t	*font_matrix,
+					   const cairo_matrix_t	*ctm,
+					   const cairo_font_options_t *options,
+					   cairo_scaled_font_t **font)
+{
+    HFONT hfont = NULL;
+
+    cairo_win32_font_face_t *font_face = abstract_face;
+
+    if (font_face->hfont) {
+        /* Check whether it's OK to go ahead and use the font-face's HFONT. */
+        if (_is_scale (ctm, 1.) &&
+            _is_scale (font_matrix, -font_face->logfont.lfHeight)) {
+            hfont = font_face->hfont;
+        }
+    }
+
+    return _win32_scaled_font_create (&font_face->logfont,
+				      hfont,
+				      &font_face->base,
+				      font_matrix, ctm, options,
+				      font);
+}
+
+const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
+    CAIRO_FONT_TYPE_WIN32,
+    _cairo_win32_font_face_create_for_toy,
+    _cairo_win32_font_face_destroy,
+    _cairo_win32_font_face_scaled_font_create
+};
+
+/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
+ * The primary purpose of this mapping is to provide unique
+ * #cairo_font_face_t values so that our cache and mapping from
+ * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
+ * corresponding #cairo_font_face_t objects fall out of downstream
+ * caches, we don't need them in this hash table anymore.
+ *
+ * Modifications to this hash table are protected by
+ * _cairo_win32_font_face_mutex.
+ */
+
+static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
+
+static int
+_cairo_win32_font_face_keys_equal (const void *key_a,
+				   const void *key_b);
+
+static void
+_cairo_win32_font_face_hash_table_destroy (void)
+{
+    cairo_hash_table_t *hash_table;
+
+    /* We manually acquire the lock rather than calling
+     * _cairo_win32_font_face_hash_table_lock simply to avoid creating
+     * the table only to destroy it again. */
+    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
+    hash_table = cairo_win32_font_face_hash_table;
+    cairo_win32_font_face_hash_table = NULL;
+    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+
+    if (hash_table != NULL)
+	_cairo_hash_table_destroy (hash_table);
+}
+
+static cairo_hash_table_t *
+_cairo_win32_font_face_hash_table_lock (void)
+{
+    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
+
+    if (unlikely (cairo_win32_font_face_hash_table == NULL))
+    {
+	cairo_win32_font_face_hash_table =
+	_cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
+
+	if (unlikely (cairo_win32_font_face_hash_table == NULL)) {
+	    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return NULL;
+	}
+    }
+
+    return cairo_win32_font_face_hash_table;
+}
+
+static void
+_cairo_win32_font_face_hash_table_unlock (void)
+{
+    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+}
+
+static void
+_cairo_win32_font_face_destroy (void *abstract_face)
+{
+    cairo_win32_font_face_t *font_face = abstract_face;
+    cairo_hash_table_t *hash_table;
+
+    hash_table = _cairo_win32_font_face_hash_table_lock ();
+    /* All created objects must have been mapped in the hash table. */
+    assert (hash_table != NULL);
+
+    if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
+	/* somebody recreated the font whilst we waited for the lock */
+	_cairo_win32_font_face_hash_table_unlock ();
+	return;
+    }
+
+    /* Font faces in SUCCESS status are guaranteed to be in the
+     * hashtable. Font faces in an error status are removed from the
+     * hashtable if they are found during a lookup, thus they should
+     * only be removed if they are in the hashtable. */
+    if (likely (font_face->base.status == CAIRO_STATUS_SUCCESS) ||
+	_cairo_hash_table_lookup (hash_table, &font_face->base.hash_entry) == font_face)
+	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
+
+    _cairo_win32_font_face_hash_table_unlock ();
+}
+
+static void
+_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
+				 LOGFONTW                *logfont,
+				 HFONT                    font)
+{
+    unsigned long hash = _CAIRO_HASH_INIT_VALUE;
+
+    key->logfont = *logfont;
+    key->hfont = font;
+
+    hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName));
+    hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight));
+    hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic));
+
+    key->base.hash_entry.hash = hash;
+}
+
+static int
+_cairo_win32_font_face_keys_equal (const void *key_a,
+				   const void *key_b)
+{
+    const cairo_win32_font_face_t *face_a = key_a;
+    const cairo_win32_font_face_t *face_b = key_b;
+
+    if (face_a->logfont.lfWeight         == face_b->logfont.lfWeight &&
+	face_a->logfont.lfItalic         == face_b->logfont.lfItalic &&
+	face_a->logfont.lfUnderline      == face_b->logfont.lfUnderline &&
+	face_a->logfont.lfStrikeOut      == face_b->logfont.lfStrikeOut &&
+	face_a->logfont.lfCharSet        == face_b->logfont.lfCharSet &&
+	face_a->logfont.lfOutPrecision   == face_b->logfont.lfOutPrecision &&
+	face_a->logfont.lfClipPrecision  == face_b->logfont.lfClipPrecision &&
+	face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily &&
+	(wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0))
+	return TRUE;
+    else
+	return FALSE;
+}
+
+/**
+ * cairo_win32_font_face_create_for_logfontw_hfont:
+ * @logfont: A #LOGFONTW structure specifying the font to use.
+ *   If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement
+ *   fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
+ *   lfEscapement must be zero.
+ * @font: An #HFONT that can be used when the font matrix is a scale by
+ *   -lfHeight and the CTM is identity.
+ *
+ * Creates a new font for the Win32 font backend based on a
+ * #LOGFONT. This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ * The #cairo_scaled_font_t
+ * returned from cairo_scaled_font_create() is also for the Win32 backend
+ * and can be used with functions such as cairo_win32_scaled_font_select_font().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ **/
+cairo_font_face_t *
+cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
+{
+    cairo_win32_font_face_t *font_face, key;
+    cairo_hash_table_t *hash_table;
+    cairo_status_t status;
+
+    hash_table = _cairo_win32_font_face_hash_table_lock ();
+    if (unlikely (hash_table == NULL)) {
+        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_font_face_t *)&_cairo_font_face_nil;
+    }
+
+    _cairo_win32_font_face_init_key (&key, logfont, font);
+
+    /* Return existing unscaled font if it exists in the hash table. */
+    font_face = _cairo_hash_table_lookup (hash_table,
+					 &key.base.hash_entry);
+    if (font_face != NULL) {
+	if (font_face->base.status == CAIRO_STATUS_SUCCESS) {
+	    cairo_font_face_reference (&font_face->base);
+	    _cairo_win32_font_face_hash_table_unlock ();
+	    return &font_face->base;
+	}
+
+	/* remove the bad font from the hash table */
+	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
+    }
+
+    /* Otherwise create it and insert into hash table. */
+    font_face = malloc (sizeof (cairo_win32_font_face_t));
+    if (!font_face) {
+        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	goto FAIL;
+    }
+
+    _cairo_win32_font_face_init_key (font_face, logfont, font);
+    _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
+
+    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
+    status = _cairo_hash_table_insert (hash_table,
+				       &font_face->base.hash_entry);
+    if (unlikely (status))
+	goto FAIL;
+
+    _cairo_win32_font_face_hash_table_unlock ();
+    return &font_face->base;
+
+FAIL:
+    _cairo_win32_font_face_hash_table_unlock ();
+    return (cairo_font_face_t *)&_cairo_font_face_nil;
+}
+
+/**
+ * cairo_win32_font_face_create_for_logfontw:
+ * @logfont: A #LOGFONTW structure specifying the font to use.
+ *   The lfHeight, lfWidth, lfOrientation and lfEscapement
+ *   fields of this structure are ignored.
+ *
+ * Creates a new font for the Win32 font backend based on a
+ * #LOGFONT. This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ * The #cairo_scaled_font_t
+ * returned from cairo_scaled_font_create() is also for the Win32 backend
+ * and can be used with functions such as cairo_win32_scaled_font_select_font().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ **/
+cairo_font_face_t *
+cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
+{
+    return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
+}
+
+/**
+ * cairo_win32_font_face_create_for_hfont:
+ * @font: An #HFONT structure specifying the font to use.
+ *
+ * Creates a new font for the Win32 font backend based on a
+ * #HFONT. This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ * The #cairo_scaled_font_t
+ * returned from cairo_scaled_font_create() is also for the Win32 backend
+ * and can be used with functions such as cairo_win32_scaled_font_select_font().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ **/
+cairo_font_face_t *
+cairo_win32_font_face_create_for_hfont (HFONT font)
+{
+    LOGFONTW logfont;
+    GetObjectW (font, sizeof(logfont), &logfont);
+
+    if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
+        logfont.lfWidth != 0) {
+        /* We can't use this font because that optimization requires that
+         * lfEscapement, lfOrientation and lfWidth be zero. */
+        font = NULL;
+    }
+
+    return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
+}
+
+static cairo_bool_t
+_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
+{
+    return scaled_font->backend == &_cairo_win32_scaled_font_backend;
+}
+
+/**
+ * cairo_win32_scaled_font_select_font:
+ * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an
+ *   object can be created with cairo_win32_scaled_font_create_for_logfontw().
+ * @hdc: a device context
+ *
+ * Selects the font into the given device context and changes the
+ * map mode and world transformation of the device context to match
+ * that of the font. This function is intended for use when using
+ * layout APIs such as Uniscribe to do text layout with the
+ * cairo font. After finishing using the device context, you must call
+ * cairo_win32_scaled_font_done_font() to release any resources allocated
+ * by this function.
+ *
+ * See cairo_win32_scaled_font_get_metrics_factor() for converting logical
+ * coordinates from the device context to font space.
+ *
+ * Normally, calls to SaveDC() and RestoreDC() would be made around
+ * the use of this function to preserve the original graphics state.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if the operation succeeded.
+ *   otherwise an error such as %CAIRO_STATUS_NO_MEMORY and
+ *   the device context is unchanged.
+ **/
+cairo_status_t
+cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
+				     HDC                  hdc)
+{
+    cairo_status_t status;
+    HFONT hfont;
+    HFONT old_hfont = NULL;
+    int old_mode;
+
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+    }
+
+    if (scaled_font->status)
+	return scaled_font->status;
+
+    status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont);
+    if (status)
+	return status;
+
+    old_hfont = SelectObject (hdc, hfont);
+    if (!old_hfont)
+	return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
+
+    old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
+    if (!old_mode) {
+	status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
+	SelectObject (hdc, old_hfont);
+	return status;
+    }
+
+    status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc);
+    if (status) {
+	SetGraphicsMode (hdc, old_mode);
+	SelectObject (hdc, old_hfont);
+	return status;
+    }
+
+    SetMapMode (hdc, MM_TEXT);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_win32_scaled_font_done_font:
+ * @scaled_font: A scaled font from the Win32 font backend.
+ *
+ * Releases any resources allocated by cairo_win32_scaled_font_select_font()
+ **/
+void
+cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
+{
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+    }
+}
+
+/**
+ * cairo_win32_scaled_font_get_metrics_factor:
+ * @scaled_font: a scaled font from the Win32 font backend
+ *
+ * Gets a scale factor between logical coordinates in the coordinate
+ * space used by cairo_win32_scaled_font_select_font() (that is, the
+ * coordinate system used by the Windows functions to return metrics) and
+ * font space coordinates.
+ *
+ * Return value: factor to multiply logical units by to get font space
+ *               coordinates.
+ **/
+double
+cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
+{
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return 1.;
+    }
+    return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
+}
+
+/**
+ * cairo_win32_scaled_font_get_logical_to_device:
+ * @scaled_font: a scaled font from the Win32 font backend
+ * @logical_to_device: matrix to return
+ *
+ * Gets the transformation mapping the logical space used by @scaled_font
+ * to device space.
+ *
+ * Since: 1.4
+ **/
+void
+cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
+					       cairo_matrix_t *logical_to_device)
+{
+    cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	cairo_matrix_init_identity (logical_to_device);
+	return;
+    }
+    *logical_to_device = win_font->logical_to_device;
+}
+
+/**
+ * cairo_win32_scaled_font_get_device_to_logical:
+ * @scaled_font: a scaled font from the Win32 font backend
+ * @device_to_logical: matrix to return
+ *
+ * Gets the transformation mapping device space to the logical space
+ * used by @scaled_font.
+ *
+ * Since: 1.4
+ **/
+void
+cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
+					       cairo_matrix_t *device_to_logical)
+{
+    cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
+    if (! _cairo_scaled_font_is_win32 (scaled_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	cairo_matrix_init_identity (device_to_logical);
+	return;
+    }
+    *device_to_logical = win_font->device_to_logical;
+}
+
+void
+_cairo_win32_font_reset_static_data (void)
+{
+    _cairo_win32_font_face_hash_table_destroy ();
+}
diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c
new file mode 100644
index 0000000..17a68f7
--- /dev/null
+++ b/src/win32/cairo-win32-printing-surface.c
@@ -0,0 +1,1915 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2007, 2008 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *      Adrian Johnson <ajohnson at redneon.com>
+ *      Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-default-context-private.h"
+#include "cairo-error-private.h"
+#include "cairo-paginated-private.h"
+
+#include "cairo-clip-private.h"
+#include "cairo-win32-private.h"
+#include "cairo-recording-surface-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+#include "cairo-image-info-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-surface-backend-private.h"
+#include "cairo-surface-clipper-private.h"
+
+#include <windows.h>
+
+#if !defined(POSTSCRIPT_IDENTIFY)
+# define POSTSCRIPT_IDENTIFY 0x1015
+#endif
+
+#if !defined(PSIDENT_GDICENTRIC)
+# define PSIDENT_GDICENTRIC 0x0000
+#endif
+
+#if !defined(GET_PS_FEATURESETTING)
+# define GET_PS_FEATURESETTING 0x1019
+#endif
+
+#if !defined(FEATURESETTING_PSLEVEL)
+# define FEATURESETTING_PSLEVEL 0x0002
+#endif
+
+#if !defined(GRADIENT_FILL_RECT_H)
+# define GRADIENT_FILL_RECT_H 0x00
+#endif
+
+#if !defined(CHECKJPEGFORMAT)
+# define CHECKJPEGFORMAT 0x1017
+#endif
+
+#if !defined(CHECKPNGFORMAT)
+# define CHECKPNGFORMAT 0x1018
+#endif
+
+#define PELS_72DPI  ((LONG)(72. / 0.0254))
+
+static const char *_cairo_win32_printing_supported_mime_types[] =
+{
+    CAIRO_MIME_TYPE_JPEG,
+    CAIRO_MIME_TYPE_PNG,
+    NULL
+};
+
+static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
+static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend;
+
+static void
+_cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface)
+{
+    DWORD word;
+    INT ps_feature, ps_level;
+
+    word = PSIDENT_GDICENTRIC;
+    if (ExtEscape (surface->dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0)
+	return;
+
+    ps_feature = FEATURESETTING_PSLEVEL;
+    if (ExtEscape (surface->dc, GET_PS_FEATURESETTING, sizeof(INT),
+		   (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0)
+	return;
+
+    if (ps_level >= 3)
+	surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+}
+
+static void
+_cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface)
+{
+    DWORD word;
+
+    word = CHECKJPEGFORMAT;
+    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
+	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
+
+    word = CHECKPNGFORMAT;
+    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
+	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG;
+}
+
+/* When creating an EMF file, ExtTextOut with ETO_GLYPH_INDEX does not
+ * work unless the GDI function GdiInitializeLanguagePack() has been
+ * called.
+ *
+ *   http://m-a-tech.blogspot.com/2009/04/emf-buffer-idiocracy.html
+ *
+ * The only information I could find on the how to use this
+ * undocumented function is the use in:
+ *
+ * http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/render_process.cc?view=markup
+ *
+ * to solve the same problem. The above code first checks if LPK.DLL
+ * is already loaded. If it is not it calls
+ * GdiInitializeLanguagePack() using the prototype
+ *   BOOL GdiInitializeLanguagePack (int)
+ * and argument 0.
+ */
+static void
+_cairo_win32_printing_surface_init_language_pack (cairo_win32_surface_t *surface)
+{
+    typedef BOOL (WINAPI *gdi_init_lang_pack_func_t)(int);
+    gdi_init_lang_pack_func_t gdi_init_lang_pack;
+    HMODULE module;
+
+    if (GetModuleHandleW (L"LPK.DLL"))
+	return;
+
+    module = GetModuleHandleW (L"GDI32.DLL");
+    if (module) {
+	gdi_init_lang_pack = (gdi_init_lang_pack_func_t)
+	    GetProcAddress (module, "GdiInitializeLanguagePack");
+	if (gdi_init_lang_pack)
+	    gdi_init_lang_pack (0);
+    }
+}
+
+static cairo_int_status_t
+analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern)
+{
+    cairo_image_surface_t  *image;
+    void		   *image_extra;
+    cairo_int_status_t      status;
+    cairo_image_transparency_t transparency;
+
+    status = _cairo_surface_acquire_source_image (pattern->surface,
+						  &image,
+						  &image_extra);
+    if (status)
+	return status;
+
+    transparency = _cairo_image_analyze_transparency (image);
+    switch (transparency) {
+    case CAIRO_IMAGE_UNKNOWN:
+	ASSERT_NOT_REACHED;
+    case CAIRO_IMAGE_IS_OPAQUE:
+	status = CAIRO_STATUS_SUCCESS;
+	break;
+
+    case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
+    case CAIRO_IMAGE_HAS_ALPHA:
+	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+	break;
+    }
+
+    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+
+    return status;
+}
+
+static cairo_bool_t
+surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+{
+    if (_cairo_surface_is_recording (pattern->surface))
+	return TRUE;
+
+    if (cairo_surface_get_type (pattern->surface) != CAIRO_SURFACE_TYPE_WIN32 &&
+	pattern->surface->backend->acquire_source_image == NULL)
+    {
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static cairo_bool_t
+pattern_supported (cairo_win32_surface_t *surface, const cairo_pattern_t *pattern)
+{
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
+	return TRUE;
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+	return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
+	return surface->flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+
+    return FALSE;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface,
+                                                 cairo_operator_t       op,
+                                                 const cairo_pattern_t *pattern)
+{
+    if (! pattern_supported (surface, pattern))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (!(op == CAIRO_OPERATOR_SOURCE ||
+	  op == CAIRO_OPERATOR_OVER ||
+	  op == CAIRO_OPERATOR_CLEAR))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+
+	if ( _cairo_surface_is_recording (surface_pattern->surface))
+	    return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
+    }
+
+    if (op == CAIRO_OPERATOR_SOURCE ||
+	op == CAIRO_OPERATOR_CLEAR)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
+     * the pattern contains transparency, we return
+     * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
+     * surface. If the analysis surface determines that there is
+     * anything drawn under this operation, a fallback image will be
+     * used. Otherwise the operation will be replayed during the
+     * render stage and we blend the transarency into the white
+     * background to convert the pattern to opaque.
+     */
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+
+	return analyze_surface_pattern_transparency (surface_pattern);
+    }
+
+    if (_cairo_pattern_is_opaque (pattern, NULL))
+	return CAIRO_STATUS_SUCCESS;
+    else
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+}
+
+static cairo_bool_t
+_cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surface,
+                                                   cairo_operator_t       op,
+                                                   const cairo_pattern_t *pattern)
+{
+    if (_cairo_win32_printing_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
+	return TRUE;
+    else
+	return FALSE;
+}
+
+static void
+_cairo_win32_printing_surface_init_clear_color (cairo_win32_surface_t *surface,
+						cairo_solid_pattern_t *color)
+{
+    if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
+	_cairo_pattern_init_solid (color, CAIRO_COLOR_WHITE);
+    else
+	_cairo_pattern_init_solid (color, CAIRO_COLOR_BLACK);
+}
+
+static COLORREF
+_cairo_win32_printing_surface_flatten_transparency (cairo_win32_surface_t *surface,
+						    const cairo_color_t   *color)
+{
+    COLORREF c;
+    BYTE red, green, blue;
+
+    red   = color->red_short   >> 8;
+    green = color->green_short >> 8;
+    blue  = color->blue_short  >> 8;
+
+    if (!CAIRO_COLOR_IS_OPAQUE(color)) {
+	if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
+	    /* Blend into white */
+	    uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
+
+	    red   = (color->red_short   >> 8) + one_minus_alpha;
+	    green = (color->green_short >> 8) + one_minus_alpha;
+	    blue  = (color->blue_short  >> 8) + one_minus_alpha;
+	} else {
+	    /* Blend into black */
+	    red   = (color->red_short   >> 8);
+	    green = (color->green_short >> 8);
+	    blue  = (color->blue_short  >> 8);
+	}
+    }
+    c = RGB (red, green, blue);
+
+    return c;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface,
+                                                  const cairo_pattern_t *source)
+{
+    cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source;
+    COLORREF color;
+
+    color = _cairo_win32_printing_surface_flatten_transparency (surface,
+								&pattern->color);
+    surface->brush = CreateSolidBrush (color);
+    if (!surface->brush)
+	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)");
+    surface->old_brush = SelectObject (surface->dc, surface->brush);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_printing_surface_done_solid_brush (cairo_win32_surface_t *surface)
+{
+    if (surface->old_brush) {
+	SelectObject (surface->dc, surface->old_brush);
+	DeleteObject (surface->brush);
+	surface->old_brush = NULL;
+    }
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface,
+						RECT                  *clip)
+{
+    XFORM xform;
+
+    _cairo_matrix_to_win32_xform (&surface->ctm, &xform);
+    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
+	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform");
+    GetClipBox (surface->dc, clip);
+
+    _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
+    if (!SetWorldTransform (surface->dc, &xform))
+	return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface,
+                                                   const cairo_pattern_t *pattern)
+{
+    RECT clip;
+    cairo_status_t status;
+
+    GetClipBox (surface->dc, &clip);
+    status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern);
+    if (status)
+	return status;
+
+    FillRect (surface->dc, &clip, surface->brush);
+    _cairo_win32_printing_surface_done_solid_brush (surface);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_surface_t   *surface,
+						       cairo_surface_pattern_t *pattern)
+{
+    cairo_content_t old_content;
+    cairo_matrix_t old_ctm;
+    cairo_bool_t old_has_ctm;
+    cairo_rectangle_int_t recording_extents;
+    cairo_status_t status;
+    cairo_extend_t extend;
+    cairo_matrix_t p2d;
+    XFORM xform;
+    int x_tile, y_tile, left, right, top, bottom;
+    RECT clip;
+    cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) pattern->surface;
+    cairo_box_t bbox;
+
+    extend = cairo_pattern_get_extend (&pattern->base);
+
+    p2d = pattern->base.matrix;
+    status = cairo_matrix_invert (&p2d);
+    /* _cairo_pattern_set_matrix guarantees invertibility */
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    old_ctm = surface->ctm;
+    old_has_ctm = surface->has_ctm;
+    cairo_matrix_multiply (&p2d, &p2d, &surface->ctm);
+    surface->ctm = p2d;
+    SaveDC (surface->dc);
+    _cairo_matrix_to_win32_xform (&p2d, &xform);
+
+    status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
+    if (status)
+	return status;
+
+    _cairo_box_round_to_rectangle (&bbox, &recording_extents);
+
+    status = _cairo_win32_printing_surface_get_ctm_clip_box (surface, &clip);
+    if (status)
+	return status;
+
+    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
+	left = floor (clip.left / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
+	right = ceil (clip.right / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
+	top = floor (clip.top / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
+	bottom = ceil (clip.bottom / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
+    } else {
+	left = 0;
+	right = 1;
+	top = 0;
+	bottom = 1;
+    }
+
+    old_content = surface->content;
+    if (recording_surface->base.content == CAIRO_CONTENT_COLOR) {
+	surface->content = CAIRO_CONTENT_COLOR;
+	status = _cairo_win32_printing_surface_paint_solid_pattern (surface,
+								    &_cairo_pattern_black.base);
+	if (status)
+	    return status;
+    }
+
+    for (y_tile = top; y_tile < bottom; y_tile++) {
+	for (x_tile = left; x_tile < right; x_tile++) {
+	    cairo_matrix_t m;
+	    double x, y;
+
+	    SaveDC (surface->dc);
+	    m = p2d;
+	    cairo_matrix_translate (&m,
+				    x_tile*recording_extents.width,
+				    y_tile*recording_extents.height);
+	    if (extend == CAIRO_EXTEND_REFLECT) {
+		if (x_tile % 2) {
+		    cairo_matrix_translate (&m, recording_extents.width, 0);
+		    cairo_matrix_scale (&m, -1, 1);
+		}
+		if (y_tile % 2) {
+		    cairo_matrix_translate (&m, 0, recording_extents.height);
+		    cairo_matrix_scale (&m, 1, -1);
+		}
+	    }
+	    surface->ctm = m;
+	    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
+
+	    /* Set clip path around bbox of the pattern. */
+	    BeginPath (surface->dc);
+
+	    x = 0;
+	    y = 0;
+	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
+	    MoveToEx (surface->dc, (int) x, (int) y, NULL);
+
+	    x = recording_extents.width;
+	    y = 0;
+	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
+	    LineTo (surface->dc, (int) x, (int) y);
+
+	    x = recording_extents.width;
+	    y = recording_extents.height;
+	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
+	    LineTo (surface->dc, (int) x, (int) y);
+
+	    x = 0;
+	    y = recording_extents.height;
+	    cairo_matrix_transform_point (&surface->ctm, &x, &y);
+	    LineTo (surface->dc, (int) x, (int) y);
+
+	    CloseFigure (surface->dc);
+	    EndPath (surface->dc);
+	    SelectClipPath (surface->dc, RGN_AND);
+
+	    SaveDC (surface->dc); /* Allow clip path to be reset during replay */
+	    status = _cairo_recording_surface_replay_region (&recording_surface->base, NULL,
+							     &surface->base,
+							     CAIRO_RECORDING_REGION_NATIVE);
+	    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
+	    /* Restore both the clip save and our earlier path SaveDC */
+	    RestoreDC (surface->dc, -2);
+
+	    if (status)
+		return status;
+	}
+    }
+
+    surface->content = old_content;
+    surface->ctm = old_ctm;
+    surface->has_ctm = old_has_ctm;
+    RestoreDC (surface->dc, -1);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
+					  cairo_surface_t         *source,
+					  const unsigned char    **data,
+					  unsigned long           *length,
+					  cairo_image_info_t      *info)
+{
+    const unsigned char *mime_data;
+    unsigned long mime_data_length;
+    cairo_int_status_t status;
+    DWORD result;
+
+    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
+				 &mime_data, &mime_data_length);
+    if (mime_data == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_image_info_get_jpeg_info (info, mime_data, mime_data_length);
+    if (status)
+	return status;
+
+    result = 0;
+    if (ExtEscape(surface->dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data,
+		  sizeof(result), (char *) &result) <= 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (result != 1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    *data = mime_data;
+    *length = mime_data_length;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
+					 cairo_surface_t         *source,
+					 const unsigned char    **data,
+					 unsigned long           *length,
+					 cairo_image_info_t      *info)
+{
+    const unsigned char *mime_data;
+    unsigned long mime_data_length;
+
+    cairo_int_status_t status;
+    DWORD result;
+
+    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_PNG,
+				 &mime_data, &mime_data_length);
+    if (mime_data == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_image_info_get_png_info (info, mime_data, mime_data_length);
+    if (status)
+	return status;
+
+    result = 0;
+    if (ExtEscape(surface->dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data,
+		  sizeof(result), (char *) &result) <= 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (result != 1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    *data = mime_data;
+    *length = mime_data_length;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surface,
+						   cairo_surface_pattern_t *pattern)
+{
+    cairo_status_t status;
+    cairo_extend_t extend;
+    cairo_image_surface_t *image;
+    void *image_extra;
+    cairo_image_surface_t *opaque_image = NULL;
+    BITMAPINFO bi;
+    cairo_matrix_t m;
+    int oldmode;
+    XFORM xform;
+    int x_tile, y_tile, left, right, top, bottom;
+    RECT clip;
+    const cairo_color_t *background_color;
+    const unsigned char *mime_data;
+    unsigned long mime_size;
+    cairo_image_info_t mime_info;
+    cairo_bool_t use_mime;
+    DWORD mime_type;
+
+    /* If we can't use StretchDIBits with this surface, we can't do anything
+     * here.
+     */
+    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
+	background_color = CAIRO_COLOR_WHITE;
+    else
+	background_color = CAIRO_COLOR_BLACK;
+
+    extend = cairo_pattern_get_extend (&pattern->base);
+
+    status = _cairo_surface_acquire_source_image (pattern->surface,
+						  &image, &image_extra);
+    if (status)
+	return status;
+
+    if (image->base.status) {
+	status = image->base.status;
+	goto CLEANUP_IMAGE;
+    }
+
+    if (image->width == 0 || image->height == 0) {
+	status = CAIRO_STATUS_SUCCESS;
+	goto CLEANUP_IMAGE;
+    }
+
+    mime_type = BI_JPEG;
+    status = _cairo_win32_printing_surface_check_jpeg (surface,
+						       pattern->surface,
+						       &mime_data,
+						       &mime_size,
+						       &mime_info);
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	mime_type = BI_PNG;
+	status = _cairo_win32_printing_surface_check_png (surface,
+							  pattern->surface,
+							  &mime_data,
+							  &mime_size,
+							  &mime_info);
+    }
+    if (_cairo_status_is_error (status))
+	return status;
+
+    use_mime = (status == CAIRO_STATUS_SUCCESS);
+
+    if (!use_mime && image->format != CAIRO_FORMAT_RGB24) {
+	cairo_surface_t *opaque_surface;
+	cairo_surface_pattern_t image_pattern;
+	cairo_solid_pattern_t background_pattern;
+
+	opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+						     image->width,
+						     image->height);
+	if (opaque_surface->status) {
+	    status = opaque_surface->status;
+	    goto CLEANUP_OPAQUE_IMAGE;
+	}
+
+	_cairo_pattern_init_solid (&background_pattern,
+				   background_color);
+	status = _cairo_surface_paint (opaque_surface,
+				       CAIRO_OPERATOR_SOURCE,
+				       &background_pattern.base,
+				       NULL);
+	if (status)
+	    goto CLEANUP_OPAQUE_IMAGE;
+
+	_cairo_pattern_init_for_surface (&image_pattern, &image->base);
+	status = _cairo_surface_paint (opaque_surface,
+				       CAIRO_OPERATOR_OVER,
+				       &image_pattern.base,
+				       NULL);
+	_cairo_pattern_fini (&image_pattern.base);
+	if (status)
+	    goto CLEANUP_OPAQUE_IMAGE;
+
+	opaque_image = (cairo_image_surface_t *) opaque_surface;
+    } else {
+	opaque_image = image;
+    }
+
+    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bi.bmiHeader.biWidth = use_mime ? mime_info.width : opaque_image->width;
+    bi.bmiHeader.biHeight = use_mime ? - mime_info.height : -opaque_image->height;
+    bi.bmiHeader.biSizeImage = use_mime ? mime_size : 0;
+    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+    bi.bmiHeader.biPlanes = 1;
+    bi.bmiHeader.biBitCount = 32;
+    bi.bmiHeader.biCompression = use_mime ? mime_type : BI_RGB;
+    bi.bmiHeader.biClrUsed = 0;
+    bi.bmiHeader.biClrImportant = 0;
+
+    m = pattern->base.matrix;
+    status = cairo_matrix_invert (&m);
+    /* _cairo_pattern_set_matrix guarantees invertibility */
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    cairo_matrix_multiply (&m, &m, &surface->gdi_ctm);
+    SaveDC (surface->dc);
+    _cairo_matrix_to_win32_xform (&m, &xform);
+
+    if (! SetWorldTransform (surface->dc, &xform)) {
+	status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern");
+	goto CLEANUP_OPAQUE_IMAGE;
+    }
+
+    oldmode = SetStretchBltMode(surface->dc, HALFTONE);
+
+    GetClipBox (surface->dc, &clip);
+    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
+	left = floor ( clip.left / (double) opaque_image->width);
+	right = ceil (clip.right / (double) opaque_image->width);
+	top = floor (clip.top / (double) opaque_image->height);
+	bottom = ceil (clip.bottom / (double) opaque_image->height);
+    } else {
+	left = 0;
+	right = 1;
+	top = 0;
+	bottom = 1;
+    }
+
+    for (y_tile = top; y_tile < bottom; y_tile++) {
+	for (x_tile = left; x_tile < right; x_tile++) {
+	    if (!StretchDIBits (surface->dc,
+				x_tile*opaque_image->width,
+				y_tile*opaque_image->height,
+				opaque_image->width,
+				opaque_image->height,
+				0,
+				0,
+				use_mime ? mime_info.width : opaque_image->width,
+				use_mime ? mime_info.height : opaque_image->height,
+				use_mime ? mime_data : opaque_image->data,
+				&bi,
+				DIB_RGB_COLORS,
+				SRCCOPY))
+	    {
+		status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
+		goto CLEANUP_OPAQUE_IMAGE;
+	    }
+	}
+    }
+    SetStretchBltMode(surface->dc, oldmode);
+    RestoreDC (surface->dc, -1);
+
+CLEANUP_OPAQUE_IMAGE:
+    if (opaque_image != image)
+	cairo_surface_destroy (&opaque_image->base);
+CLEANUP_IMAGE:
+    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t   *surface,
+                                                     cairo_surface_pattern_t *pattern)
+{
+    if (_cairo_surface_is_recording (pattern->surface)) {
+	return _cairo_win32_printing_surface_paint_recording_pattern (surface,
+								      pattern);
+    } else {
+	return _cairo_win32_printing_surface_paint_image_pattern (surface,
+								  pattern);
+    }
+}
+
+static void
+vertex_set_color (TRIVERTEX *vert, cairo_color_stop_t *color)
+{
+    /* MSDN says that the range here is 0x0000 .. 0xff00;
+     * that may well be a typo, but just chop the low bits
+     * here. */
+    vert->Alpha = 0xff00;
+    vert->Red   = color->red_short & 0xff00;
+    vert->Green = color->green_short & 0xff00;
+    vert->Blue  = color->blue_short & 0xff00;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surface,
+                                                    cairo_linear_pattern_t *pattern)
+{
+    TRIVERTEX *vert;
+    GRADIENT_RECT *rect;
+    RECT clip;
+    XFORM xform;
+    int i, num_stops;
+    cairo_matrix_t mat, rot;
+    double p1x, p1y, p2x, p2y, xd, yd, d, sn, cs;
+    cairo_extend_t extend;
+    int range_start, range_stop, num_ranges, num_rects, stop;
+    int total_verts, total_rects;
+    cairo_status_t status;
+
+    extend = cairo_pattern_get_extend (&pattern->base.base);
+    SaveDC (surface->dc);
+
+    mat = pattern->base.base.matrix;
+    status = cairo_matrix_invert (&mat);
+    /* _cairo_pattern_set_matrix guarantees invertibility */
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    cairo_matrix_multiply (&mat, &surface->ctm, &mat);
+
+    p1x = pattern->pd1.x;
+    p1y = pattern->pd1.y;
+    p2x = pattern->pd2.x;
+    p2y = pattern->pd2.y;
+    cairo_matrix_translate (&mat, p1x, p1y);
+
+    xd = p2x - p1x;
+    yd = p2y - p1y;
+    d = sqrt (xd*xd + yd*yd);
+    sn = yd/d;
+    cs = xd/d;
+    cairo_matrix_init (&rot,
+		       cs, sn,
+		       -sn, cs,
+		        0, 0);
+    cairo_matrix_multiply (&mat, &rot, &mat);
+
+    _cairo_matrix_to_win32_xform (&mat, &xform);
+
+    if (!SetWorldTransform (surface->dc, &xform))
+	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2");
+
+    GetClipBox (surface->dc, &clip);
+
+    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
+	range_start = floor (clip.left / d);
+	range_stop = ceil (clip.right / d);
+    } else {
+	range_start = 0;
+	range_stop = 1;
+    }
+    num_ranges = range_stop - range_start;
+    num_stops = pattern->base.n_stops;
+    num_rects = num_stops - 1;
+
+    /* Add an extra four points and two rectangles for EXTEND_PAD */
+    vert = malloc (sizeof (TRIVERTEX) * (num_rects*2*num_ranges + 4));
+    rect = malloc (sizeof (GRADIENT_RECT) * (num_rects*num_ranges + 2));
+
+    for (i = 0; i < num_ranges*num_rects; i++) {
+	vert[i*2].y = (LONG) clip.top;
+	if (i%num_rects == 0) {
+	    stop = 0;
+	    if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
+		stop = num_rects;
+	    vert[i*2].x = (LONG)(d*(range_start + i/num_rects));
+	    vertex_set_color (&vert[i*2], &pattern->base.stops[stop].color);
+	} else {
+	    vert[i*2].x = vert[i*2-1].x;
+	    vert[i*2].Red = vert[i*2-1].Red;
+	    vert[i*2].Green = vert[i*2-1].Green;
+	    vert[i*2].Blue = vert[i*2-1].Blue;
+	    vert[i*2].Alpha = vert[i*2-1].Alpha;
+	}
+
+	stop = i%num_rects + 1;
+	vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset));
+	vert[i*2+1].y = (LONG) clip.bottom;
+	if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
+	    stop = num_rects - stop;
+	vertex_set_color (&vert[i*2+1], &pattern->base.stops[stop].color);
+
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+    }
+    total_verts = 2*num_ranges*num_rects;
+    total_rects = num_ranges*num_rects;
+
+    if (extend == CAIRO_EXTEND_PAD) {
+	vert[i*2].x = vert[i*2-1].x;
+	vert[i*2].y = (LONG) clip.top;
+	vert[i*2].Red = vert[i*2-1].Red;
+	vert[i*2].Green = vert[i*2-1].Green;
+	vert[i*2].Blue = vert[i*2-1].Blue;
+	vert[i*2].Alpha = 0xff00;
+	vert[i*2+1].x = clip.right;
+	vert[i*2+1].y = (LONG) clip.bottom;
+	vert[i*2+1].Red = vert[i*2-1].Red;
+	vert[i*2+1].Green = vert[i*2-1].Green;
+	vert[i*2+1].Blue = vert[i*2-1].Blue;
+	vert[i*2+1].Alpha = 0xff00;
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+
+	i++;
+
+	vert[i*2].x = clip.left;
+	vert[i*2].y = (LONG) clip.top;
+	vert[i*2].Red = vert[0].Red;
+	vert[i*2].Green = vert[0].Green;
+	vert[i*2].Blue = vert[0].Blue;
+	vert[i*2].Alpha = 0xff00;
+	vert[i*2+1].x = vert[0].x;
+	vert[i*2+1].y = (LONG) clip.bottom;
+	vert[i*2+1].Red = vert[0].Red;
+	vert[i*2+1].Green = vert[0].Green;
+	vert[i*2+1].Blue = vert[0].Blue;
+	vert[i*2+1].Alpha = 0xff00;
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+
+	total_verts += 4;
+	total_rects += 2;
+    }
+
+    if (!GradientFill (surface->dc,
+		       vert, total_verts,
+		       rect, total_rects,
+		       GRADIENT_FILL_RECT_H))
+	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill");
+
+    free (rect);
+    free (vert);
+    RestoreDC (surface->dc, -1);
+
+    return 0;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
+                                             const cairo_pattern_t *pattern)
+{
+    cairo_status_t status;
+
+    switch (pattern->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	status = _cairo_win32_printing_surface_paint_solid_pattern (surface, pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	status = _cairo_win32_printing_surface_paint_surface_pattern (surface,
+                                                                      (cairo_surface_pattern_t *) pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	status = _cairo_win32_printing_surface_paint_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+	break;
+
+    case CAIRO_PATTERN_TYPE_MESH:
+	ASSERT_NOT_REACHED;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+typedef struct _win32_print_path_info {
+    cairo_win32_surface_t *surface;
+} win32_path_info_t;
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_move_to (void *closure,
+					    const cairo_point_t *point)
+{
+    win32_path_info_t *path_info = closure;
+
+    if (path_info->surface->has_ctm) {
+	double x, y;
+
+	x = _cairo_fixed_to_double (point->x);
+	y = _cairo_fixed_to_double (point->y);
+	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
+	MoveToEx (path_info->surface->dc, (int) x, (int) y, NULL);
+    } else {
+	MoveToEx (path_info->surface->dc,
+		  _cairo_fixed_integer_part (point->x),
+		  _cairo_fixed_integer_part (point->y),
+		  NULL);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_line_to (void *closure,
+					    const cairo_point_t *point)
+{
+    win32_path_info_t *path_info = closure;
+
+    path_info->surface->path_empty = FALSE;
+    if (path_info->surface->has_ctm) {
+	double x, y;
+
+	x = _cairo_fixed_to_double (point->x);
+	y = _cairo_fixed_to_double (point->y);
+	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
+	LineTo (path_info->surface->dc, (int) x, (int) y);
+    } else {
+	LineTo (path_info->surface->dc,
+		_cairo_fixed_integer_part (point->x),
+		_cairo_fixed_integer_part (point->y));
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_curve_to (void          *closure,
+                                             const cairo_point_t *b,
+                                             const cairo_point_t *c,
+                                             const cairo_point_t *d)
+{
+    win32_path_info_t *path_info = closure;
+    POINT points[3];
+
+    path_info->surface->path_empty = FALSE;
+    if (path_info->surface->has_ctm) {
+	double x, y;
+
+	x = _cairo_fixed_to_double (b->x);
+	y = _cairo_fixed_to_double (b->y);
+	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
+	points[0].x = (LONG) x;
+	points[0].y = (LONG) y;
+
+	x = _cairo_fixed_to_double (c->x);
+	y = _cairo_fixed_to_double (c->y);
+	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
+	points[1].x = (LONG) x;
+	points[1].y = (LONG) y;
+
+	x = _cairo_fixed_to_double (d->x);
+	y = _cairo_fixed_to_double (d->y);
+	cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y);
+	points[2].x = (LONG) x;
+	points[2].y = (LONG) y;
+    } else {
+	points[0].x = _cairo_fixed_integer_part (b->x);
+	points[0].y = _cairo_fixed_integer_part (b->y);
+	points[1].x = _cairo_fixed_integer_part (c->x);
+	points[1].y = _cairo_fixed_integer_part (c->y);
+	points[2].x = _cairo_fixed_integer_part (d->x);
+	points[2].y = _cairo_fixed_integer_part (d->y);
+    }
+    PolyBezierTo (path_info->surface->dc, points, 3);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_close_path (void *closure)
+{
+    win32_path_info_t *path_info = closure;
+
+    CloseFigure (path_info->surface->dc);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_emit_path (cairo_win32_surface_t    *surface,
+					 const cairo_path_fixed_t *path)
+{
+    win32_path_info_t path_info;
+
+    path_info.surface = surface;
+    return _cairo_path_fixed_interpret (path,
+					_cairo_win32_printing_surface_path_move_to,
+					_cairo_win32_printing_surface_path_line_to,
+					_cairo_win32_printing_surface_path_curve_to,
+					_cairo_win32_printing_surface_path_close_path,
+					&path_info);
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_show_page (void *abstract_surface)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+
+    /* Undo both SaveDC's that we did in start_page */
+    RestoreDC (surface->dc, -2);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
+                                                   cairo_path_fixed_t *path,
+                                                   cairo_fill_rule_t   fill_rule,
+                                                   double	       tolerance,
+                                                   cairo_antialias_t   antialias)
+{
+    cairo_win32_surface_t *surface = cairo_container_of (clipper,
+							 cairo_win32_surface_t,
+							 clipper);
+    cairo_status_t status;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (path == NULL) {
+	RestoreDC (surface->dc, -1);
+	SaveDC (surface->dc);
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	SetPolyFillMode (surface->dc, WINDING);
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	SetPolyFillMode (surface->dc, ALTERNATE);
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    SelectClipPath (surface->dc, RGN_AND);
+
+    return status;
+}
+
+static void
+_cairo_win32_printing_surface_get_font_options (void                  *abstract_surface,
+                                                cairo_font_options_t  *options)
+{
+    _cairo_font_options_init_default (options);
+
+    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
+    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
+    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint (void			*abstract_surface,
+                                     cairo_operator_t		 op,
+                                     const cairo_pattern_t	*source,
+				     const cairo_clip_t      *clip)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_solid_pattern_t clear;
+    cairo_status_t status;
+
+    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
+    if (status)
+	return status;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
+	source = (cairo_pattern_t*) &clear;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+
+    return _cairo_win32_printing_surface_paint_pattern (surface, source);
+}
+
+static int
+_cairo_win32_line_cap (cairo_line_cap_t cap)
+{
+    switch (cap) {
+    case CAIRO_LINE_CAP_BUTT:
+	return PS_ENDCAP_FLAT;
+    case CAIRO_LINE_CAP_ROUND:
+	return PS_ENDCAP_ROUND;
+    case CAIRO_LINE_CAP_SQUARE:
+	return PS_ENDCAP_SQUARE;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static int
+_cairo_win32_line_join (cairo_line_join_t join)
+{
+    switch (join) {
+    case CAIRO_LINE_JOIN_MITER:
+	return PS_JOIN_MITER;
+    case CAIRO_LINE_JOIN_ROUND:
+	return PS_JOIN_ROUND;
+    case CAIRO_LINE_JOIN_BEVEL:
+	return PS_JOIN_BEVEL;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static void
+_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
+{
+    double s;
+
+    s = fabs (m->xx);
+    if (fabs (m->xy) > s)
+	s = fabs (m->xy);
+    if (fabs (m->yx) > s)
+	s = fabs (m->yx);
+    if (fabs (m->yy) > s)
+	s = fabs (m->yy);
+    *scale = s;
+    s = 1.0/s;
+    cairo_matrix_scale (m, s, s);
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_stroke (void			*abstract_surface,
+                                      cairo_operator_t		 op,
+                                      const cairo_pattern_t	*source,
+                                      const cairo_path_fixed_t	*path,
+                                      const cairo_stroke_style_t *style,
+                                      const cairo_matrix_t	*stroke_ctm,
+                                      const cairo_matrix_t	*stroke_ctm_inverse,
+                                      double			tolerance,
+                                      cairo_antialias_t		antialias,
+				      const cairo_clip_t    *clip)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
+    HPEN pen;
+    LOGBRUSH brush;
+    COLORREF color;
+    XFORM xform;
+    DWORD pen_style;
+    DWORD *dash_array;
+    HGDIOBJ obj;
+    unsigned int i;
+    cairo_solid_pattern_t clear;
+    cairo_matrix_t mat;
+    double scale;
+
+    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
+    if (status)
+	return status;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
+	source = (cairo_pattern_t*) &clear;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	/* Win32 does not support a dash offset. */
+	if (style->num_dashes > 0 && style->dash_offset != 0.0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+    }
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+    assert (!(style->num_dashes > 0 && style->dash_offset != 0.0));
+
+    cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm);
+    _cairo_matrix_factor_out_scale (&mat, &scale);
+
+    pen_style = PS_GEOMETRIC;
+    dash_array = NULL;
+    if (style->num_dashes) {
+	pen_style |= PS_USERSTYLE;
+	dash_array = calloc (sizeof (DWORD), style->num_dashes);
+	for (i = 0; i < style->num_dashes; i++) {
+	    dash_array[i] = (DWORD) (scale * style->dash[i]);
+	}
+    } else {
+	pen_style |= PS_SOLID;
+    }
+
+    SetMiterLimit (surface->dc, (FLOAT) (style->miter_limit), NULL);
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+
+
+	color = _cairo_win32_printing_surface_flatten_transparency (surface,
+								    &solid->color);
+    } else {
+	/* Color not used as the pen will only be used by WidenPath() */
+	color = RGB (0,0,0);
+    }
+    brush.lbStyle = BS_SOLID;
+    brush.lbColor = color;
+    brush.lbHatch = 0;
+    pen_style |= _cairo_win32_line_cap (style->line_cap);
+    pen_style |= _cairo_win32_line_join (style->line_join);
+    pen = ExtCreatePen(pen_style,
+		       scale * style->line_width,
+		       &brush,
+		       style->num_dashes,
+		       dash_array);
+    if (pen == NULL)
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen");
+    obj = SelectObject (surface->dc, pen);
+    if (obj == NULL)
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject");
+
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+    if (status)
+	return status;
+
+    /*
+     * Switch to user space to set line parameters
+     */
+    SaveDC (surface->dc);
+
+    _cairo_matrix_to_win32_xform (&mat, &xform);
+    xform.eDx = 0.0f;
+    xform.eDy = 0.0f;
+
+    if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY))
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform");
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	StrokePath (surface->dc);
+    } else {
+	if (!WidenPath (surface->dc))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath");
+	if (!SelectClipPath (surface->dc, RGN_AND))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath");
+
+	/* Return to device space to paint the pattern */
+	_cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform);
+	if (!SetWorldTransform (surface->dc, &xform))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform");
+	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
+    }
+    RestoreDC (surface->dc, -1);
+    DeleteObject (pen);
+    free (dash_array);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_fill (void		        *abstract_surface,
+				    cairo_operator_t		 op,
+				    const cairo_pattern_t	*source,
+				    const cairo_path_fixed_t	*path,
+				    cairo_fill_rule_t		 fill_rule,
+				    double			 tolerance,
+				    cairo_antialias_t		 antialias,
+				    const cairo_clip_t		*clip)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
+    cairo_solid_pattern_t clear;
+
+    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
+    if (status)
+	return status;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
+	source = (cairo_pattern_t*) &clear;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+
+    surface->path_empty = TRUE;
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	SetPolyFillMode (surface->dc, WINDING);
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	SetPolyFillMode (surface->dc, ALTERNATE);
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
+	if (status)
+	    return status;
+
+	FillPath (surface->dc);
+	_cairo_win32_printing_surface_done_solid_brush (surface);
+    } else if (surface->path_empty == FALSE) {
+	SaveDC (surface->dc);
+	SelectClipPath (surface->dc, RGN_AND);
+	status = _cairo_win32_printing_surface_paint_pattern (surface, source);
+	RestoreDC (surface->dc, -1);
+    }
+
+    fflush(stderr);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t 	*surface,
+						 cairo_operator_t	 op,
+						 const cairo_pattern_t  *source,
+						 cairo_glyph_t        	*glyphs,
+						 int			 num_glyphs,
+						 cairo_scaled_font_t  	*scaled_font,
+						 const cairo_clip_t	*clip)
+{
+    cairo_matrix_t ctm;
+    cairo_glyph_t  *unicode_glyphs;
+    cairo_scaled_font_subsets_glyph_t subset_glyph;
+    int i, first;
+    cairo_bool_t sequence_is_unicode;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    /* Where possible reverse the glyph indices back to unicode
+     * characters. Strings of glyphs that could not be reversed to
+     * unicode will be printed with ETO_GLYPH_INDEX.
+     *
+     * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
+     * operation, the font subsetting function
+     * _cairo_scaled_font_subsets_map_glyph() is used to obtain
+     * the unicode value because it caches the reverse mapping in
+     * the subsets.
+     */
+
+    if (surface->has_ctm) {
+	for (i = 0; i < num_glyphs; i++)
+	    cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y);
+	cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm);
+	scaled_font = cairo_scaled_font_create (scaled_font->font_face,
+						&scaled_font->font_matrix,
+						&ctm,
+						&scaled_font->options);
+    }
+
+    unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+    if (unicode_glyphs == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    memcpy (unicode_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+    for (i = 0; i < num_glyphs; i++) {
+	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+						       scaled_font,
+						       glyphs[i].index,
+						       NULL, 0,
+						       &subset_glyph);
+	if (status)
+	    goto fail;
+
+	unicode_glyphs[i].index = subset_glyph.unicode;
+    }
+
+    i = 0;
+    first = 0;
+    sequence_is_unicode = unicode_glyphs[0].index <= 0xffff;
+    while (i < num_glyphs) {
+	if (i == num_glyphs - 1 ||
+	    ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode))
+	{
+	    status = _cairo_win32_surface_show_glyphs_internal (
+		surface,
+		op,
+		source,
+		sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
+		i - first + 1,
+		scaled_font,
+		clip,
+		! sequence_is_unicode);
+	    first = i + 1;
+	    if (i < num_glyphs - 1)
+		sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff;
+	}
+	i++;
+    }
+
+fail:
+    if (surface->has_ctm)
+	cairo_scaled_font_destroy (scaled_font);
+
+    free (unicode_glyphs);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_show_glyphs (void                 *abstract_surface,
+                                           cairo_operator_t	 op,
+                                           const cairo_pattern_t *source,
+                                           cairo_glyph_t        *glyphs,
+                                           int			 num_glyphs,
+                                           cairo_scaled_font_t  *scaled_font,
+					   const cairo_clip_t	*clip)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_pattern_t *opaque = NULL;
+    int i;
+    cairo_matrix_t old_ctm;
+    cairo_bool_t old_has_ctm;
+    cairo_solid_pattern_t clear;
+
+    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
+    if (status)
+	return status;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
+	source = (cairo_pattern_t*) &clear;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	/* When printing bitmap fonts to a printer DC, Windows may
+	 * substitute an outline font for bitmap font. As the win32
+	 * font backend always uses a screen DC when obtaining the
+	 * font metrics the metrics of the substituted font will not
+	 * match the metrics that the win32 font backend returns.
+	 *
+	 * If we are printing a bitmap font, use fallback images to
+	 * ensure the font is not substituted.
+	 */
+#if CAIRO_HAS_WIN32_FONT
+	if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
+	    if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	    else
+		return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+	}
+#endif
+
+	/* For non win32 fonts we need to check that each glyph has a
+	 * path available. If a path is not available,
+	 * _cairo_scaled_glyph_lookup() will return
+	 * CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be
+	 * used.
+	 */
+	for (i = 0; i < num_glyphs; i++) {
+	    status = _cairo_scaled_glyph_lookup (scaled_font,
+						 glyphs[i].index,
+						 CAIRO_SCALED_GLYPH_INFO_PATH,
+						 &scaled_glyph);
+	    if (status)
+		return status;
+	}
+
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+    }
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+	COLORREF color;
+
+	color = _cairo_win32_printing_surface_flatten_transparency (surface,
+								    &solid->color);
+	opaque = cairo_pattern_create_rgb (GetRValue (color) / 255.0,
+					   GetGValue (color) / 255.0,
+					   GetBValue (color) / 255.0);
+	if (opaque->status)
+	    return opaque->status;
+	source = opaque;
+    }
+
+#if CAIRO_HAS_WIN32_FONT
+    if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
+	source->type == CAIRO_PATTERN_TYPE_SOLID)
+    {
+	return _cairo_win32_printing_surface_emit_win32_glyphs (surface,
+								op,
+								source,
+								glyphs,
+								num_glyphs,
+								scaled_font,
+								clip);
+    }
+#endif
+
+    SaveDC (surface->dc);
+    old_ctm = surface->ctm;
+    old_has_ctm = surface->has_ctm;
+    surface->has_ctm = TRUE;
+    surface->path_empty = TRUE;
+    BeginPath (surface->dc);
+    for (i = 0; i < num_glyphs; i++) {
+	status = _cairo_scaled_glyph_lookup (scaled_font,
+					     glyphs[i].index,
+					     CAIRO_SCALED_GLYPH_INFO_PATH,
+					     &scaled_glyph);
+	if (status)
+	    break;
+	surface->ctm = old_ctm;
+	cairo_matrix_translate (&surface->ctm, glyphs[i].x, glyphs[i].y);
+	status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path);
+    }
+    EndPath (surface->dc);
+    surface->ctm = old_ctm;
+    surface->has_ctm = old_has_ctm;
+    if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
+	if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	    status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
+	    if (status)
+		return status;
+
+	    SetPolyFillMode (surface->dc, WINDING);
+	    FillPath (surface->dc);
+	    _cairo_win32_printing_surface_done_solid_brush (surface);
+	} else {
+	    SelectClipPath (surface->dc, RGN_AND);
+	    status = _cairo_win32_printing_surface_paint_pattern (surface, source);
+	}
+    }
+    RestoreDC (surface->dc, -1);
+
+    if (opaque)
+	cairo_pattern_destroy (opaque);
+
+    return status;
+}
+
+static const char **
+_cairo_win32_printing_surface_get_supported_mime_types (void	  *abstract_surface)
+{
+    return _cairo_win32_printing_supported_mime_types;
+}
+
+static cairo_surface_t *
+_cairo_win32_printing_surface_create_similar (void		*abstract_surface,
+					      cairo_content_t	 content,
+					      int		 width,
+					      int		 height)
+{
+    cairo_rectangle_t extents;
+
+    extents.x = extents.y = 0;
+    extents.width  = width;
+    extents.height = height;
+    return cairo_recording_surface_create (content, &extents);
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_start_page (void *abstract_surface)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    XFORM xform;
+    double x_res, y_res;
+    cairo_matrix_t inverse_ctm;
+    cairo_status_t status;
+
+    SaveDC (surface->dc); /* Save application context first, before doing MWT */
+
+    /* As the logical coordinates used by GDI functions (eg LineTo)
+     * are integers we need to do some additional work to prevent
+     * rounding errors. For example the obvious way to paint a recording
+     * pattern is to:
+     *
+     *   SaveDC()
+     *   transform the device context DC by the pattern to device matrix
+     *   replay the recording surface
+     *   RestoreDC()
+     *
+     * The problem here is that if the pattern to device matrix is
+     * [100 0 0 100 0 0], coordinates in the recording pattern such as
+     * (1.56, 2.23) which correspond to (156, 223) in device space
+     * will be rounded to (100, 200) due to (1.56, 2.23) being
+     * truncated to integers.
+     *
+     * This is solved by saving the current GDI CTM in surface->ctm,
+     * switch the GDI CTM to identity, and transforming all
+     * coordinates by surface->ctm before passing them to GDI. When
+     * painting a recording pattern, surface->ctm is transformed by the
+     * pattern to device matrix.
+     *
+     * For printing device contexts where 1 unit is 1 dpi, switching
+     * the GDI CTM to identity maximises the possible resolution of
+     * coordinates.
+     *
+     * If the device context is an EMF file, using an identity
+     * transform often provides insufficent resolution. The workaround
+     * is to set the GDI CTM to a scale < 1 eg [1.0/16 0 0 1/0/16 0 0]
+     * and scale the cairo CTM by [16 0 0 16 0 0]. The
+     * SetWorldTransform function call to scale the GDI CTM by 1.0/16
+     * will be recorded in the EMF followed by all the graphics
+     * functions by their coordinateds multiplied by 16.
+     *
+     * To support allowing the user to set a GDI CTM with scale < 1,
+     * we avoid switching to an identity CTM if the CTM xx and yy is < 1.
+     */
+    SetGraphicsMode (surface->dc, GM_ADVANCED);
+    GetWorldTransform(surface->dc, &xform);
+    if (xform.eM11 < 1 && xform.eM22 < 1) {
+	cairo_matrix_init_identity (&surface->ctm);
+	surface->gdi_ctm.xx = xform.eM11;
+	surface->gdi_ctm.xy = xform.eM21;
+	surface->gdi_ctm.yx = xform.eM12;
+	surface->gdi_ctm.yy = xform.eM22;
+	surface->gdi_ctm.x0 = xform.eDx;
+	surface->gdi_ctm.y0 = xform.eDy;
+    } else {
+	surface->ctm.xx = xform.eM11;
+	surface->ctm.xy = xform.eM21;
+	surface->ctm.yx = xform.eM12;
+	surface->ctm.yy = xform.eM22;
+	surface->ctm.x0 = xform.eDx;
+	surface->ctm.y0 = xform.eDy;
+	cairo_matrix_init_identity (&surface->gdi_ctm);
+	if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY))
+	    return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform");
+    }
+
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
+    surface->has_gdi_ctm = !_cairo_matrix_is_identity (&surface->gdi_ctm);
+    inverse_ctm = surface->ctm;
+    status = cairo_matrix_invert (&inverse_ctm);
+    if (status)
+	return status;
+
+    x_res = GetDeviceCaps (surface->dc, LOGPIXELSX);
+    y_res = GetDeviceCaps (surface->dc, LOGPIXELSY);
+    cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res);
+    _cairo_surface_set_resolution (&surface->base, x_res, y_res);
+
+    SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
+                                                  cairo_paginated_mode_t paginated_mode)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+
+    surface->paginated_mode = paginated_mode;
+}
+
+static cairo_bool_t
+_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface)
+{
+    return TRUE;
+}
+
+/**
+ * cairo_win32_printing_surface_create:
+ * @hdc: the DC to create a surface for
+ *
+ * Creates a cairo surface that targets the given DC.  The DC will be
+ * queried for its initial clip extents, and this will be used as the
+ * size of the cairo surface.  The DC should be a printing DC;
+ * antialiasing will be ignored, and GDI will be used as much as
+ * possible to draw to the surface.
+ *
+ * The returned surface will be wrapped using the paginated surface to
+ * provide correct complex rendering behaviour; cairo_surface_show_page() and
+ * associated methods must be used for correct output.
+ *
+ * Return value: the newly created surface
+ *
+ * Since: 1.6
+ **/
+cairo_surface_t *
+cairo_win32_printing_surface_create (HDC hdc)
+{
+    cairo_win32_surface_t *surface;
+    cairo_surface_t *paginated;
+    RECT rect;
+
+    surface = malloc (sizeof (cairo_win32_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
+	free (surface);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    _cairo_surface_clipper_init (&surface->clipper,
+				 _cairo_win32_printing_surface_clipper_intersect_clip_path);
+
+    surface->image = NULL;
+    surface->format = CAIRO_FORMAT_RGB24;
+    surface->content = CAIRO_CONTENT_COLOR_ALPHA;
+
+    surface->dc = hdc;
+    surface->bitmap = NULL;
+    surface->is_dib = FALSE;
+    surface->saved_dc_bitmap = NULL;
+    surface->brush = NULL;
+    surface->old_brush = NULL;
+    surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
+    if (surface->font_subsets == NULL) {
+	free (surface);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    GetClipBox(hdc, &rect);
+    surface->extents.x = rect.left;
+    surface->extents.y = rect.top;
+    surface->extents.width = rect.right - rect.left;
+    surface->extents.height = rect.bottom - rect.top;
+
+    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
+    surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
+
+    _cairo_win32_printing_surface_init_ps_mode (surface);
+    _cairo_win32_printing_surface_init_image_support (surface);
+    _cairo_win32_printing_surface_init_language_pack (surface);
+    _cairo_surface_init (&surface->base,
+			 &cairo_win32_printing_surface_backend,
+			 NULL, /* device */
+                         CAIRO_CONTENT_COLOR_ALPHA);
+
+    paginated = _cairo_paginated_surface_create (&surface->base,
+						 CAIRO_CONTENT_COLOR_ALPHA,
+						 &cairo_win32_surface_paginated_backend);
+
+    /* paginated keeps the only reference to surface now, drop ours */
+    cairo_surface_destroy (&surface->base);
+
+    return paginated;
+}
+
+cairo_bool_t
+_cairo_surface_is_win32_printing (cairo_surface_t *surface)
+{
+    return surface->backend == &cairo_win32_printing_surface_backend;
+}
+
+static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
+    CAIRO_SURFACE_TYPE_WIN32_PRINTING,
+    _cairo_win32_surface_finish,
+
+    _cairo_default_context_create,
+
+    _cairo_win32_printing_surface_create_similar,
+    NULL, /* create similar image */
+    NULL, /* map to image */
+    NULL, /* unmap image */
+
+    _cairo_surface_default_source,
+    NULL, /* acquire_source_image */
+    NULL, /* release_source_image */
+    NULL, /* snapshot */
+
+    NULL, /* copy_page */
+    _cairo_win32_printing_surface_show_page,
+
+    _cairo_win32_surface_get_extents,
+    _cairo_win32_printing_surface_get_font_options,
+
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+
+    _cairo_win32_printing_surface_paint,
+    NULL, /* mask */
+    _cairo_win32_printing_surface_stroke,
+    _cairo_win32_printing_surface_fill,
+    NULL, /* fill/stroke */
+    _cairo_win32_printing_surface_show_glyphs,
+    NULL, /* has_show_text_glyphs */
+    NULL, /* show_text_glyphs */
+    _cairo_win32_printing_surface_get_supported_mime_types,
+};
+
+static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend = {
+    _cairo_win32_printing_surface_start_page,
+    _cairo_win32_printing_surface_set_paginated_mode,
+    NULL, /* set_bounding_box */
+    NULL, /* _cairo_win32_printing_surface_has_fallback_images, */
+    _cairo_win32_printing_surface_supports_fine_grained_fallbacks,
+};
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
new file mode 100644
index 0000000..07830dc
--- /dev/null
+++ b/src/win32/cairo-win32-private.h
@@ -0,0 +1,219 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ */
+
+#ifndef CAIRO_WIN32_PRIVATE_H
+#define CAIRO_WIN32_PRIVATE_H
+
+#include "cairo-win32.h"
+#include "cairoint.h"
+#include "cairo-surface-clipper-private.h"
+
+#ifndef SHADEBLENDCAPS
+#define SHADEBLENDCAPS 120
+#endif
+#ifndef SB_NONE
+#define SB_NONE 0
+#endif
+
+#define WIN32_FONT_LOGICAL_SCALE 32
+
+typedef struct _cairo_win32_surface {
+    cairo_surface_t base;
+
+    cairo_format_t format;
+
+    HDC dc;
+
+    /* We create off-screen surfaces as DIBs or DDBs, based on what we created
+     * originally*/
+    HBITMAP bitmap;
+    cairo_bool_t is_dib;
+
+    /* Used to save the initial 1x1 monochrome bitmap for the DC to
+     * select back into the DC before deleting the DC and our
+     * bitmap. For Windows XP, this doesn't seem to be necessary
+     * ... we can just delete the DC and that automatically unselects
+     * out bitmap. But it's standard practice so apparently is needed
+     * on some versions of Windows.
+     */
+    HBITMAP saved_dc_bitmap;
+
+    cairo_surface_t *image;
+
+    /* We use the x and y parts of extents for situations where
+     * we're not supposed to draw to the entire surface.
+     * For example, during a paint event a program will get
+     * a DC that has been clipped to the dirty region.
+     * A cairo surface constructed for that DC will have extents
+     * that match bounds of the clipped region.
+     *
+     * jrmuizel: I'm not sure if storing these extents instead
+     * of just using the size is better... */
+    cairo_rectangle_int_t extents;
+
+    /* Initial clip bits
+     * We need these kept around so that we maintain
+     * whatever clip was set on the original DC at creation
+     * time when cairo is asked to reset the surface clip.
+     */
+    cairo_rectangle_int_t clip_rect;
+    HRGN initial_clip_rgn;
+    cairo_bool_t had_simple_clip;
+    cairo_region_t *clip_region;
+
+    /* For path clipping to the printing-surface */
+    cairo_surface_clipper_t clipper;
+
+    /* Surface DC flags */
+    uint32_t flags;
+
+    /* printing surface bits */
+    cairo_paginated_mode_t paginated_mode;
+    cairo_content_t content;
+    cairo_bool_t path_empty;
+    cairo_bool_t has_ctm;
+    cairo_matrix_t ctm;
+    cairo_bool_t has_gdi_ctm;
+    cairo_matrix_t gdi_ctm;
+    HBRUSH brush, old_brush;
+    cairo_scaled_font_subsets_t *font_subsets;
+} cairo_win32_surface_t;
+
+/* Surface DC flag values */
+enum {
+    /* If this is a surface created for printing or not */
+    CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
+
+    /* Whether the DC is a display DC or not */
+    CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
+
+    /* Whether we can use BitBlt with this surface */
+    CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
+
+    /* Whether we can use AlphaBlend with this surface */
+    CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
+
+    /* Whether we can use StretchBlt with this surface */
+    CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
+
+    /* Whether we can use StretchDIBits with this surface */
+    CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5),
+
+    /* Whether we can use GradientFill rectangles with this surface */
+    CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
+
+    /* Whether we can use the CHECKJPEGFORMAT escape function */
+    CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
+
+    /* Whether we can use the CHECKJPEGFORMAT escape function */
+    CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
+};
+
+cairo_status_t
+_cairo_win32_print_gdi_error (const char *context);
+
+cairo_bool_t
+_cairo_surface_is_win32 (cairo_surface_t *surface);
+
+cairo_bool_t
+_cairo_surface_is_win32_printing (cairo_surface_t *surface);
+
+cairo_status_t
+_cairo_win32_surface_finish (void *abstract_surface);
+
+cairo_bool_t
+_cairo_win32_surface_get_extents (void		          *abstract_surface,
+				  cairo_rectangle_int_t   *rectangle);
+
+uint32_t
+_cairo_win32_flags_for_dc (HDC dc);
+
+cairo_status_t
+_cairo_win32_surface_set_clip_region (void           *abstract_surface,
+				      cairo_region_t *region);
+
+cairo_int_status_t
+_cairo_win32_surface_show_glyphs_internal (void			 *surface,
+					   cairo_operator_t	  op,
+					   const cairo_pattern_t *source,
+					   cairo_glyph_t	 *glyphs,
+					   int			  num_glyphs,
+					   cairo_scaled_font_t	 *scaled_font,
+					   const cairo_clip_t	 *clip,
+					   cairo_bool_t		  glyph_indices);
+
+cairo_int_status_t
+_cairo_win32_surface_show_glyphs (void			*surface,
+				  cairo_operator_t	 op,
+				  const cairo_pattern_t	*source,
+				  cairo_glyph_t		*glyphs,
+				  int			 num_glyphs,
+				  cairo_scaled_font_t	*scaled_font,
+				  const cairo_clip_t	*clip);
+
+cairo_surface_t *
+_cairo_win32_surface_create_similar (void	    *abstract_src,
+				     cairo_content_t content,
+				     int	     width,
+				     int	     height);
+
+static inline void
+_cairo_matrix_to_win32_xform (const cairo_matrix_t *m,
+                              XFORM *xform)
+{
+    xform->eM11 = (FLOAT) m->xx;
+    xform->eM21 = (FLOAT) m->xy;
+    xform->eM12 = (FLOAT) m->yx;
+    xform->eM22 = (FLOAT) m->yy;
+    xform->eDx = (FLOAT) m->x0;
+    xform->eDy = (FLOAT) m->y0;
+}
+
+cairo_int_status_t
+_cairo_win32_save_initial_clip (HDC dc, cairo_win32_surface_t *surface);
+
+cairo_int_status_t
+_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface);
+
+void
+_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header);
+
+cairo_bool_t
+_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
+
+cairo_bool_t
+_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font);
+
+#endif /* CAIRO_WIN32_PRIVATE_H */
diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c
new file mode 100644
index 0000000..ec351d3
--- /dev/null
+++ b/src/win32/cairo-win32-surface.c
@@ -0,0 +1,2087 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-clip-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
+#include "cairo-error-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-paginated-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-win32-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+#include "cairo-surface-fallback-private.h"
+#include "cairo-surface-backend-private.h"
+
+#include <wchar.h>
+#include <windows.h>
+
+#if defined(__MINGW32__) && !defined(ETO_PDY)
+# define ETO_PDY 0x2000
+#endif
+
+#undef DEBUG_COMPOSITE
+
+/* for older SDKs */
+#ifndef SHADEBLENDCAPS
+#define SHADEBLENDCAPS  120
+#endif
+#ifndef SB_NONE
+#define SB_NONE         0x00000000
+#endif
+
+#define PELS_72DPI  ((LONG)(72. / 0.0254))
+
+/**
+ * SECTION:cairo-win32
+ * @Title: Win32 Surfaces
+ * @Short_Description: Microsoft Windows surface support
+ * @See_Also: #cairo_surface_t
+ *
+ * The Microsoft Windows surface is used to render cairo graphics to
+ * Microsoft Windows windows, bitmaps, and printing device contexts.
+ *
+ * The surface returned by cairo_win32_printing_surface_create() is of surface
+ * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface
+ * type.
+ *
+ * The surface returned by the other win32 constructors is of surface type
+ * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type.
+ */
+
+/**
+ * CAIRO_HAS_WIN32_SURFACE:
+ *
+ * Defined if the Microsoft Windows surface backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ */
+
+static const cairo_surface_backend_t cairo_win32_surface_backend;
+
+/**
+ * _cairo_win32_print_gdi_error:
+ * @context: context string to display along with the error
+ *
+ * Helper function to dump out a human readable form of the
+ * current error code.
+ *
+ * Return value: A cairo status code for the error code
+ **/
+cairo_status_t
+_cairo_win32_print_gdi_error (const char *context)
+{
+    void *lpMsgBuf;
+    DWORD last_error = GetLastError ();
+
+    if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			 FORMAT_MESSAGE_FROM_SYSTEM,
+			 NULL,
+			 last_error,
+			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+			 (LPWSTR) &lpMsgBuf,
+			 0, NULL)) {
+	fprintf (stderr, "%s: Unknown GDI error", context);
+    } else {
+	fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf);
+
+	LocalFree (lpMsgBuf);
+    }
+
+    fflush (stderr);
+
+    /* We should switch off of last_status, but we'd either return
+     * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there
+     * is no CAIRO_STATUS_UNKNOWN_ERROR.
+     */
+
+    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+}
+
+uint32_t
+_cairo_win32_flags_for_dc (HDC dc)
+{
+    uint32_t flags = 0;
+
+    if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
+	flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY;
+
+	/* These will always be possible, but the actual GetDeviceCaps
+	 * calls will return whether they're accelerated or not.
+	 * We may want to use our own (pixman) routines sometimes
+	 * if they're eventually faster, but for now have GDI do
+	 * everything.
+	 */
+	flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
+	flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+	flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
+    } else {
+	int cap;
+
+	cap = GetDeviceCaps(dc, SHADEBLENDCAPS);
+	if (cap != SB_NONE)
+	    flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
+
+	cap = GetDeviceCaps(dc, RASTERCAPS);
+	if (cap & RC_BITBLT)
+	    flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
+	if (cap & RC_STRETCHBLT)
+	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+	if (cap & RC_STRETCHDIB)
+	    flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
+    }
+
+    return flags;
+}
+
+static cairo_status_t
+_create_dc_and_bitmap (cairo_win32_surface_t *surface,
+		       HDC                    original_dc,
+		       cairo_format_t         format,
+		       int                    width,
+		       int                    height,
+		       unsigned char        **bits_out,
+		       int                   *rowstride_out)
+{
+    cairo_status_t status;
+
+    BITMAPINFO *bitmap_info = NULL;
+    struct {
+	BITMAPINFOHEADER bmiHeader;
+	RGBQUAD bmiColors[2];
+    } bmi_stack;
+    void *bits;
+
+    int num_palette = 0;	/* Quiet GCC */
+    int i;
+
+    surface->dc = NULL;
+    surface->bitmap = NULL;
+    surface->is_dib = FALSE;
+
+    switch (format) {
+    default:
+    case CAIRO_FORMAT_INVALID:
+	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
+    case CAIRO_FORMAT_ARGB32:
+    case CAIRO_FORMAT_RGB24:
+	num_palette = 0;
+	break;
+
+    case CAIRO_FORMAT_A8:
+	num_palette = 256;
+	break;
+
+    case CAIRO_FORMAT_A1:
+	num_palette = 2;
+	break;
+    }
+
+    if (num_palette > 2) {
+	bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
+	if (!bitmap_info)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else {
+	bitmap_info = (BITMAPINFO *)&bmi_stack;
+    }
+
+    bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+    bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
+    bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
+    bitmap_info->bmiHeader.biSizeImage = 0;
+    bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
+    bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
+    bitmap_info->bmiHeader.biPlanes = 1;
+
+    switch (format) {
+    /* We can't create real RGB24 bitmaps because something seems to
+     * break if we do, especially if we don't set up an image
+     * fallback.  It could be a bug with using a 24bpp pixman image
+     * (and creating one with masks).  So treat them like 32bpp.
+     * Note: This causes problems when using BitBlt/AlphaBlend/etc!
+     * see end of file.
+     */
+    case CAIRO_FORMAT_RGB24:
+    case CAIRO_FORMAT_ARGB32:
+	bitmap_info->bmiHeader.biBitCount = 32;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 0;	/* unused */
+	bitmap_info->bmiHeader.biClrImportant = 0;
+	break;
+
+    case CAIRO_FORMAT_A8:
+	bitmap_info->bmiHeader.biBitCount = 8;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 256;
+	bitmap_info->bmiHeader.biClrImportant = 0;
+
+	for (i = 0; i < 256; i++) {
+	    bitmap_info->bmiColors[i].rgbBlue = i;
+	    bitmap_info->bmiColors[i].rgbGreen = i;
+	    bitmap_info->bmiColors[i].rgbRed = i;
+	    bitmap_info->bmiColors[i].rgbReserved = 0;
+	}
+
+	break;
+
+    case CAIRO_FORMAT_A1:
+	bitmap_info->bmiHeader.biBitCount = 1;
+	bitmap_info->bmiHeader.biCompression = BI_RGB;
+	bitmap_info->bmiHeader.biClrUsed = 2;
+	bitmap_info->bmiHeader.biClrImportant = 0;
+
+	for (i = 0; i < 2; i++) {
+	    bitmap_info->bmiColors[i].rgbBlue = i * 255;
+	    bitmap_info->bmiColors[i].rgbGreen = i * 255;
+	    bitmap_info->bmiColors[i].rgbRed = i * 255;
+	    bitmap_info->bmiColors[i].rgbReserved = 0;
+	}
+
+	break;
+    }
+
+    surface->dc = CreateCompatibleDC (original_dc);
+    if (!surface->dc)
+	goto FAIL;
+
+    surface->bitmap = CreateDIBSection (surface->dc,
+			                bitmap_info,
+			                DIB_RGB_COLORS,
+			                &bits,
+			                NULL, 0);
+    if (!surface->bitmap)
+	goto FAIL;
+
+    surface->is_dib = TRUE;
+
+    GdiFlush();
+
+    surface->saved_dc_bitmap = SelectObject (surface->dc,
+					     surface->bitmap);
+    if (!surface->saved_dc_bitmap)
+	goto FAIL;
+
+    if (bitmap_info && num_palette > 2)
+	free (bitmap_info);
+
+    if (bits_out)
+	*bits_out = bits;
+
+    if (rowstride_out) {
+	/* Windows bitmaps are padded to 32-bit (dword) boundaries */
+	switch (format) {
+	case CAIRO_FORMAT_ARGB32:
+	case CAIRO_FORMAT_RGB24:
+	    *rowstride_out = 4 * width;
+	    break;
+
+	case CAIRO_FORMAT_A8:
+	    *rowstride_out = (width + 3) & ~3;
+	    break;
+
+	case CAIRO_FORMAT_A1:
+	    *rowstride_out = ((width + 31) & ~31) / 8;
+	    break;
+	}
+    }
+
+    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
+
+    return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+    status = _cairo_win32_print_gdi_error ("_create_dc_and_bitmap");
+
+    if (bitmap_info && num_palette > 2)
+	free (bitmap_info);
+
+    if (surface->saved_dc_bitmap) {
+	SelectObject (surface->dc, surface->saved_dc_bitmap);
+	surface->saved_dc_bitmap = NULL;
+    }
+
+    if (surface->bitmap) {
+	DeleteObject (surface->bitmap);
+	surface->bitmap = NULL;
+    }
+
+    if (surface->dc) {
+ 	DeleteDC (surface->dc);
+	surface->dc = NULL;
+    }
+
+    return status;
+}
+
+static cairo_surface_t *
+_cairo_win32_surface_create_for_dc (HDC             original_dc,
+				    cairo_format_t  format,
+				    int	            width,
+				    int	            height)
+{
+    cairo_status_t status;
+    cairo_win32_surface_t *surface;
+    unsigned char *bits;
+    int rowstride;
+
+    if (! CAIRO_FORMAT_VALID (format))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+
+    surface = malloc (sizeof (cairo_win32_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    surface->clip_region = NULL;
+
+    status = _create_dc_and_bitmap (surface, original_dc, format,
+				    width, height,
+				    &bits, &rowstride);
+    if (status)
+	goto FAIL;
+
+    surface->image = cairo_image_surface_create_for_data (bits, format,
+							  width, height, rowstride);
+    status = surface->image->status;
+    if (status)
+	goto FAIL;
+
+    surface->format = format;
+
+    surface->clip_rect.x = 0;
+    surface->clip_rect.y = 0;
+    surface->clip_rect.width = width;
+    surface->clip_rect.height = height;
+
+    surface->initial_clip_rgn = NULL;
+    surface->had_simple_clip = FALSE;
+
+    surface->extents = surface->clip_rect;
+    surface->font_subsets = NULL;
+
+    _cairo_surface_init (&surface->base,
+			 &cairo_win32_surface_backend,
+			 NULL, /* device */
+			 _cairo_content_from_format (format));
+
+    return &surface->base;
+
+ FAIL:
+    if (surface->bitmap) {
+	SelectObject (surface->dc, surface->saved_dc_bitmap);
+	DeleteObject (surface->bitmap);
+	DeleteDC (surface->dc);
+    }
+    free (surface);
+
+    return _cairo_surface_create_in_error (status);
+}
+
+static cairo_surface_t *
+_cairo_win32_surface_create_similar_internal (void	    *abstract_src,
+					      cairo_content_t content,
+					      int	     width,
+					      int	     height,
+					      cairo_bool_t   force_dib)
+{
+    cairo_win32_surface_t *src = abstract_src;
+    cairo_format_t format = _cairo_format_from_content (content);
+    cairo_surface_t *new_surf = NULL;
+
+    /* We force a DIB always if:
+     * - we need alpha; or
+     * - the parent is a DIB; or
+     * - the parent is for printing (because we don't care about the bit depth at that point)
+     *
+     * We also might end up with a DIB even if a DDB is requested if DDB creation failed
+     * due to out of memory.
+     */
+    if (src->is_dib ||
+	(content & CAIRO_CONTENT_ALPHA) ||
+	src->base.backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
+    {
+	force_dib = TRUE;
+    }
+
+    if (!force_dib) {
+	/* try to create a ddb */
+	new_surf = cairo_win32_surface_create_with_ddb (src->dc, CAIRO_FORMAT_RGB24, width, height);
+
+	if (new_surf->status != CAIRO_STATUS_SUCCESS)
+	    new_surf = NULL;
+    }
+
+    if (new_surf == NULL) {
+	new_surf = _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
+    }
+
+    return new_surf;
+}
+
+cairo_surface_t *
+_cairo_win32_surface_create_similar (void	    *abstract_src,
+				     cairo_content_t content,
+				     int	     width,
+				     int	     height)
+{
+    return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE);
+}
+
+cairo_status_t
+_cairo_win32_surface_finish (void *abstract_surface)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+
+    if (surface->image)
+	cairo_surface_destroy (surface->image);
+
+    /* If we created the Bitmap and DC, destroy them */
+    if (surface->bitmap) {
+	SelectObject (surface->dc, surface->saved_dc_bitmap);
+	DeleteObject (surface->bitmap);
+	DeleteDC (surface->dc);
+    } else {
+	_cairo_win32_restore_initial_clip (surface);
+    }
+
+    if (surface->initial_clip_rgn)
+	DeleteObject (surface->initial_clip_rgn);
+
+    if (surface->font_subsets != NULL)
+	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
+				   int                     x,
+				   int                     y,
+				   int                     width,
+				   int                     height,
+				   cairo_win32_surface_t **local_out)
+{
+    cairo_win32_surface_t *local;
+    cairo_int_status_t status;
+    cairo_content_t content = _cairo_content_from_format (surface->format);
+
+    local =
+	(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
+	(surface, content, width, height, TRUE);
+    if (local == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (local->base.status)
+	return local->base.status;
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Only BitBlt if the source surface supports it. */
+    if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
+	BitBlt (local->dc,
+		0, 0,
+		width, height,
+		surface->dc,
+		x, y,
+		SRCCOPY))
+    {
+	status = CAIRO_STATUS_SUCCESS;
+    }
+
+    if (status) {
+	/* If we failed here, most likely the source or dest doesn't
+	 * support BitBlt/AlphaBlend (e.g. a printer).
+	 * You can't reliably get bits from a printer DC, so just fill in
+	 * the surface as white (common case for printing).
+	 */
+
+	RECT r;
+	r.left = r.top = 0;
+	r.right = width;
+	r.bottom = height;
+	FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
+    }
+
+    *local_out = local;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_surface_t *
+_cairo_win32_surface_map_to_image (void                    *abstract_surface,
+				   const cairo_rectangle_int_t   *extents)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_surface_t *local = NULL;
+    cairo_status_t status;
+
+    if (surface->image) {
+	GdiFlush();
+	return _cairo_surface_create_for_rectangle_int (surface->image,
+							extents);
+    }
+
+    status = _cairo_win32_surface_get_subimage (abstract_surface,
+						extents->x,
+						extents->y,
+						extents->width,
+						extents->height,
+						&local);
+    if (unlikely (status))
+	return _cairo_surface_create_in_error (status);
+
+    status = cairo_surface_set_user_data (local->image,
+					  (const cairo_user_data_key_t *)surface->image,
+					  local, NULL);
+    if (unlikely (status)) {
+	cairo_surface_destroy (&local->base);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    cairo_surface_set_device_offset (local->image, -extents->x, -extents->y);
+    return local->image;
+}
+
+static cairo_int_status_t
+_cairo_win32_surface_unmap_image (void                    *abstract_surface,
+				  cairo_image_surface_t   *image)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_surface_t *local;
+
+    local = cairo_surface_get_user_data (&image->base,
+					 (const cairo_user_data_key_t *) surface->image);
+    if (!local)
+	return CAIRO_INT_STATUS_SUCCESS;
+
+    if (!BitBlt (surface->dc,
+		 image->base.device_transform.x0,
+		 image->base.device_transform.y0,
+		 image->width, image->height,
+		 local->dc,
+		 0, 0,
+		 SRCCOPY))
+	_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
+					   cairo_image_surface_t  **image_out,
+					   void                   **image_extra)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_win32_surface_t *local;
+    cairo_status_t status;
+
+    if (surface->image) {
+	*image_out = (cairo_image_surface_t *)surface->image;
+	*image_extra = NULL;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
+						surface->extents.width,
+						surface->extents.height, &local);
+    if (status)
+	return status;
+
+    *image_out = (cairo_image_surface_t *)local->image;
+    *image_extra = local;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_surface_release_source_image (void                   *abstract_surface,
+					   cairo_image_surface_t  *image,
+					   void                   *image_extra)
+{
+    cairo_win32_surface_t *local = image_extra;
+
+    if (local)
+	cairo_surface_destroy ((cairo_surface_t *)local);
+}
+
+cairo_status_t
+_cairo_win32_surface_set_clip_region (void           *abstract_surface,
+				      cairo_region_t *region)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (surface->clip_region == region)
+	return CAIRO_STATUS_SUCCESS;
+
+    cairo_region_destroy (surface->clip_region);
+    surface->clip_region = cairo_region_reference (region);
+
+    /* The semantics we want is that any clip set by cairo combines
+     * is intersected with the clip on device context that the
+     * surface was created for. To implement this, we need to
+     * save the original clip when first setting a clip on surface.
+     */
+
+    /* Clear any clip set by cairo, return to the original first */
+    status = _cairo_win32_restore_initial_clip (surface);
+
+    /* Then combine any new region with it */
+    if (region) {
+	cairo_rectangle_int_t extents;
+	int num_rects;
+	RGNDATA *data;
+	size_t data_size;
+	RECT *rects;
+	int i;
+	HRGN gdi_region;
+
+	/* Create a GDI region for the cairo region */
+
+	cairo_region_get_extents (region, &extents);
+	num_rects = cairo_region_num_rectangles (region);
+	/* XXX see notes in _cairo_win32_save_initial_clip --
+	 * this code will interact badly with a HDC which had an initial
+	 * world transform -- we should probably manually transform the
+	 * region rects, because SelectClipRgn takes device units, not
+	 * logical units (unlike IntersectClipRect).
+	 */
+
+	data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
+	data = malloc (data_size);
+	if (!data)
+	    return _cairo_error(CAIRO_STATUS_NO_MEMORY);
+	rects = (RECT *)data->Buffer;
+
+	data->rdh.dwSize = sizeof (RGNDATAHEADER);
+	data->rdh.iType = RDH_RECTANGLES;
+	data->rdh.nCount = num_rects;
+	data->rdh.nRgnSize = num_rects * sizeof (RECT);
+	data->rdh.rcBound.left = extents.x;
+	data->rdh.rcBound.top = extents.y;
+	data->rdh.rcBound.right = extents.x + extents.width;
+	data->rdh.rcBound.bottom = extents.y + extents.height;
+
+	for (i = 0; i < num_rects; i++) {
+	    cairo_rectangle_int_t rect;
+
+	    cairo_region_get_rectangle (region, i, &rect);
+
+	    rects[i].left   = rect.x;
+	    rects[i].top    = rect.y;
+	    rects[i].right  = rect.x + rect.width;
+	    rects[i].bottom = rect.y + rect.height;
+	}
+
+	gdi_region = ExtCreateRegion (NULL, data_size, data);
+	free (data);
+
+	if (!gdi_region)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	/* AND the new region into our DC */
+	if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
+	    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
+
+	DeleteObject (gdi_region);
+    }
+
+    return status;
+}
+
+#if !defined(AC_SRC_OVER)
+#define AC_SRC_OVER                 0x00
+#pragma pack(1)
+typedef struct {
+    BYTE   BlendOp;
+    BYTE   BlendFlags;
+    BYTE   SourceConstantAlpha;
+    BYTE   AlphaFormat;
+}BLENDFUNCTION;
+#pragma pack()
+#endif
+
+/* for compatibility with VC++ 6 */
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA                0x01
+#endif
+
+typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest,
+						 int nXOriginDest,
+						 int nYOriginDest,
+						 int nWidthDest,
+						 int hHeightDest,
+						 HDC hdcSrc,
+						 int nXOriginSrc,
+						 int nYOriginSrc,
+						 int nWidthSrc,
+						 int nHeightSrc,
+						 BLENDFUNCTION blendFunction);
+
+static cairo_int_status_t
+_composite_alpha_blend (cairo_win32_surface_t *dst,
+			cairo_win32_surface_t *src,
+			int                    alpha,
+			int                    src_x,
+			int                    src_y,
+			int                    src_w,
+			int                    src_h,
+			int                    dst_x,
+			int                    dst_y,
+			int                    dst_w,
+			int                    dst_h)
+{
+    static unsigned alpha_blend_checked = FALSE;
+    static cairo_alpha_blend_func_t alpha_blend = NULL;
+
+    BLENDFUNCTION blend_function;
+
+    /* Check for AlphaBlend dynamically to allow compiling on
+     * MSVC 6 and use on older windows versions
+     */
+    if (!alpha_blend_checked) {
+	OSVERSIONINFO os;
+
+	os.dwOSVersionInfoSize = sizeof (os);
+	GetVersionEx (&os);
+
+	/* If running on Win98, disable using AlphaBlend()
+	 * to avoid Win98 AlphaBlend() bug */
+	if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
+	    os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
+	{
+	    HMODULE msimg32_dll = LoadLibraryW (L"msimg32");
+
+	    if (msimg32_dll != NULL)
+		alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,
+									"AlphaBlend");
+	}
+
+	alpha_blend_checked = TRUE;
+    }
+
+    if (alpha_blend == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    blend_function.BlendOp = AC_SRC_OVER;
+    blend_function.BlendFlags = 0;
+    blend_function.SourceConstantAlpha = alpha;
+    blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
+
+    if (!alpha_blend (dst->dc,
+		      dst_x, dst_y,
+		      dst_w, dst_h,
+		      src->dc,
+		      src_x, src_y,
+		      src_w, src_h,
+		      blend_function))
+	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
+				      cairo_image_surface_t *src_image,
+				      cairo_win32_surface_t *dst,
+				      cairo_rectangle_int_t src_extents,
+				      cairo_rectangle_int_t src_r,
+				      cairo_rectangle_int_t dst_r,
+				      int alpha,
+				      cairo_bool_t needs_alpha,
+				      cairo_bool_t needs_scale)
+{
+    /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
+    if (src_image) {
+	if (needs_alpha || needs_scale)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
+	    BITMAPINFO bi;
+	    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+	    bi.bmiHeader.biWidth = src_image->width;
+	    bi.bmiHeader.biHeight = - src_image->height;
+	    bi.bmiHeader.biSizeImage = 0;
+	    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+	    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+	    bi.bmiHeader.biPlanes = 1;
+	    bi.bmiHeader.biBitCount = 32;
+	    bi.bmiHeader.biCompression = BI_RGB;
+	    bi.bmiHeader.biClrUsed = 0;
+	    bi.bmiHeader.biClrImportant = 0;
+
+	    /* StretchDIBits is broken with top-down dibs; you need to do some
+	     * special munging to make the coordinate space work (basically,
+	     * need to address everything based on the bottom left, instead of top left,
+	     * and need to tell it to flip the resulting image.
+	     *
+	     * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
+	     */
+	    if (!StretchDIBits (dst->dc,
+				/* dst x,y,w,h */
+				dst_r.x, dst_r.y + dst_r.height - 1,
+				dst_r.width, - (int) dst_r.height,
+				/* src x,y,w,h */
+				src_r.x, src_extents.height - src_r.y + 1,
+				src_r.width, - (int) src_r.height,
+				src_image->data,
+				&bi,
+				DIB_RGB_COLORS,
+				SRCCOPY))
+		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
+	}
+    } else if (!needs_alpha) {
+	/* BitBlt or StretchBlt? */
+	if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
+	    if (!BitBlt (dst->dc,
+			 dst_r.x, dst_r.y,
+			 dst_r.width, dst_r.height,
+			 src->dc,
+			 src_r.x, src_r.y,
+			 SRCCOPY))
+		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
+	} else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
+	    /* StretchBlt? */
+	    /* XXX check if we want HALFTONE, based on the src filter */
+	    BOOL success;
+	    int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
+	    success = StretchBlt(dst->dc,
+				 dst_r.x, dst_r.y,
+				 dst_r.width, dst_r.height,
+				 src->dc,
+				 src_r.x, src_r.y,
+				 src_r.width, src_r.height,
+				 SRCCOPY);
+	    SetStretchBltMode(dst->dc, oldmode);
+
+	    if (!success)
+		return _cairo_win32_print_gdi_error ("StretchBlt");
+	}
+    } else if (needs_alpha && !needs_scale) {
+  	return _composite_alpha_blend (dst, src, alpha,
+				       src_r.x, src_r.y, src_r.width, src_r.height,
+				       dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* from pixman-private.h */
+#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
+
+static cairo_int_status_t
+_cairo_win32_surface_composite (cairo_operator_t	op,
+				const cairo_pattern_t	*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,
+				cairo_region_t	       *clip_region)
+{
+    cairo_win32_surface_t *dst = abstract_dst;
+    cairo_win32_surface_t *src;
+    cairo_surface_pattern_t *src_surface_pattern;
+    int alpha;
+    double scalex, scaley;
+    cairo_fixed_t x0_fixed, y0_fixed;
+    cairo_int_status_t status;
+
+    cairo_bool_t needs_alpha, needs_scale, needs_repeat;
+    cairo_image_surface_t *src_image = NULL;
+
+    cairo_format_t src_format;
+    cairo_rectangle_int_t src_extents;
+
+    cairo_rectangle_int_t src_r = { src_x, src_y, width, height };
+    cairo_rectangle_int_t dst_r = { dst_x, dst_y, width, height };
+
+#ifdef DEBUG_COMPOSITE
+    fprintf (stderr, "+++ composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
+	     op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
+#endif
+
+    /* If the destination can't do any of these, then
+     * we may as well give up, since this is what we'll
+     * look to for optimization.
+     */
+    if ((dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT |
+		       CAIRO_WIN32_SURFACE_CAN_ALPHABLEND |
+		       CAIRO_WIN32_SURFACE_CAN_STRETCHBLT |
+		       CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
+	== 0)
+    {
+	goto UNSUPPORTED;
+    }
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
+	goto UNSUPPORTED;
+
+    if (pattern->extend != CAIRO_EXTEND_NONE &&
+	pattern->extend != CAIRO_EXTEND_REPEAT)
+	goto UNSUPPORTED;
+
+    if (mask_pattern) {
+	/* FIXME: When we fully support RENDER style 4-channel
+	 * masks we need to check r/g/b != 1.0.
+	 */
+	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
+    } else {
+	alpha = 255;
+    }
+
+    src_surface_pattern = (cairo_surface_pattern_t *)pattern;
+    src = (cairo_win32_surface_t *)src_surface_pattern->surface;
+
+    if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE &&
+	dst->flags & (CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
+    {
+	/* In some very limited cases, we can use StretchDIBits to draw
+	 * an image surface directly:
+	 *  - source is CAIRO_FORMAT_ARGB32
+	 *  - dest is CAIRO_FORMAT_ARGB32
+	 *  - alpha is 255
+	 *  - operator is SOURCE or OVER
+	 *  - image stride is 4*width
+	 */
+	src_image = (cairo_image_surface_t*) src;
+
+	if (src_image->format != CAIRO_FORMAT_RGB24 ||
+	    dst->format != CAIRO_FORMAT_RGB24 ||
+	    alpha != 255 ||
+	    (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
+	    src_image->stride != (src_image->width * 4))
+	{
+	    goto UNSUPPORTED;
+	}
+
+	src_format = src_image->format;
+	src_extents.x = 0;
+	src_extents.y = 0;
+	src_extents.width = src_image->width;
+	src_extents.height = src_image->height;
+    } else if (src->base.backend != dst->base.backend) {
+	goto UNSUPPORTED;
+    } else {
+	src_format = src->format;
+	src_extents = src->extents;
+    }
+
+
+#ifdef DEBUG_COMPOSITE
+    fprintf (stderr, "Before check: src size: (%d %d) xy [%d %d] -> dst [%d %d %d %d] {srcmat %f %f %f %f}\n",
+	     src_extents.width, src_extents.height,
+	     src_x, src_y,
+	     dst_x, dst_y, width, height,
+	     pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy);
+#endif
+
+    /* We can only use GDI functions if the source and destination rectangles
+     * are on integer pixel boundaries.  Figure that out here.
+     */
+    x0_fixed = _cairo_fixed_from_double(pattern->matrix.x0 / pattern->matrix.xx);
+    y0_fixed = _cairo_fixed_from_double(pattern->matrix.y0 / pattern->matrix.yy);
+
+    if (pattern->matrix.yx != 0.0 ||
+	pattern->matrix.xy != 0.0 ||
+	!_cairo_fixed_is_integer(x0_fixed) ||
+	!_cairo_fixed_is_integer(y0_fixed))
+    {
+	goto UNSUPPORTED;
+    }
+
+    scalex = pattern->matrix.xx;
+    scaley = pattern->matrix.yy;
+
+    src_r.x += _cairo_fixed_integer_part(x0_fixed);
+    src_r.y += _cairo_fixed_integer_part(y0_fixed);
+
+    /* Success, right? */
+    if (scalex == 0.0 || scaley == 0.0)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (scalex != 1.0 || scaley != 1.0)
+	goto UNSUPPORTED;
+
+    /* If the src coordinates are outside of the source surface bounds,
+     * we have to fix them up, because this is an error for the GDI
+     * functions.
+     */
+
+#ifdef DEBUG_COMPOSITE
+    fprintf (stderr, "before: [%d %d %d %d] -> [%d %d %d %d]\n",
+	     src_r.x, src_r.y, src_r.width, src_r.height,
+	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+    fflush (stderr);
+#endif
+
+    /* If the src rectangle doesn't wholly lie within the src extents,
+     * fudge things.  We really need to do fixup on the unpainted
+     * region -- e.g. the SOURCE operator is broken for areas outside
+     * of the extents, because it won't clear that area to transparent
+     * black.
+     */
+
+    if (pattern->extend != CAIRO_EXTEND_REPEAT) {
+	needs_repeat = FALSE;
+
+	/* If the src rect and the extents of the source image don't overlap at all,
+	 * we can't do anything useful here.
+	 */
+	if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
+	    (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
+	{
+	    if (op == CAIRO_OPERATOR_OVER)
+		return CAIRO_STATUS_SUCCESS;
+	    goto UNSUPPORTED;
+	}
+
+	if (src_r.x < 0) {
+	    src_r.width += src_r.x;
+	    src_r.x = 0;
+
+	    dst_r.width += src_r.x;
+	    dst_r.x -= src_r.x;
+	}
+
+	if (src_r.y < 0) {
+	    src_r.height += src_r.y;
+	    src_r.y = 0;
+
+	    dst_r.height += dst_r.y;
+	    dst_r.y -= src_r.y;
+	}
+
+	if (src_r.x + src_r.width > src_extents.width) {
+	    src_r.width = src_extents.width - src_r.x;
+	    dst_r.width = src_r.width;
+	}
+
+	if (src_r.y + src_r.height > src_extents.height) {
+	    src_r.height = src_extents.height - src_r.y;
+	    dst_r.height = src_r.height;
+	}
+    } else {
+	needs_repeat = TRUE;
+    }
+
+    /*
+     * Operations that we can do:
+     *
+     *  RGB OVER  RGB -> BitBlt (same as SOURCE)
+     *  RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+     * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
+     * ARGB OVER  RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
+     * 
+     *  RGB OVER  RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
+     *  RGB OVER ARGB + mask -> UNSUPPORTED
+     * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
+     * ARGB OVER  RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
+     * 
+     *  RGB SOURCE  RGB -> BitBlt
+     *  RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+     * ARGB SOURCE ARGB -> BitBlt
+     * ARGB SOURCE  RGB -> BitBlt
+     * 
+     *  RGB SOURCE  RGB + mask -> unsupported
+     *  RGB SOURCE ARGB + mask -> unsupported
+     * ARGB SOURCE ARGB + mask -> unsupported
+     * ARGB SOURCE  RGB + mask -> unsupported
+     */
+
+    /*
+     * Figure out what action to take.
+     */
+    if (op == CAIRO_OPERATOR_OVER) {
+	if (alpha == 0)
+	    return CAIRO_STATUS_SUCCESS;
+
+	if (src_format == dst->format) {
+	    if (alpha == 255 && src_format == CAIRO_FORMAT_RGB24) {
+		needs_alpha = FALSE;
+	    } else {
+		needs_alpha = TRUE;
+	    }
+	} else if (src_format == CAIRO_FORMAT_ARGB32 &&
+		   dst->format == CAIRO_FORMAT_RGB24)
+	{
+	    needs_alpha = TRUE;
+	} else {
+	    goto UNSUPPORTED;
+	}
+    } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
+	if ((src_format == dst->format) ||
+	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
+	{
+	    needs_alpha = FALSE;
+	} else {
+	    goto UNSUPPORTED;
+	}
+    } else {
+	goto UNSUPPORTED;
+    }
+
+    if (scalex == 1.0 && scaley == 1.0) {
+	needs_scale = FALSE;
+    } else {
+	/* Should never be reached until we turn StretchBlt back on */
+	needs_scale = TRUE;
+    }
+
+#ifdef DEBUG_COMPOSITE
+    fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
+	     src_r.x, src_r.y, src_r.width, src_r.height,
+	     dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+    fflush (stderr);
+#endif
+
+    status = _cairo_win32_surface_set_clip_region (dst, clip_region);
+    if (status)
+	return status;
+
+    /* If we need to repeat, we turn the repeated blit into
+     * a bunch of piece-by-piece blits.
+     */
+    if (needs_repeat) {
+	cairo_rectangle_int_t piece_src_r, piece_dst_r;
+	uint32_t rendered_width = 0, rendered_height = 0;
+	uint32_t to_render_height, to_render_width;
+	int32_t piece_x, piece_y;
+	int32_t src_start_x = MOD(src_r.x, src_extents.width);
+	int32_t src_start_y = MOD(src_r.y, src_extents.height);
+
+	if (needs_scale)
+	    goto UNSUPPORTED;
+
+	/* If both the src and dest have an image, we may as well fall
+	 * back, because it will be faster than our separate blits.
+	 * Our blit code will be fastest when the src is a DDB and the
+	 * destination is a DDB.
+	 */
+	if ((src_image || src->image) && dst->image)
+	    goto UNSUPPORTED;
+
+	/* If the src is not a bitmap but an on-screen (or unknown)
+	 * DC, chances are that fallback will be faster.
+	 */
+	if (src->bitmap == NULL)
+	    goto UNSUPPORTED;
+
+	/* If we can use PatBlt, just do so */
+	if (!src_image && !needs_alpha)
+	{
+	    HBRUSH brush;
+	    HGDIOBJ old_brush;
+	    POINT old_brush_origin;
+
+	    /* Set up the brush with our bitmap */
+	    brush = CreatePatternBrush (src->bitmap);
+
+	    /* SetBrushOrgEx sets the coordinates in the destination DC of where the
+	     * pattern should start.
+	     */
+	    SetBrushOrgEx (dst->dc, dst_r.x - src_start_x,
+			   dst_r.y - src_start_y, &old_brush_origin);
+
+	    old_brush = SelectObject (dst->dc, brush);
+
+	    PatBlt (dst->dc, dst_r.x, dst_r.y, dst_r.width, dst_r.height, PATCOPY);
+
+	    /* Restore the old brush and pen */
+	    SetBrushOrgEx (dst->dc, old_brush_origin.x, old_brush_origin.y, NULL);
+	    SelectObject (dst->dc, old_brush);
+	    DeleteObject (brush);
+
+	    return CAIRO_STATUS_SUCCESS;
+	}
+
+	/* If we were not able to use PatBlt, then manually expand out the blit */
+
+	/* Arbitrary factor; we think that going through
+	 * fallback will be faster if we have to do more
+	 * than this amount of blits in either direction.
+	 */
+	if (dst_r.width / src_extents.width > 5 ||
+	    dst_r.height / src_extents.height > 5)
+	    goto UNSUPPORTED;
+
+	for (rendered_height = 0;
+	     rendered_height < dst_r.height;
+	     rendered_height += to_render_height)
+	{
+	    piece_y = (src_start_y + rendered_height) % src_extents.height;
+	    to_render_height = src_extents.height - piece_y;
+
+	    if (rendered_height + to_render_height > dst_r.height)
+		to_render_height = dst_r.height - rendered_height;
+
+	    for (rendered_width = 0;
+		 rendered_width < dst_r.width;
+		 rendered_width += to_render_width)
+	    {
+		piece_x = (src_start_x + rendered_width) % src_extents.width;
+		to_render_width = src_extents.width - piece_x;
+
+		if (rendered_width + to_render_width > dst_r.width)
+		    to_render_width = dst_r.width - rendered_width;
+
+		piece_src_r.x = piece_x;
+		piece_src_r.y = piece_y;
+		piece_src_r.width = to_render_width;
+		piece_src_r.height = to_render_height;
+
+		piece_dst_r.x = dst_r.x + rendered_width;
+		piece_dst_r.y = dst_r.y + rendered_height;
+		piece_dst_r.width = to_render_width;
+		piece_dst_r.height = to_render_height;
+
+		status = _cairo_win32_surface_composite_inner (src, src_image, dst,
+							       src_extents, piece_src_r, piece_dst_r,
+							       alpha, needs_alpha, needs_scale);
+		if (status != CAIRO_STATUS_SUCCESS) {
+		    /* Uh oh.  If something failed, and it's the first
+		     * piece, then we can jump to UNSUPPORTED. 
+		     * Otherwise, this is bad times, because part of the
+		     * rendering was already done. */
+		    if (rendered_width == 0 &&
+			rendered_height == 0)
+		    {
+			goto UNSUPPORTED;
+		    }
+
+		    return status;
+		}
+	    }
+	}
+    } else {
+	status = _cairo_win32_surface_composite_inner (src, src_image, dst,
+						       src_extents, src_r, dst_r,
+						       alpha, needs_alpha, needs_scale);
+    }
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	return status;
+
+UNSUPPORTED:
+    /* Fall back to image surface directly, if this is a DIB surface */
+    if (dst->image) {
+	GdiFlush();
+
+#if 0
+	return dst->image->backend->composite (op, pattern, mask_pattern,
+					       dst->image,
+					       src_x, src_y,
+					       mask_x, mask_y,
+					       dst_x, dst_y,
+					       width, height,
+					       clip_region);
+#endif
+    }
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+/* This big function tells us how to optimize operators for the
+ * case of solid destination and constant-alpha source
+ *
+ * Note: This function needs revisiting if we add support for
+ *       super-luminescent colors (a == 0, r,g,b > 0)
+ */
+static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED }
+categorize_solid_dest_operator (cairo_operator_t op,
+				unsigned short   alpha)
+{
+    enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source;
+
+    if (alpha >= 0xff00)
+	source = SOURCE_SOLID;
+    else if (alpha < 0x100)
+	source = SOURCE_TRANSPARENT;
+    else
+	source = SOURCE_OTHER;
+
+    switch (op) {
+    case CAIRO_OPERATOR_CLEAR:    /* 0                 0 */
+    case CAIRO_OPERATOR_OUT:      /* 1 - Ab            0 */
+	return DO_CLEAR;
+	break;
+
+    case CAIRO_OPERATOR_SOURCE:   /* 1                 0 */
+    case CAIRO_OPERATOR_IN:       /* Ab                0 */
+	return DO_SOURCE;
+	break;
+
+    case CAIRO_OPERATOR_OVER:     /* 1            1 - Aa */
+    case CAIRO_OPERATOR_ATOP:     /* Ab           1 - Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_SOURCE;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+
+    case CAIRO_OPERATOR_DEST_OUT: /* 0            1 - Aa */
+    case CAIRO_OPERATOR_XOR:      /* 1 - Ab       1 - Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_CLEAR;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+    	break;
+
+    case CAIRO_OPERATOR_DEST:     /* 0                 1 */
+    case CAIRO_OPERATOR_DEST_OVER:/* 1 - Ab            1 */
+    case CAIRO_OPERATOR_SATURATE: /* min(1,(1-Ab)/Aa)  1 */
+	return DO_NOTHING;
+	break;
+
+    case CAIRO_OPERATOR_DEST_IN:  /* 0                Aa */
+    case CAIRO_OPERATOR_DEST_ATOP:/* 1 - Ab           Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_NOTHING;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_CLEAR;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+
+    case CAIRO_OPERATOR_ADD:	  /* 1                1 */
+	if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+
+    case CAIRO_OPERATOR_MULTIPLY:
+    case CAIRO_OPERATOR_SCREEN:
+    case CAIRO_OPERATOR_OVERLAY:
+    case CAIRO_OPERATOR_DARKEN:
+    case CAIRO_OPERATOR_LIGHTEN:
+    case CAIRO_OPERATOR_COLOR_DODGE:
+    case CAIRO_OPERATOR_COLOR_BURN:
+    case CAIRO_OPERATOR_HARD_LIGHT:
+    case CAIRO_OPERATOR_SOFT_LIGHT:
+    case CAIRO_OPERATOR_DIFFERENCE:
+    case CAIRO_OPERATOR_EXCLUSION:
+    case CAIRO_OPERATOR_HSL_HUE:
+    case CAIRO_OPERATOR_HSL_SATURATION:
+    case CAIRO_OPERATOR_HSL_COLOR:
+    case CAIRO_OPERATOR_HSL_LUMINOSITY:
+	return DO_UNSUPPORTED;
+
+    default:
+	ASSERT_NOT_REACHED;
+	return DO_UNSUPPORTED;
+    }
+}
+
+static cairo_int_status_t
+_cairo_win32_surface_fill_rectangles (void			*abstract_surface,
+				      cairo_operator_t		op,
+				      const cairo_color_t	*color,
+				      cairo_rectangle_int_t	*rects,
+				      int			num_rects)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+    COLORREF new_color;
+    HBRUSH new_brush;
+    int i;
+
+    /* XXXperf If it's not RGB24, we need to do a little more checking
+     * to figure out when we can use GDI.  We don't have that checking
+     * anywhere at the moment, so just bail and use the fallback
+     * paths. */
+    if (surface->format != CAIRO_FORMAT_RGB24)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_win32_surface_set_clip_region (surface, NULL);
+    if (status)
+	return status;
+
+    /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
+     * surfaces with alpha.)
+     */
+    switch (categorize_solid_dest_operator (op, color->alpha_short)) {
+    case DO_CLEAR:
+	new_color = RGB (0, 0, 0);
+	break;
+    case DO_SOURCE:
+	new_color = RGB (color->red_short >> 8, color->green_short >> 8, color->blue_short >> 8);
+	break;
+    case DO_NOTHING:
+	return CAIRO_STATUS_SUCCESS;
+    case DO_UNSUPPORTED:
+    default:
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    new_brush = CreateSolidBrush (new_color);
+    if (!new_brush)
+	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
+
+    for (i = 0; i < num_rects; i++) {
+	RECT rect;
+
+	rect.left = rects[i].x;
+	rect.top = rects[i].y;
+	rect.right = rects[i].x + rects[i].width;
+	rect.bottom = rects[i].y + rects[i].height;
+
+	if (!FillRect (surface->dc, &rect, new_brush))
+	    goto FAIL;
+    }
+
+    DeleteObject (new_brush);
+
+    return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles");
+
+    DeleteObject (new_brush);
+
+    return status;
+}
+
+cairo_bool_t
+_cairo_win32_surface_get_extents (void		          *abstract_surface,
+				  cairo_rectangle_int_t   *rectangle)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+
+    *rectangle = surface->extents;
+    return TRUE;
+}
+
+static cairo_status_t
+_cairo_win32_surface_flush (void *abstract_surface)
+{
+    return _cairo_win32_surface_set_clip_region (abstract_surface, NULL);
+}
+
+#define STACK_GLYPH_SIZE 256
+
+cairo_int_status_t
+_cairo_win32_surface_show_glyphs_internal (void			 *surface,
+					   cairo_operator_t	  op,
+					   const cairo_pattern_t *source,
+					   cairo_glyph_t	 *glyphs,
+					   int			  num_glyphs,
+					   cairo_scaled_font_t	 *scaled_font,
+					   const cairo_clip_t	 *clip,
+					   cairo_bool_t		  glyph_indexing)
+{
+#if CAIRO_HAS_WIN32_FONT
+    cairo_win32_surface_t *dst = surface;
+
+    WORD glyph_buf_stack[STACK_GLYPH_SIZE];
+    WORD *glyph_buf = glyph_buf_stack;
+    int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
+    int *dxy_buf = dxy_buf_stack;
+
+    BOOL win_result = 0;
+    int i, j;
+
+    cairo_solid_pattern_t *solid_pattern;
+    COLORREF color;
+
+    cairo_matrix_t device_to_logical;
+
+    int start_x, start_y;
+    double user_x, user_y;
+    int logical_x, logical_y;
+    unsigned int glyph_index_option;
+
+    /* We can only handle win32 fonts */
+    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* We can only handle opaque solid color sources */
+    if (!_cairo_pattern_is_opaque_solid(source))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* We can only handle operator SOURCE or OVER with the destination
+     * having no alpha */
+    if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
+	(dst->format != CAIRO_FORMAT_RGB24))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* If we have a fallback mask clip set on the dst, we have
+     * to go through the fallback path, but only if we're not
+     * doing this for printing */
+    if (clip != NULL) {
+	if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) {
+	    if (! _cairo_clip_is_region (clip))
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    _cairo_win32_surface_set_clip_region (surface,
+						  _cairo_clip_get_region (clip));
+	}
+    }
+
+    solid_pattern = (cairo_solid_pattern_t *)source;
+    color = RGB(((int)solid_pattern->color.red_short) >> 8,
+		((int)solid_pattern->color.green_short) >> 8,
+		((int)solid_pattern->color.blue_short) >> 8);
+
+    cairo_win32_scaled_font_get_device_to_logical(scaled_font, &device_to_logical);
+
+    SaveDC(dst->dc);
+
+    cairo_win32_scaled_font_select_font(scaled_font, dst->dc);
+    SetTextColor(dst->dc, color);
+    SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT);
+    SetBkMode(dst->dc, TRANSPARENT);
+
+    if (num_glyphs > STACK_GLYPH_SIZE) {
+	glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
+        dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
+    }
+
+    /* It is vital that dx values for dxy_buf are calculated from the delta of
+     * _logical_ x coordinates (not user x coordinates) or else the sum of all
+     * previous dx values may start to diverge from the current glyph's x
+     * coordinate due to accumulated rounding error. As a result strings could
+     * be painted shorter or longer than expected. */
+
+    user_x = glyphs[0].x;
+    user_y = glyphs[0].y;
+
+    cairo_matrix_transform_point(&device_to_logical,
+                                 &user_x, &user_y);
+
+    logical_x = _cairo_lround (user_x);
+    logical_y = _cairo_lround (user_y);
+
+    start_x = logical_x;
+    start_y = logical_y;
+
+    for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
+        glyph_buf[i] = (WORD) glyphs[i].index;
+        if (i == num_glyphs - 1) {
+            dxy_buf[j] = 0;
+            dxy_buf[j+1] = 0;
+        } else {
+            double next_user_x = glyphs[i+1].x;
+            double next_user_y = glyphs[i+1].y;
+            int next_logical_x, next_logical_y;
+
+            cairo_matrix_transform_point(&device_to_logical,
+                                         &next_user_x, &next_user_y);
+
+            next_logical_x = _cairo_lround (next_user_x);
+            next_logical_y = _cairo_lround (next_user_y);
+
+            dxy_buf[j] = _cairo_lround (next_logical_x - logical_x);
+            dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y);
+
+            logical_x = next_logical_x;
+            logical_y = next_logical_y;
+        }
+    }
+
+    if (glyph_indexing)
+	glyph_index_option = ETO_GLYPH_INDEX;
+    else
+	glyph_index_option = 0;
+
+    win_result = ExtTextOutW(dst->dc,
+                             start_x,
+                             start_y,
+                             glyph_index_option | ETO_PDY,
+                             NULL,
+                             glyph_buf,
+                             num_glyphs,
+                             dxy_buf);
+    if (!win_result) {
+        _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
+    }
+
+    RestoreDC(dst->dc, -1);
+
+    if (glyph_buf != glyph_buf_stack) {
+	free(glyph_buf);
+        free(dxy_buf);
+    }
+    return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
+#else
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+#endif
+}
+
+#undef STACK_GLYPH_SIZE
+
+cairo_int_status_t
+_cairo_win32_surface_show_glyphs (void			*surface,
+				  cairo_operator_t	 op,
+				  const cairo_pattern_t *source,
+				  cairo_glyph_t		*glyphs,
+				  int			 num_glyphs,
+				  cairo_scaled_font_t	*scaled_font,
+				  const cairo_clip_t    *clip)
+{
+    return _cairo_win32_surface_show_glyphs_internal (surface,
+						      op,
+						      source,
+						      glyphs,
+						      num_glyphs,
+						      scaled_font,
+						      clip,
+						      TRUE);
+}
+
+
+/**
+ * cairo_win32_surface_create:
+ * @hdc: the DC to create a surface for
+ *
+ * Creates a cairo surface that targets the given DC.  The DC will be
+ * queried for its initial clip extents, and this will be used as the
+ * size of the cairo surface.  The resulting surface will always be of
+ * format %CAIRO_FORMAT_RGB24; should you need another surface format,
+ * you will need to create one through
+ * cairo_win32_surface_create_with_dib().
+ *
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_win32_surface_create (HDC hdc)
+{
+    cairo_win32_surface_t *surface;
+
+    cairo_format_t format;
+    RECT rect;
+
+    /* Assume that everything coming in as a HDC is RGB24 */
+    format = CAIRO_FORMAT_RGB24;
+
+    surface = malloc (sizeof (cairo_win32_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) {
+	free (surface);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    surface->clip_region = NULL;
+    surface->image = NULL;
+    surface->format = format;
+
+    surface->dc = hdc;
+    surface->bitmap = NULL;
+    surface->is_dib = FALSE;
+    surface->saved_dc_bitmap = NULL;
+    surface->brush = NULL;
+    surface->old_brush = NULL;
+    surface->font_subsets = NULL;
+
+    GetClipBox(hdc, &rect);
+    surface->extents.x = rect.left;
+    surface->extents.y = rect.top;
+    surface->extents.width = rect.right - rect.left;
+    surface->extents.height = rect.bottom - rect.top;
+
+    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
+
+    _cairo_surface_init (&surface->base,
+			 &cairo_win32_surface_backend,
+			 NULL, /* device */
+			 _cairo_content_from_format (format));
+
+    return &surface->base;
+}
+
+/**
+ * cairo_win32_surface_create_with_dib:
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a device-independent-bitmap surface not associated with
+ * any particular existing surface or device context. The created
+ * bitmap will be uninitialized.
+ *
+ * Return value: the newly created surface
+ *
+ * Since: 1.2
+ **/
+cairo_surface_t *
+cairo_win32_surface_create_with_dib (cairo_format_t format,
+				     int	    width,
+				     int	    height)
+{
+    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
+}
+
+/**
+ * cairo_win32_surface_create_with_ddb:
+ * @hdc: a DC compatible with the surface to create
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a device-dependent-bitmap surface not associated with
+ * any particular existing surface or device context. The created
+ * bitmap will be uninitialized.
+ *
+ * Return value: the newly created surface
+ *
+ * Since: 1.4
+ **/
+cairo_surface_t *
+cairo_win32_surface_create_with_ddb (HDC hdc,
+				     cairo_format_t format,
+				     int width,
+				     int height)
+{
+    cairo_win32_surface_t *new_surf;
+    HBITMAP ddb;
+    HDC screen_dc, ddb_dc;
+    HBITMAP saved_dc_bitmap;
+
+    if (format != CAIRO_FORMAT_RGB24)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+/* XXX handle these eventually
+	format != CAIRO_FORMAT_A8 ||
+	format != CAIRO_FORMAT_A1)
+*/
+
+    if (!hdc) {
+	screen_dc = GetDC (NULL);
+	hdc = screen_dc;
+    } else {
+	screen_dc = NULL;
+    }
+
+    ddb_dc = CreateCompatibleDC (hdc);
+    if (ddb_dc == NULL) {
+	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	goto FINISH;
+    }
+
+    ddb = CreateCompatibleBitmap (hdc, width, height);
+    if (ddb == NULL) {
+	DeleteDC (ddb_dc);
+
+	/* Note that if an app actually does hit this out of memory
+	 * condition, it's going to have lots of other issues, as
+	 * video memory is probably exhausted.  However, it can often
+	 * continue using DIBs instead of DDBs.
+	 */
+	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	goto FINISH;
+    }
+
+    saved_dc_bitmap = SelectObject (ddb_dc, ddb);
+
+    new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
+    new_surf->bitmap = ddb;
+    new_surf->saved_dc_bitmap = saved_dc_bitmap;
+    new_surf->is_dib = FALSE;
+
+FINISH:
+    if (screen_dc)
+	ReleaseDC (NULL, screen_dc);
+
+    return (cairo_surface_t*) new_surf;
+}
+
+/**
+ * _cairo_surface_is_win32:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is a win32 surface.  This will
+ * return False if this is a win32 printing surface; use
+ * _cairo_surface_is_win32_printing() to check for that.
+ *
+ * Return value: True if the surface is an win32 surface
+ **/
+int
+_cairo_surface_is_win32 (cairo_surface_t *surface)
+{
+    return surface->backend == &cairo_win32_surface_backend;
+}
+
+/**
+ * cairo_win32_surface_get_dc
+ * @surface: a #cairo_surface_t
+ *
+ * Returns the HDC associated with this surface, or %NULL if none.
+ * Also returns %NULL if the surface is not a win32 surface.
+ *
+ * A call to cairo_surface_flush() is required before using the HDC to
+ * ensure that all pending drawing operations are finished and to
+ * restore any temporary modification cairo has made to its state. A
+ * call to cairo_surface_mark_dirty() is required after the state or
+ * the content of the HDC has been modified.
+ *
+ * Return value: HDC or %NULL if no HDC available.
+ *
+ * Since: 1.2
+ **/
+HDC
+cairo_win32_surface_get_dc (cairo_surface_t *surface)
+{
+    if (_cairo_surface_is_win32 (surface))
+	return ((cairo_win32_surface_t *) target)->dc;
+
+    if (_cairo_surface_is_paginated (surface)) {
+	cairo_surface_t *target = _cairo_paginated_surface_get_target (surface);
+	if (_cairo_surface_is_win32_printing (target))
+	    return ((cairo_win32_surface_t *) target)->dc;
+    }
+
+    return NULL;
+}
+
+/**
+ * cairo_win32_surface_get_image
+ * @surface: a #cairo_surface_t
+ *
+ * Returns a #cairo_surface_t image surface that refers to the same bits
+ * as the DIB of the Win32 surface.  If the passed-in win32 surface
+ * is not a DIB surface, %NULL is returned.
+ *
+ * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t),
+ * or %NULL if the win32 surface is not a DIB.
+ *
+ * Since: 1.4
+ */
+cairo_surface_t *
+cairo_win32_surface_get_image (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_win32(surface))
+	return NULL;
+
+    return ((cairo_win32_surface_t*)surface)->image;
+}
+
+static const cairo_surface_backend_t cairo_win32_surface_backend = {
+    CAIRO_SURFACE_TYPE_WIN32,
+    _cairo_win32_surface_finish,
+
+    _cairo_default_context_create,
+
+    _cairo_win32_surface_create_similar,
+    NULL,
+    _cairo_win32_surface_map_to_image,
+    _cairo_win32_surface_unmap_image,
+
+    _cairo_surface_default_source,
+    _cairo_win32_surface_acquire_source_image,
+    _cairo_win32_surface_release_source_image,
+    NULL,  /* snapshot */
+
+    NULL, /* copy_page */
+    NULL, /* show_page */
+
+    _cairo_win32_surface_get_extents,
+    NULL, /* get_font_options */
+
+    _cairo_win32_surface_flush,
+    NULL, /* mark_dirty_rectangle */
+
+    NULL, /* paint */
+    NULL, /* mask */
+    NULL, /* stroke */
+    NULL, /* fill */
+    NULL, /* fill/stroke */
+    _cairo_win32_surface_show_glyphs,
+};
+
+/* Notes:
+ *
+ * Win32 alpha-understanding functions
+ *
+ * BitBlt - will copy full 32 bits from a 32bpp DIB to result
+ *          (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
+ *          (but not safe going RGB24->ARGB32, if RGB24 is also represented
+ *           as a 32bpp DIB, since the alpha isn't discarded!)
+ *
+ * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
+ *              it will still copy over the src alpha, because the SCA value (255) will be
+ *              multiplied by all the src components.
+ */
+
+
+cairo_int_status_t
+_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
+{
+    RECT rect;
+    int clipBoxType;
+    int gm;
+    XFORM saved_xform;
+
+    /* GetClipBox/GetClipRgn and friends interact badly with a world transform
+     * set.  GetClipBox returns values in logical (transformed) coordinates;
+     * it's unclear what GetClipRgn returns, because the region is empty in the
+     * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates.
+     * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn
+     * works in device units.
+     *
+     * So, avoid the whole mess and get rid of the world transform
+     * while we store our initial data and when we restore initial coordinates.
+     *
+     * XXX we may need to modify x/y by the ViewportOrg or WindowOrg
+     * here in GM_COMPATIBLE; unclear.
+     */
+    gm = GetGraphicsMode (hdc);
+    if (gm == GM_ADVANCED) {
+	GetWorldTransform (hdc, &saved_xform);
+	ModifyWorldTransform (hdc, NULL, MWT_IDENTITY);
+    }
+
+    clipBoxType = GetClipBox (hdc, &rect);
+    if (clipBoxType == ERROR) {
+	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
+	SetGraphicsMode (hdc, gm);
+	/* XXX: Can we make a more reasonable guess at the error cause here? */
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    surface->clip_rect.x = rect.left;
+    surface->clip_rect.y = rect.top;
+    surface->clip_rect.width = rect.right - rect.left;
+    surface->clip_rect.height = rect.bottom - rect.top;
+
+    surface->initial_clip_rgn = NULL;
+    surface->had_simple_clip = FALSE;
+
+    if (clipBoxType == COMPLEXREGION) {
+	surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
+	if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
+	    DeleteObject(surface->initial_clip_rgn);
+	    surface->initial_clip_rgn = NULL;
+	}
+    } else if (clipBoxType == SIMPLEREGION) {
+	surface->had_simple_clip = TRUE;
+    }
+
+    if (gm == GM_ADVANCED)
+	SetWorldTransform (hdc, &saved_xform);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface)
+{
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+    XFORM saved_xform;
+    int gm = GetGraphicsMode (surface->dc);
+    if (gm == GM_ADVANCED) {
+	GetWorldTransform (surface->dc, &saved_xform);
+	ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY);
+    }
+
+    /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */
+    SelectClipRgn (surface->dc, surface->initial_clip_rgn);
+
+    if (surface->had_simple_clip) {
+	/* then if we had a simple clip, intersect */
+	IntersectClipRect (surface->dc,
+			   surface->clip_rect.x,
+			   surface->clip_rect.y,
+			   surface->clip_rect.x + surface->clip_rect.width,
+			   surface->clip_rect.y + surface->clip_rect.height);
+    }
+
+    if (gm == GM_ADVANCED)
+	SetWorldTransform (surface->dc, &saved_xform);
+
+    return status;
+}
+
+void
+_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
+{
+    RGNDATA *rd;
+    unsigned int z;
+
+    if (header)
+	fprintf (stderr, "%s\n", header);
+
+    if (rgn == NULL) {
+	fprintf (stderr, " NULL\n");
+    }
+
+    z = GetRegionData(rgn, 0, NULL);
+    rd = (RGNDATA*) malloc(z);
+    z = GetRegionData(rgn, z, rd);
+
+    fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n",
+	     rd->rdh.nCount,
+	     rd->rdh.rcBound.left,
+	     rd->rdh.rcBound.top,
+	     rd->rdh.rcBound.right - rd->rdh.rcBound.left,
+	     rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
+
+    for (z = 0; z < rd->rdh.nCount; z++) {
+	RECT r = ((RECT*)rd->Buffer)[z];
+	fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n",
+		 z, r.left, r.top, r.right - r.left, r.bottom - r.top);
+    }
+
+    free(rd);
+    fflush (stderr);
+}
commit 8bea52bb0b55e2b041fbd43bc36221b5eb07b863
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 12 12:32:49 2012 +0000

    Add preliminary damage tracking
    
    This is initially based around the requirements for handling internal
    fallbacks to the image compositor and reducing the number of pixels
    required to be transferred.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 67e3537..6bcdd43 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -66,6 +66,7 @@ cairo_private = \
 	cairo-compositor-private.h \
 	cairo-contour-private.h \
 	cairo-composite-rectangles-private.h \
+	cairo-damage-private.h \
 	cairo-default-context-private.h \
 	cairo-device-private.h \
 	cairo-error-private.h \
@@ -142,6 +143,7 @@ cairo_sources = \
 	cairo-composite-rectangles.c \
 	cairo-compositor.c \
 	cairo-contour.c \
+	cairo-damage.c \
 	cairo-debug.c \
 	cairo-default-context.c \
 	cairo-device.c \
diff --git a/src/cairo-compositor.c b/src/cairo-compositor.c
index cf943e7..f6b06e5 100644
--- a/src/cairo-compositor.c
+++ b/src/cairo-compositor.c
@@ -38,6 +38,7 @@
 #include "cairoint.h"
 
 #include "cairo-compositor-private.h"
+#include "cairo-damage-private.h"
 #include "cairo-error-private.h"
 
 cairo_int_status_t
@@ -65,6 +66,10 @@ _cairo_compositor_paint (const cairo_compositor_t	*compositor,
 	compositor = compositor->delegate;
     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
 
+    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
+	surface->damage = _cairo_damage_add_rectangle (surface->damage,
+						       &extents.unbounded);
+
     _cairo_composite_rectangles_fini (&extents);
 
     return status;
@@ -96,6 +101,10 @@ _cairo_compositor_mask (const cairo_compositor_t	*compositor,
 	compositor = compositor->delegate;
     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
 
+    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
+	surface->damage = _cairo_damage_add_rectangle (surface->damage,
+						       &extents.unbounded);
+
     _cairo_composite_rectangles_fini (&extents);
 
     return status;
@@ -135,6 +144,10 @@ _cairo_compositor_stroke (const cairo_compositor_t	*compositor,
 	compositor = compositor->delegate;
     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
 
+    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
+	surface->damage = _cairo_damage_add_rectangle (surface->damage,
+						       &extents.unbounded);
+
     _cairo_composite_rectangles_fini (&extents);
 
     return status;
@@ -170,6 +183,10 @@ _cairo_compositor_fill (const cairo_compositor_t	*compositor,
 	compositor = compositor->delegate;
     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
 
+    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
+	surface->damage = _cairo_damage_add_rectangle (surface->damage,
+						       &extents.unbounded);
+
     _cairo_composite_rectangles_fini (&extents);
 
     return status;
@@ -207,6 +224,10 @@ _cairo_compositor_glyphs (const cairo_compositor_t		*compositor,
 	compositor = compositor->delegate;
     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
 
+    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
+	surface->damage = _cairo_damage_add_rectangle (surface->damage,
+						       &extents.unbounded);
+
     _cairo_composite_rectangles_fini (&extents);
 
     return status;
diff --git a/src/cairo-damage-private.h b/src/cairo-damage-private.h
new file mode 100644
index 0000000..28768fd
--- /dev/null
+++ b/src/cairo-damage-private.h
@@ -0,0 +1,82 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#ifndef CAIRO_DAMAGE_PRIVATE_H
+#define CAIRO_DAMAGE_PRIVATE_H
+
+#include "cairo-types-private.h"
+
+#include <pixman.h>
+
+CAIRO_BEGIN_DECLS
+
+struct _cairo_damage {
+    cairo_status_t status;
+    cairo_region_t *region;
+
+    int dirty, remain;
+    struct _cairo_damage_chunk {
+	struct _cairo_damage_chunk *next;
+	cairo_box_t *base;
+	int count;
+	int size;
+    } chunks, *tail;
+    cairo_box_t boxes[32];
+};
+
+cairo_private cairo_damage_t *
+_cairo_damage_create (void);
+
+cairo_private cairo_damage_t *
+_cairo_damage_add_box (cairo_damage_t *damage,
+		       const cairo_box_t *box);
+
+cairo_private cairo_damage_t *
+_cairo_damage_add_rectangle (cairo_damage_t *damage,
+			     const cairo_rectangle_int_t *rect);
+
+cairo_private cairo_damage_t *
+_cairo_damage_add_region (cairo_damage_t *damage,
+			  const cairo_region_t *region);
+
+cairo_private cairo_damage_t *
+_cairo_damage_reduce (cairo_damage_t *damage);
+
+cairo_private void
+_cairo_damage_destroy (cairo_damage_t *damage);
+
+CAIRO_END_DECLS
+
+#endif /* CAIRO_DAMAGE_PRIVATE_H */
diff --git a/src/cairo-damage.c b/src/cairo-damage.c
new file mode 100644
index 0000000..7b95c84
--- /dev/null
+++ b/src/cairo-damage.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-damage-private.h"
+#include "cairo-region-private.h"
+
+static const cairo_damage_t __cairo_damage__nil = { CAIRO_STATUS_NO_MEMORY };
+
+cairo_damage_t *
+_cairo_damage_create (void)
+{
+    cairo_damage_t *damage;
+
+    damage = malloc (sizeof (*damage));
+    if (unlikely (damage == NULL)) {
+	_cairo_error_throw(CAIRO_STATUS_NO_MEMORY);
+	return (cairo_damage_t *) &__cairo_damage__nil;
+    }
+
+    damage->status = CAIRO_STATUS_SUCCESS;
+    damage->region = NULL;
+    damage->dirty = 0;
+    damage->tail = &damage->chunks;
+    damage->chunks.base = damage->boxes;
+    damage->chunks.size = ARRAY_LENGTH(damage->boxes);
+    damage->chunks.count = 0;
+    damage->chunks.next = NULL;
+
+    damage->remain = damage->chunks.size;
+
+    return damage;
+}
+
+void
+_cairo_damage_destroy (cairo_damage_t *damage)
+{
+    struct _cairo_damage_chunk *chunk, *next;
+
+    for (chunk = damage->chunks.next; chunk != NULL; chunk = next) {
+	next = chunk->next;
+	free (chunk);
+    }
+    cairo_region_destroy (damage->region);
+    free (damage);
+}
+
+static cairo_damage_t *
+_cairo_damage_add_boxes(cairo_damage_t *damage,
+			const cairo_box_t *boxes,
+			int count)
+{
+    struct _cairo_damage_chunk *chunk;
+    int n, size;
+
+    if (damage == NULL)
+	damage = _cairo_damage_create ();
+
+    damage->dirty += count;
+
+    n = count;
+    if (n > damage->remain)
+	n = damage->remain;
+
+    memcpy (damage->tail->base + damage->tail->count, boxes, n);
+
+    count -= n;
+    damage->tail->count += n;
+    damage->remain -= n;
+
+    if (count == 0)
+	return damage;
+
+    size = 2 * damage->tail->size;
+    if (size < count)
+	size = (count + 64) & ~63;
+
+    chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size);
+    if (unlikely (chunk == NULL)) {
+	_cairo_damage_destroy (damage);
+	return (cairo_damage_t *) &__cairo_damage__nil;
+    }
+
+    chunk->next = NULL;
+    chunk->base = (cairo_box_t *) (chunk + 1);
+    chunk->size = size;
+    chunk->count = count;
+
+    damage->tail->next = chunk;
+    damage->remain = size - count;
+
+    memcpy (damage->tail->base, boxes + n, count);
+
+    return damage;
+}
+
+cairo_damage_t *
+_cairo_damage_add_box(cairo_damage_t *damage,
+		      const cairo_box_t *box)
+{
+    return _cairo_damage_add_boxes(damage, box, 1);
+}
+
+cairo_damage_t *
+_cairo_damage_add_rectangle(cairo_damage_t *damage,
+			    const cairo_rectangle_int_t *r)
+{
+    cairo_box_t box;
+
+    box.p1.x = r->x;
+    box.p1.y = r->y;
+    box.p2.x = r->x + r->width;
+    box.p2.y = r->y + r->height;
+
+    return _cairo_damage_add_boxes(damage, &box, 1);
+}
+
+cairo_damage_t *
+_cairo_damage_add_region (cairo_damage_t *damage,
+			  const cairo_region_t *region)
+{
+    cairo_box_t *boxes;
+    int nbox;
+
+    boxes = _cairo_region_get_boxes (region, &nbox);
+    return _cairo_damage_add_boxes(damage, boxes, nbox);
+}
+
+cairo_damage_t *
+_cairo_damage_reduce (cairo_damage_t *damage)
+{
+    cairo_box_t *free_boxes = NULL;
+    cairo_box_t *boxes, *b;
+    struct _cairo_damage_chunk *chunk, *last;
+
+    if (damage == NULL || !damage->dirty)
+	return damage;
+
+    if (damage->region) {
+	cairo_region_t *region;
+
+	region = damage->region;
+	damage->region = NULL;
+
+	damage = _cairo_damage_add_region (damage, region);
+	cairo_region_destroy (region);
+
+	if (unlikely (damage->status))
+	    return damage;
+    }
+
+    boxes = damage->tail->base;
+    if (damage->dirty > damage->tail->size) {
+	boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t));
+	if (unlikely (boxes == NULL)) {
+	    _cairo_damage_destroy (damage);
+	    return (cairo_damage_t *) &__cairo_damage__nil;
+	}
+
+	b = boxes;
+	last = NULL;
+    } else {
+	b = boxes + damage->tail->count;
+	last = damage->tail;
+    }
+
+    for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) {
+	memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t));
+	b += chunk->count;
+    }
+
+    damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty);
+    free (free_boxes);
+
+    if (unlikely (damage->region->status)) {
+	_cairo_damage_destroy (damage);
+	return (cairo_damage_t *) &__cairo_damage__nil;
+    }
+
+    damage->dirty = 0;
+    return damage;
+}
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 05c99b7..fede14c 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -544,7 +544,7 @@ slim_hidden_def (cairo_image_surface_create_for_data);
  *
  * Since: 1.2
  **/
-    unsigned char *
+unsigned char *
 cairo_image_surface_get_data (cairo_surface_t *surface)
 {
     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
@@ -970,10 +970,10 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
     NULL, /* show_page */
 
     _cairo_image_surface_get_extents,
-    _cairo_image_surface_get_font_options,
+    NULL,
 
     NULL, /* flush */
-    NULL, /* mark dirty */
+    NULL,
 
     _cairo_image_surface_paint,
     _cairo_image_surface_mask,
diff --git a/src/cairo-region-private.h b/src/cairo-region-private.h
index 11070ba..549e508 100644
--- a/src/cairo-region-private.h
+++ b/src/cairo-region-private.h
@@ -66,6 +66,12 @@ _cairo_region_init_rectangle (cairo_region_t *region,
 cairo_private void
 _cairo_region_fini (cairo_region_t *region);
 
+cairo_private cairo_region_t *
+_cairo_region_create_from_boxes (const cairo_box_t *boxes, int count);
+
+cairo_private cairo_box_t *
+_cairo_region_get_boxes (const cairo_region_t *region, int *nbox);
+
 CAIRO_END_DECLS
 
 #endif /* CAIRO_REGION_PRIVATE_H */
diff --git a/src/cairo-region.c b/src/cairo-region.c
index f3ccb89..a7ec50c 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -276,6 +276,38 @@ cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
 }
 slim_hidden_def (cairo_region_create_rectangles);
 
+cairo_region_t *
+_cairo_region_create_from_boxes (const cairo_box_t *boxes, int count)
+{
+    cairo_region_t *region;
+
+    region = _cairo_malloc (sizeof (cairo_region_t));
+    if (unlikely (region == NULL))
+	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    CAIRO_REFERENCE_COUNT_INIT (&region->ref_count, 1);
+    region->status = CAIRO_STATUS_SUCCESS;
+
+    if (! pixman_region32_init_rects (&region->rgn,
+				      (pixman_box32_t *)boxes, count)) {
+	free (region);
+	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    return region;
+}
+
+cairo_box_t *
+_cairo_region_get_boxes (const cairo_region_t *region, int *nbox)
+{
+    if (region->status) {
+	nbox = 0;
+	return NULL;
+    }
+
+    return (cairo_box_t *) pixman_region32_rectangles (CONST_CAST &region->rgn, nbox);
+}
+
 /**
  * cairo_region_create_rectangle:
  * @rectangle: a #cairo_rectangle_int_t
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index af24e25..657592d 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -62,6 +62,7 @@ struct _cairo_surface {
     cairo_status_t status;
     unsigned int unique_id;
     unsigned int serial;
+    cairo_damage_t *damage;
 
     unsigned finished : 1;
     unsigned is_clear : 1;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 9a4b88d..13f0909 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -40,6 +40,7 @@
 
 #include "cairo-array-private.h"
 #include "cairo-clip-private.h"
+#include "cairo-damage-private.h"
 #include "cairo-device-private.h"
 #include "cairo-error-private.h"
 #include "cairo-image-surface-private.h"
@@ -104,6 +105,7 @@ const cairo_surface_t name = {					\
     status,				/* status */		\
     0,					/* unique id */		\
     0,					/* serial */		\
+    NULL,				/* damage */		\
     FALSE,				/* finished */		\
     TRUE,				/* is_clear */		\
     FALSE,				/* has_font_options */	\
@@ -410,6 +412,7 @@ _cairo_surface_init (cairo_surface_t			*surface,
     surface->finished = FALSE;
     surface->is_clear = FALSE;
     surface->serial = 0;
+    surface->damage = NULL;
     surface->owns_device = (device != NULL);
 
     _cairo_user_data_array_init (&surface->user_data);
@@ -845,6 +848,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
     /* paranoid check that nobody took a reference whilst finishing */
     assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
 
+    if (surface->damage)
+	_cairo_damage_destroy (surface->damage);
+
     _cairo_user_data_array_fini (&surface->user_data);
     _cairo_user_data_array_fini (&surface->mime_data);
 
@@ -1424,6 +1430,17 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
     surface->is_clear = FALSE;
     surface->serial++;
 
+    if (surface->damage) {
+	cairo_box_t box;
+
+	box.p1.x = x;
+	box.p1.y = y;
+	box.p2.x = x + width;
+	box.p2.y = y + height;
+
+	surface->damage = _cairo_damage_add_box (surface->damage, &box);
+    }
+
     if (surface->backend->mark_dirty_rectangle != NULL) {
 	/* XXX: FRAGILE: We're ignoring the scaling component of
 	 * device_transform here. I don't know what the right thing to
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 2fdd0a1..3a1882b 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -66,6 +66,7 @@ typedef struct _cairo_color_stop cairo_color_stop_t;
 typedef struct _cairo_contour cairo_contour_t;
 typedef struct _cairo_contour_chain cairo_contour_chain_t;
 typedef struct _cairo_contour_iter cairo_contour_iter_t;
+typedef struct _cairo_damage cairo_damage_t;
 typedef struct _cairo_device_backend cairo_device_backend_t;
 typedef struct _cairo_font_face_backend     cairo_font_face_backend_t;
 typedef struct _cairo_gstate cairo_gstate_t;


More information about the cairo-commit mailing list