[cairo-commit] 9 commits - meson.build src/cairo-atomic-private.h src/cairo.c src/cairo-device.c src/cairo-error-private.h src/cairo.h src/cairoint.h src/cairo-misc.c src/cairo-region.c src/cairo-spans.c src/cairo-surface.c src/cairo-win32.h src/meson.build src/win32

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Mar 5 03:55:00 UTC 2022


 meson.build                              |   32 
 src/cairo-atomic-private.h               |    2 
 src/cairo-device.c                       |    1 
 src/cairo-error-private.h                |    1 
 src/cairo-misc.c                         |    2 
 src/cairo-region.c                       |    1 
 src/cairo-spans.c                        |    2 
 src/cairo-surface.c                      |    1 
 src/cairo-win32.h                        |   10 
 src/cairo.c                              |    4 
 src/cairo.h                              |    6 
 src/cairoint.h                           |   14 
 src/meson.build                          |    3 
 src/win32/cairo-dwrite-font.cpp          | 1758 +++++++++++++++++++++++++++++++
 src/win32/cairo-dwrite-private.hpp       |  266 ++++
 src/win32/cairo-win32-display-surface.c  |    2 
 src/win32/cairo-win32-font.c             |    6 
 src/win32/cairo-win32-printing-surface.c |   37 
 src/win32/cairo-win32-private.h          |   30 
 src/win32/cairo-win32-refptr.hpp         |  178 +++
 src/win32/cairo-win32-surface.c          |   13 
 src/win32/d2d1-extra.h                   |  111 +
 src/win32/dw-extra.h                     |   78 +
 23 files changed, 2546 insertions(+), 12 deletions(-)

New commits:
commit 135327c112fafa6300c140f46c7ce1a346e49515
Merge: 1fee5ac98 fa3a1bca7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Mar 5 03:54:58 2022 +0000

    Merge branch 'win32-color-fonts' into 'master'
    
    Windows color fonts
    
    See merge request cairo/cairo!244

commit fa3a1bca7d4cf04bf5002a3e0e886dffe29ccfab
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Feb 27 20:40:52 2022 +1030

    Remove the extra API from the mozilla DWrite

diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 99e2f5c63..4f257d7ed 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -69,15 +69,9 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
 cairo_public HDC
 cairo_win32_surface_get_dc (cairo_surface_t *surface);
 
-cairo_public HDC
-cairo_win32_get_dc_with_clip (cairo_t *cr);
-
 cairo_public cairo_surface_t *
 cairo_win32_surface_get_image (cairo_surface_t *surface);
 
-cairo_public cairo_status_t
-cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height);
-
 #if CAIRO_HAS_WIN32_FONT
 
 /*
@@ -111,9 +105,6 @@ cairo_public void
 cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
 					       cairo_matrix_t *device_to_logical);
 
-cairo_public BYTE
-cairo_win32_get_system_text_quality (void);
-
 #endif /* CAIRO_HAS_WIN32_FONT */
 
 #if CAIRO_HAS_DWRITE_FONT
@@ -124,18 +115,6 @@ cairo_win32_get_system_text_quality (void);
 cairo_public cairo_font_face_t *
 cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font_face);
 
-cairo_public void
-cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed);
-
-cairo_public cairo_bool_t
-cairo_dwrite_scaled_font_get_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font);
-
-cairo_public void
-cairo_dwrite_set_cleartype_params (FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
-
-cairo_public int
-cairo_dwrite_get_cleartype_rendering_mode ();
-
 #endif /* CAIRO_HAS_DWRITE_FONT */
 
 CAIRO_END_DECLS
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
index 4538309fc..486b12811 100644
--- a/src/win32/cairo-win32-private.h
+++ b/src/win32/cairo-win32-private.h
@@ -253,6 +253,9 @@ _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);
 
+cairo_public BYTE
+cairo_win32_get_system_text_quality (void);
+
 #if CAIRO_HAS_DWRITE_FONT
 
 cairo_int_status_t
diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c
index 39391650f..e53c16540 100644
--- a/src/win32/cairo-win32-surface.c
+++ b/src/win32/cairo-win32-surface.c
@@ -171,46 +171,6 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
     return NULL;
 }
 
-HDC
-cairo_win32_get_dc_with_clip (cairo_t *cr)
-{
-    cairo_surface_t *surface = cairo_get_target (cr);
-    if (cr->backend->type == CAIRO_TYPE_DEFAULT) {
-        cairo_default_context_t *c = (cairo_default_context_t *) cr;
-        cairo_clip_t *clip = _cairo_clip_copy (_cairo_gstate_get_clip (c->gstate));
-        if (_cairo_surface_is_win32 (surface)) {
-            cairo_win32_display_surface_t *winsurf = (cairo_win32_display_surface_t *) surface;
-
-            _cairo_win32_display_surface_set_clip (winsurf, clip);
-
-            _cairo_clip_destroy (clip);
-            return winsurf->win32.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)) {
-                cairo_status_t status;
-                cairo_win32_printing_surface_t *psurf = (cairo_win32_printing_surface_t *) target;
-
-                status = _cairo_surface_clipper_set_clip (&psurf->clipper, clip);
-
-                _cairo_clip_destroy (clip);
-
-                if (status)
-                    return NULL;
-
-                return psurf->win32.dc;
-            }
-        }
-        _cairo_clip_destroy (clip);
-    }
-    return NULL;
-}
-
 /**
  * _cairo_surface_is_win32:
  * @surface: a #cairo_surface_t
@@ -386,17 +346,3 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
 #endif
 }
 #undef STACK_GLYPH_SIZE
-
-cairo_status_t
-cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height)
-{
-    if (surface->type != CAIRO_SURFACE_TYPE_WIN32)
-        return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
-
-    const cairo_win32_surface_t *winsurface = (const cairo_win32_surface_t *) surface;
-
-    *width = winsurface->extents.width;
-    *height = winsurface->extents.height;
-
-    return CAIRO_STATUS_SUCCESS;
-}
commit 5635c75a2c99a901fa1410d4a297c1a1c913c0ee
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Aug 14 15:38:14 2021 +0930

    dwrite: add color font support

diff --git a/meson.build b/meson.build
index f5aab34b4..d7dd9b428 100644
--- a/meson.build
+++ b/meson.build
@@ -503,18 +503,32 @@ if host_machine.system() == 'windows'
   ]
 
   cpp_compiler = meson.get_compiler('cpp')
-  direct2d_dep = cpp_compiler.find_library('d2d1', required: false)
+  d2d_dep = cpp_compiler.find_library('d2d1', required: false)
   dwrite_dep = cpp_compiler.find_library('dwrite', required: false)
-  direct2d_header = cpp_compiler.has_header('d2d1.h')
+  d2d_header = cpp_compiler.has_header('d2d1.h')
+  d2d_3_header = cpp_compiler.has_header('d2d1_3.h')
   dwrite_header = cpp_compiler.has_header('dwrite.h')
+  dwrite_3_header = cpp_compiler.has_header('dwrite_3.h')
+  wincodec_dep = cpp_compiler.find_library('windowscodecs', required: false)
+  wincodec_header = cpp_compiler.has_header('wincodec.h')
 
-  if direct2d_dep.found() and dwrite_dep.found() and direct2d_header and dwrite_header
+  if d2d_dep.found() and dwrite_dep.found() and d2d_header and dwrite_header and wincodec_dep.found() and wincodec_header
     feature_conf.set('CAIRO_HAS_DWRITE_FONT', 1)
     built_features += [{
       'name': 'cairo-win32-dwrite-font',
       'description': 'Microsoft Windows DWrite font backend',
-      'deps': [dwrite_dep, direct2d_dep],
+      'deps': [dwrite_dep, d2d_dep, wincodec_dep],
     }]
+    deps += [dwrite_dep, d2d_dep, wincodec_dep]
+
+    if cpp_compiler.has_header('d2d1_3.h')
+      conf.set('HAVE_D2D1_3_H', 1)
+    endif
+
+    # Exclude MinGW dwrite_3.h because it has a broken definition of DWRITE_COLOR_GLYPH_RUN1.
+    if cpp_compiler.has_header('dwrite_3.h') and cpp_compiler.get_define('__MINGW32__') == ''
+      conf.set('HAVE_DWRITE_3_H', 1)
+    endif
   endif
 endif
 
diff --git a/src/cairo-device.c b/src/cairo-device.c
index 965c84c65..50e7ee484 100644
--- a/src/cairo-device.c
+++ b/src/cairo-device.c
@@ -163,6 +163,7 @@ _cairo_device_create_in_error (cairo_status_t status)
     case CAIRO_STATUS_FREETYPE_ERROR:
     case CAIRO_STATUS_WIN32_GDI_ERROR:
     case CAIRO_STATUS_TAG_ERROR:
+    case CAIRO_STATUS_DWRITE_ERROR:
     default:
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_device_t *) &_nil_device;
diff --git a/src/cairo-error-private.h b/src/cairo-error-private.h
index d8cc7c004..d84d4c23d 100644
--- a/src/cairo-error-private.h
+++ b/src/cairo-error-private.h
@@ -98,6 +98,7 @@ enum _cairo_int_status {
     CAIRO_INT_STATUS_FREETYPE_ERROR,
     CAIRO_INT_STATUS_WIN32_GDI_ERROR,
     CAIRO_INT_STATUS_TAG_ERROR,
+    CAIRO_INT_STATUS_DWRITE_ERROR,
 
     CAIRO_INT_STATUS_LAST_STATUS,
 
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 3dc1570b5..bf8a62730 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -174,6 +174,8 @@ cairo_status_to_string (cairo_status_t status)
 	return "error occurred in the Windows Graphics Device Interface";
     case CAIRO_STATUS_TAG_ERROR:
 	return "invalid tag name, attributes, or nesting";
+    case CAIRO_STATUS_DWRITE_ERROR:
+	return "Window Direct Write error";
     default:
     case CAIRO_STATUS_LAST_STATUS:
 	return "<unknown error status>";
diff --git a/src/cairo-region.c b/src/cairo-region.c
index c1d35e174..eb78cf4a8 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -111,6 +111,7 @@ _cairo_region_create_in_error (cairo_status_t status)
     case CAIRO_STATUS_FREETYPE_ERROR:
     case CAIRO_STATUS_WIN32_GDI_ERROR:
     case CAIRO_STATUS_TAG_ERROR:
+    case CAIRO_STATUS_DWRITE_ERROR:
     default:
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_region_t *) &_cairo_region_nil;
diff --git a/src/cairo-spans.c b/src/cairo-spans.c
index 59452c0ba..1b46adf4d 100644
--- a/src/cairo-spans.c
+++ b/src/cairo-spans.c
@@ -132,6 +132,7 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
     case CAIRO_STATUS_FREETYPE_ERROR:
     case CAIRO_STATUS_WIN32_GDI_ERROR:
     case CAIRO_STATUS_TAG_ERROR:
+    case CAIRO_STATUS_DWRITE_ERROR:
     default:
 	break;
     }
@@ -249,6 +250,7 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
     case CAIRO_STATUS_FREETYPE_ERROR: RETURN_NIL;
     case CAIRO_STATUS_WIN32_GDI_ERROR: RETURN_NIL;
     case CAIRO_STATUS_TAG_ERROR: RETURN_NIL;
+    case CAIRO_STATUS_DWRITE_ERROR: RETURN_NIL;
     default:
 	break;
     }
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 46f39cb20..2fc265a2c 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -3073,6 +3073,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
     case CAIRO_STATUS_PNG_ERROR:
     case CAIRO_STATUS_FREETYPE_ERROR:
     case CAIRO_STATUS_WIN32_GDI_ERROR:
+    case CAIRO_INT_STATUS_DWRITE_ERROR:
     case CAIRO_STATUS_TAG_ERROR:
     default:
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo.c b/src/cairo.c
index d141b56d2..f55429405 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -371,8 +371,8 @@ static const cairo_t _cairo_nil[] = {
     DEFINE_NIL_CONTEXT (CAIRO_STATUS_PNG_ERROR),
     DEFINE_NIL_CONTEXT (CAIRO_STATUS_FREETYPE_ERROR),
     DEFINE_NIL_CONTEXT (CAIRO_STATUS_WIN32_GDI_ERROR),
-    DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR)
-
+    DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR),
+    DEFINE_NIL_CONTEXT (CAIRO_STATUS_DWRITE_ERROR)
 };
 COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);
 
diff --git a/src/cairo.h b/src/cairo.h
index 3aaa7a022..32ffc6b3d 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -296,6 +296,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_FREETYPE_ERROR: error occurred in libfreetype (Since 1.16)
  * @CAIRO_STATUS_WIN32_GDI_ERROR: error occurred in the Windows Graphics Device Interface (Since 1.16)
  * @CAIRO_STATUS_TAG_ERROR: invalid tag name, attributes, or nesting (Since 1.16)
+ * @CAIRO_STATUS_DWRITE_ERROR: error occurred in the Windows Direct Write API (Since 1.18)
  * @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
  *   status values defined in this enumeration.  When using this value, note
  *   that the version of cairo at run-time may have additional status values
@@ -356,6 +357,7 @@ typedef enum _cairo_status {
     CAIRO_STATUS_FREETYPE_ERROR,
     CAIRO_STATUS_WIN32_GDI_ERROR,
     CAIRO_STATUS_TAG_ERROR,
+    CAIRO_STATUS_DWRITE_ERROR,
 
     CAIRO_STATUS_LAST_STATUS
 } cairo_status_t;
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 5c8d7f00c..9c21eebba 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -42,11 +42,12 @@
 #include "cairo-image-surface-private.h"
 #include "cairo-clip-private.h"
 #include "cairo-win32-refptr.hpp"
-
 #include "cairo-dwrite-private.hpp"
 #include "cairo-truetype-subset-private.h"
 #include <float.h>
 
+#include <wincodec.h>
+
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     D2D1_FACTORY_TYPE factoryType,
     REFIID iid,
@@ -72,14 +73,52 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 				       cairo_dwrite_scaled_font_t *scaled_font,
 				       const RECT &area);
 
+/**
+ * _cairo_dwrite_error:
+ * @hr HRESULT code
+ * @context: context string to display along with the error
+ *
+ * Helper function to print a human readable form a HRESULT.
+ *
+ * Return value: A cairo status code for the error code
+ **/
+cairo_int_status_t
+_cairo_dwrite_error (HRESULT hr, const char *context)
+{
+    void *lpMsgBuf;
+
+    if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			 FORMAT_MESSAGE_FROM_SYSTEM,
+			 NULL,
+			 hr,
+			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+			 (LPWSTR) &lpMsgBuf,
+			 0, NULL)) {
+	fprintf (stderr, "%s: Unknown DWrite error HRESULT=0x%08lx\n", context, (unsigned long)hr);
+    } else {
+	fprintf (stderr, "%s: %S\n", context, (wchar_t *)lpMsgBuf);
+	LocalFree (lpMsgBuf);
+    }
+    fflush (stderr);
+
+    return (cairo_int_status_t)_cairo_error (CAIRO_STATUS_DWRITE_ERROR);
+}
+
 class D2DFactory
 {
 public:
     static ID2D1Factory *Instance()
     {
 	if (!mFactoryInstance) {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
 	    D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
 		GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
 	    if (createD2DFactory) {
 		D2D1_FACTORY_OPTIONS options;
 		options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
@@ -92,6 +131,16 @@ public:
 	return mFactoryInstance;
     }
 
+    static IDWriteFactory4 *Instance4()
+    {
+	if (!mFactoryInstance4) {
+	    if (Instance()) {
+		Instance()->QueryInterface(&mFactoryInstance4);
+	    }
+	}
+	return mFactoryInstance4;
+    }
+
     static ID2D1DCRenderTarget *RenderTarget()
     {
 	if (!mRenderTarget) {
@@ -117,10 +166,33 @@ public:
 
 private:
     static ID2D1Factory *mFactoryInstance;
+    static IDWriteFactory4 *mFactoryInstance4;
     static ID2D1DCRenderTarget *mRenderTarget;
 };
 
+class WICImagingFactory
+{
+public:
+    static IWICImagingFactory *Instance()
+    {
+	if (!mFactoryInstance) {
+	    CoInitialize(NULL);
+	    CoCreateInstance(CLSID_WICImagingFactory,
+			     NULL,
+			     CLSCTX_INPROC_SERVER,
+			     IID_PPV_ARGS(&mFactoryInstance));
+	}
+	return mFactoryInstance;
+    }
+private:
+    static IWICImagingFactory *mFactoryInstance;
+};
+
+
 IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
+IDWriteFactory4 *DWriteFactory::mFactoryInstance4 = NULL;
+
+IWICImagingFactory *WICImagingFactory::mFactoryInstance = NULL;
 IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
 IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
 IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
@@ -176,6 +248,9 @@ unsigned long
 _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
 			    uint32_t			ucs4);
 
+static cairo_bool_t
+_cairo_dwrite_has_color_glyphs(void *scaled_font);
+
 const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
     CAIRO_FONT_TYPE_DWRITE,
     _cairo_dwrite_scaled_font_fini,
@@ -187,7 +262,7 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
     NULL, /* is_synthetic */
     NULL, /* index_to_glyph_name */
     NULL, /* load_type1_data */
-    NULL, /* has_color_glyphs */
+    _cairo_dwrite_has_color_glyphs
 };
 
 /* Helper conversion functions */
@@ -219,6 +294,11 @@ cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_metrics
     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
 
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font,
+						   cairo_scaled_glyph_t	      *scaled_glyph,
+						   const cairo_color_t        *foreground_color);
+
 cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_surface
     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
@@ -276,19 +356,16 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 	break;
     }
 
-    // Cannot use C++ style new since cairo deallocates this.
-    cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)_cairo_malloc(sizeof(cairo_dwrite_font_face_t));
     IDWriteFont *font;
     HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font);
     if (SUCCEEDED(hr)) {
-	hr = font->CreateFontFace(&face->dwriteface);
+	IDWriteFontFace *dwriteface;
+	hr = font->CreateFontFace(&dwriteface);
 	if (SUCCEEDED(hr)) {
-	    *font_face = (cairo_font_face_t*)face;
-	    _cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
+	    *font_face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface);
 	    return CAIRO_STATUS_SUCCESS;
 	}
     }
-    free(face);
     return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
@@ -424,13 +501,18 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
 					    const cairo_font_options_t  *options,
 					    cairo_scaled_font_t **font)
 {
+    cairo_status_t status;
     cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face);
 
     // Must do malloc and not C++ new, since Cairo frees this.
-    cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)_cairo_malloc(
+    cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_malloc(
 	sizeof(cairo_dwrite_scaled_font_t));
-    *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont);
-    _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
+    *font = reinterpret_cast<cairo_scaled_font_t*>(dwrite_font);
+    status = _cairo_scaled_font_init(&dwrite_font->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
+    if (status) {
+	free(dwrite_font);
+	return status;
+    }
 
     cairo_font_extents_t extents;
 
@@ -443,14 +525,14 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
     extents.max_x_advance = 14.0;
     extents.max_y_advance = 0.0;
 
-    dwriteFont->mat = dwriteFont->base.ctm;
-    cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix);
-    dwriteFont->mat_inverse = dwriteFont->mat;
-    cairo_matrix_invert (&dwriteFont->mat_inverse);
+    dwrite_font->mat = dwrite_font->base.ctm;
+    cairo_matrix_multiply(&dwrite_font->mat, &dwrite_font->mat, font_matrix);
+    dwrite_font->mat_inverse = dwrite_font->mat;
+    cairo_matrix_invert (&dwrite_font->mat_inverse);
 
     cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
 
-    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
+    dwrite_font->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
 
     // The following code detects the system quality at scaled_font creation time,
     // this means that if cleartype settings are changed but the scaled_fonts
@@ -462,12 +544,12 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
 	    break;
 	case ANTIALIASED_QUALITY:
 	    default_quality = CAIRO_ANTIALIAS_GRAY;
-	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+	    dwrite_font->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
 	    break;
 	case DEFAULT_QUALITY:
 	    // _get_system_quality() seems to think aliased is default!
 	    default_quality = CAIRO_ANTIALIAS_NONE;
-	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+	    dwrite_font->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
 	    break;
     }
 
@@ -478,12 +560,12 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
     }
 
     if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) {
-	dwriteFont->antialias_mode = default_quality;
+	dwrite_font->antialias_mode = default_quality;
     } else {
-	dwriteFont->antialias_mode = options->antialias;
+	dwrite_font->antialias_mode = options->antialias;
     }
 
-    dwriteFont->rendering_mode =
+    dwrite_font->rendering_mode =
         default_quality == CAIRO_ANTIALIAS_SUBPIXEL ?
             cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL : cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
 
@@ -503,7 +585,7 @@ _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
 				const cairo_color_t          *foreground_color)
 {
     cairo_dwrite_scaled_font_t *scaled_dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
-    cairo_int_status_t status;
+    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
 	status = _cairo_dwrite_scaled_font_init_glyph_metrics (scaled_dwrite_font, scaled_glyph);
@@ -511,6 +593,12 @@ _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
 	    return status;
     }
 
+    if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+	status = _cairo_dwrite_scaled_font_init_glyph_color_surface (scaled_dwrite_font, scaled_glyph, foreground_color);
+	if (status)
+	    return status;
+    }
+
     if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
 	status = _cairo_dwrite_scaled_font_init_glyph_surface (scaled_dwrite_font, scaled_glyph);
 	if (status)
@@ -647,18 +735,20 @@ public:
 	D2D1_FIGURE_BEGIN figureBegin)
     {
 	mStartPoint = startPoint;
-	_cairo_path_fixed_move_to(mCairoPath,
-				  GetFixedX(startPoint),
-				  GetFixedY(startPoint));
+	cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
+							  GetFixedX(startPoint),
+							  GetFixedY(startPoint));
+	(void)status; /* squelch warning */
     }
 
     IFACEMETHODIMP_(void) EndFigure(
 	D2D1_FIGURE_END figureEnd)
     {
 	if (figureEnd == D2D1_FIGURE_END_CLOSED) {
-	    _cairo_path_fixed_line_to(mCairoPath,
-				      GetFixedX(mStartPoint),
-				      GetFixedY(mStartPoint));
+	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
+							      GetFixedX(mStartPoint),
+							      GetFixedY(mStartPoint));
+	    (void)status; /* squelch warning */
 	}
     }
 
@@ -667,13 +757,14 @@ public:
 	UINT beziersCount)
     {
 	for (unsigned int i = 0; i < beziersCount; i++) {
-	    _cairo_path_fixed_curve_to(mCairoPath,
-				       GetFixedX(beziers[i].point1),
-				       GetFixedY(beziers[i].point1),
-				       GetFixedX(beziers[i].point2),
-				       GetFixedY(beziers[i].point2),
-				       GetFixedX(beziers[i].point3),
-				       GetFixedY(beziers[i].point3));
+	    cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
+							       GetFixedX(beziers[i].point1),
+							       GetFixedY(beziers[i].point1),
+							       GetFixedX(beziers[i].point2),
+							       GetFixedY(beziers[i].point2),
+							       GetFixedX(beziers[i].point3),
+							       GetFixedY(beziers[i].point3));
+	    (void)status; /* squelch warning */
 	}
     }
 
@@ -682,9 +773,10 @@ public:
 	UINT pointsCount)
     {
 	for (unsigned int i = 0; i < pointsCount; i++) {
-	    _cairo_path_fixed_line_to(mCairoPath,
-				      GetFixedX(points[i]),
-				      GetFixedY(points[i]));
+	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
+							      GetFixedX(points[i]),
+							      GetFixedY(points[i]));
+	    (void)status; /* squelch warning */
 	}
     }
 
@@ -697,6 +789,7 @@ cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
 					  cairo_scaled_glyph_t *scaled_glyph)
 {
+    cairo_int_status_t status;
     cairo_path_fixed_t *path;
     path = _cairo_path_fixed_create();
     GeometryRecorder recorder(path);
@@ -715,7 +808,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
 					     FALSE,
 					     FALSE,
 					     &recorder);
-    _cairo_path_fixed_close_path(path);
+    status = (cairo_int_status_t)_cairo_path_fixed_close_path(path);
 
     /* Now apply our transformation to the drawn path. */
     _cairo_path_fixed_transform(path, &scaled_font->base.ctm);
@@ -723,6 +816,227 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
     _cairo_scaled_glyph_set_path (scaled_glyph,
 				  &scaled_font->base,
 				  path);
+    return status;
+}
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font,
+						   cairo_scaled_glyph_t	      *scaled_glyph,
+						   const cairo_color_t        *foreground_color)
+{
+    int width, height;
+    double x1, y1, x2, y2;
+    cairo_glyph_t glyph;
+    cairo_bool_t uses_foreground_color = FALSE;
+
+    cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face;
+    if (!dwrite_font_face->have_color)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    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 = (int)(x2 - x1);
+    height = (int)(y2 - y1);
+
+    glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
+    glyph.x = x1;
+    glyph.y = y1;
+
+    DWRITE_GLYPH_RUN run;
+    FLOAT advance = 0;
+    UINT16 index = (UINT16)glyph.index;
+    DWRITE_GLYPH_OFFSET offset;
+    double x = -glyph.x;
+    double y = -glyph.y;
+    DWRITE_MATRIX matrix;
+    D2D1_POINT_2F origin = {0, 0};
+    IDWriteColorGlyphRunEnumerator1 *run_enumerator;
+    HRESULT hr;
+
+    /**
+     * We transform by the inverse transformation here. This will put our glyph
+     * locations in the space in which we draw. Which is later transformed by
+     * the transformation matrix that we use. This will transform the
+     * glyph positions back to where they were before when drawing, but the
+     * glyph shapes will be transformed by the transformation matrix.
+     */
+    cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
+    offset.advanceOffset = (FLOAT)x;
+    /** Y-axis is inverted */
+    offset.ascenderOffset = -(FLOAT)y;
+
+    run.fontFace = dwrite_font_face->dwriteface;
+    run.fontEmSize = 1;
+    run.glyphCount = 1;
+    run.glyphIndices = &index;
+    run.glyphAdvances = &advance;
+    run.glyphOffsets = &offset;
+    run.isSideways = FALSE;
+    run.bidiLevel = 0;
+
+    matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
+
+    /* The list of glyph image formats this renderer is prepared to support. */
+    DWRITE_GLYPH_IMAGE_FORMATS supported_formats =
+        DWRITE_GLYPH_IMAGE_FORMATS_COLR |
+        DWRITE_GLYPH_IMAGE_FORMATS_SVG |
+        DWRITE_GLYPH_IMAGE_FORMATS_PNG |
+        DWRITE_GLYPH_IMAGE_FORMATS_JPEG |
+        DWRITE_GLYPH_IMAGE_FORMATS_TIFF |
+        DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
+
+    hr = DWriteFactory::Instance4()->TranslateColorGlyphRun(
+	origin,
+	&run,
+	NULL, /* glyphRunDescription */
+	supported_formats,
+	DWRITE_MEASURING_MODE_NATURAL,
+	&matrix,
+	0,
+	&run_enumerator);
+
+    if (hr == DWRITE_E_NOCOLOR)
+	return CAIRO_INT_STATUS_UNSUPPORTED; /* No color glyphs */
+
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed");
+
+    /* We have a color glyph(s). Use Direct2D to render it to a bitmap */
+    if (!WICImagingFactory::Instance() || !D2DFactory::Instance())
+	return _cairo_dwrite_error (hr, "Instance failed");
+
+    IWICBitmap *bitmap = NULL;
+    hr = WICImagingFactory::Instance()->CreateBitmap ((UINT)width,
+						      (UINT)height,
+						      GUID_WICPixelFormat32bppPBGRA,
+						      WICBitmapCacheOnLoad,
+						      &bitmap);
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "CreateBitmap failed");
+
+    D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
+	D2D1_RENDER_TARGET_TYPE_DEFAULT,
+	D2D1::PixelFormat(
+	    DXGI_FORMAT_B8G8R8A8_UNORM,
+	    D2D1_ALPHA_MODE_PREMULTIPLIED),
+	0,
+	0,
+	D2D1_RENDER_TARGET_USAGE_NONE,
+	D2D1_FEATURE_LEVEL_DEFAULT);
+
+    ID2D1RenderTarget* rt = NULL;
+    hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt);
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed");
+
+    ID2D1DeviceContext4* dc4 = NULL;
+    if (!SUCCEEDED(rt->QueryInterface(&dc4)))
+	return _cairo_dwrite_error (hr, "QueryInterface failed");
+
+    ID2D1SolidColorBrush *foreground_color_brush;
+    if (foreground_color) {
+	dc4->CreateSolidColorBrush(
+	    D2D1::ColorF(foreground_color->red,
+			 foreground_color->green,
+			 foreground_color->blue,
+			 foreground_color->alpha), &foreground_color_brush);
+    } else {
+	dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &foreground_color_brush);
+    }
+
+    ID2D1SolidColorBrush *color_brush;
+    dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush);
+
+    dc4->SetDpi(96, 96); /* 1 unit = 1 pixel */
+    rt->SetTransform(D2D1::Matrix3x2F(matrix.m11,
+				      matrix.m12,
+				      matrix.m21,
+				      matrix.m22,
+				      matrix.dx,
+				      matrix.dy));
+
+    dc4->BeginDraw();
+    dc4->Clear(NULL); /* Transparent black */
+
+    while (true) {
+	BOOL have_run;
+	hr = run_enumerator->MoveNext(&have_run);
+	if (!SUCCEEDED(hr) || !have_run)
+	    break;
+
+	DWRITE_COLOR_GLYPH_RUN1 const* color_run;
+	if (!SUCCEEDED(run_enumerator->GetCurrentRun (&color_run)))
+	    return _cairo_dwrite_error (hr, "GetCurrentRun failed");
+
+	switch (color_run->glyphImageFormat) {
+	    case DWRITE_GLYPH_IMAGE_FORMATS_PNG:
+	    case DWRITE_GLYPH_IMAGE_FORMATS_JPEG:
+	    case DWRITE_GLYPH_IMAGE_FORMATS_TIFF:
+	    case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8:
+		/* Bitmap glyphs */
+		dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat,
+					     origin,
+					     &color_run->glyphRun,
+					     DWRITE_MEASURING_MODE_NATURAL,
+					     D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT);
+		break;
+
+	    case DWRITE_GLYPH_IMAGE_FORMATS_SVG:
+		/* SVG glyphs */
+		dc4->DrawSvgGlyphRun(origin,
+				     &color_run->glyphRun,
+				     foreground_color_brush,
+				     nullptr,
+				     0,
+				     DWRITE_MEASURING_MODE_NATURAL);
+		if (foreground_color)
+		    uses_foreground_color = TRUE;
+		break;
+	    case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
+	    case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
+	    case DWRITE_GLYPH_IMAGE_FORMATS_COLR:
+	    default:
+		/* Outline glyphs */
+		if (color_run->paletteIndex == 0xFFFF) {
+		    D2D1_COLOR_F color = foreground_color_brush->GetColor();
+		    color_brush->SetColor(&color);
+		    uses_foreground_color = TRUE;
+		} else {
+		    color_brush->SetColor(color_run->runColor);
+		}
+
+		dc4->DrawGlyphRun(origin,
+				  &color_run->glyphRun,
+				  color_run->glyphRunDescription,
+				  color_brush,
+				  DWRITE_MEASURING_MODE_NATURAL);
+	}
+    }
+
+    hr = dc4->EndDraw();
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "dc4 failed");
+
+    color_brush->Release();
+    foreground_color_brush->Release();
+
+    cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    int stride = cairo_image_surface_get_stride (image);
+    WICRect rect = { 0, 0, width, height };
+    bitmap->CopyPixels(&rect,
+		       stride,
+		       height * stride,
+		       cairo_image_surface_get_data (image));
+    cairo_surface_mark_dirty (image);
+    bitmap->Release();
+    cairo_surface_set_device_offset (image, -x1, -y1);
+    _cairo_scaled_glyph_set_color_surface (scaled_glyph,
+					   &scaled_font->base,
+					   (cairo_image_surface_t *) image,
+					   uses_foreground_color);
+
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
@@ -892,6 +1206,14 @@ _cairo_dwrite_load_truetype_table(void                 *scaled_font,
     return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+_cairo_dwrite_has_color_glyphs(void *scaled_font)
+{
+    cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+
+    return ((cairo_dwrite_font_face_t *)dwritesf->base.font_face)->have_color;
+}
+
 // WIN32 Helper Functions
 cairo_font_face_t*
 cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font_face)
@@ -905,6 +1227,16 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font_face)
 
     face->dwriteface = dwriteface;
 
+    face->have_color = false;
+    /* Ensure IDWriteFactory4 is available before enabling color fonts */
+    if (DWriteFactory::Instance4()) {
+	IDWriteFontFace2 *fontFace2;
+	if (SUCCEEDED(dwriteface->QueryInterface(&fontFace2))) {
+	    if (fontFace2->IsColorFont())
+		face->have_color = true;
+	}
+    }
+
     font_face = (cairo_font_face_t*)face;
 
     _cairo_font_face_init (&((cairo_dwrite_font_face_t*)font_face)->base, &_cairo_dwrite_font_face_backend);
@@ -1043,8 +1375,6 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
 
     rv = rt->BindDC(surface->dc, &area);
 
-    printf("Rendering to surface: %p\n", surface->dc);
-
     if (FAILED(rv)) {
 	rt->Release();
 	return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index b471e0830..07fb0e765 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -33,9 +33,28 @@
  * Contributor(s):
  *	Bas Schouten <bschouten at mozilla.com>
  */
-#include <dwrite_1.h>
+
+#include "cairoint.h"
+#include <dwrite.h>
 #include <d2d1.h>
 
+/* If either of the dwrite_2.h or d2d1_3.h headers required for color fonts
+ * is not available, include our own version containing just the functions we need.
+ */
+
+#if HAVE_DWRITE_3_H
+#include <dwrite_3.h>
+#else
+#include "dw-extra.h"
+#endif
+
+#if HAVE_D2D1_3_H
+#include <d2d1_3.h>
+#else
+#include "d2d1-extra.h"
+#endif
+
+
 // DirectWrite is not available on all platforms.
 typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
   DWRITE_FACTORY_TYPE factoryType,
@@ -66,8 +85,15 @@ public:
     static IDWriteFactory *Instance()
     {
 	if (!mFactoryInstance) {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
 	    DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
 		GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
 	    if (createDWriteFactory) {
 		HRESULT hr = createDWriteFactory(
 		    DWRITE_FACTORY_TYPE_SHARED,
@@ -79,6 +105,16 @@ public:
 	return mFactoryInstance;
     }
 
+    static IDWriteFactory4 *Instance4()
+    {
+	if (!mFactoryInstance4) {
+	    if (Instance()) {
+		Instance()->QueryInterface(&mFactoryInstance4);
+	    }
+	}
+	return mFactoryInstance4;
+    }
+
     static IDWriteFontCollection *SystemCollection()
     {
 	if (!mSystemCollection) {
@@ -163,6 +199,7 @@ private:
     static void CreateRenderingParams();
 
     static IDWriteFactory *mFactoryInstance;
+    static IDWriteFactory4 *mFactoryInstance4;
     static IDWriteFontCollection *mSystemCollection;
     static IDWriteRenderingParams *mDefaultRenderingParams;
     static IDWriteRenderingParams *mCustomClearTypeRenderingParams;
@@ -214,6 +251,7 @@ private:
 struct _cairo_dwrite_font_face {
     cairo_font_face_t base;
     IDWriteFontFace *dwriteface;
+    cairo_bool_t have_color;
 };
 typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
 
diff --git a/src/win32/d2d1-extra.h b/src/win32/d2d1-extra.h
new file mode 100644
index 000000000..16099d834
--- /dev/null
+++ b/src/win32/d2d1-extra.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* Mingw-w64 does not have d2d1_2.h and d2d2_3.h.
+ *
+ *
+ * We only need the definitions of two functions:
+ *   ID2D1DeviceContext4::DrawColorBitmapGlyphRun()
+ *   ID2D1DeviceContext4::DrawSvgGlyphRun()
+ *
+ * But we need to include all the prior functions in the same struct,
+ * and parent structs, so that the functions are in the correct position
+ * in the vtable. The parameters of the unused functions are not
+ * required as we only need a function in the struct to create a
+ * function pointer in the vtable.
+ */
+
+#ifndef D2D1_EXTRA_H
+#define D2D1_EXTRA_H
+
+#include <d2d1_1.h>
+
+interface ID2D1DeviceContext1;
+interface ID2D1DeviceContext2;
+interface ID2D1DeviceContext3;
+interface ID2D1DeviceContext4;
+interface ID2D1SvgGlyphStyle;
+
+enum D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION {
+  D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT,
+  D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DISABLE,
+  D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_FORCE_DWORD
+};
+
+DEFINE_GUID(IID_ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87);
+MIDL_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987")
+ID2D1DeviceContext1 : public ID2D1DeviceContext
+{
+  virtual void STDMETHODCALLTYPE CreateFilledGeometryRealization() = 0;
+  virtual void STDMETHODCALLTYPE CreateStrokedGeometryRealization() = 0;
+  virtual void STDMETHODCALLTYPE DrawGeometryRealization() = 0;
+};
+__CRT_UUID_DECL(ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87)
+
+DEFINE_GUID(IID_ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7);
+MIDL_INTERFACE("394ea6a3-0c34-4321-950b-6ca20f0be6c7")
+ID2D1DeviceContext2 : public ID2D1DeviceContext1
+{
+  virtual void STDMETHODCALLTYPE CreateInk() = 0;
+  virtual void STDMETHODCALLTYPE CreateInkStyle() = 0;
+  virtual void STDMETHODCALLTYPE CreateGradientMesh() = 0;
+  virtual void STDMETHODCALLTYPE CreateImageSourceFromWic() = 0;
+  virtual void STDMETHODCALLTYPE CreateLookupTable3D() = 0;
+  virtual void STDMETHODCALLTYPE CreateImageSourceFromDxgi() = 0;
+  virtual void STDMETHODCALLTYPE GetGradientMeshWorldBounds() = 0;
+  virtual void STDMETHODCALLTYPE DrawInk() = 0;
+  virtual void STDMETHODCALLTYPE DrawGradientMesh() = 0;
+  virtual void STDMETHODCALLTYPE DrawGdiMetafile() = 0;
+  virtual void STDMETHODCALLTYPE CreateTransformedImageSource() = 0;
+};
+__CRT_UUID_DECL(ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7)
+
+
+DEFINE_GUID(IID_ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00);
+MIDL_INTERFACE("235a7496-8351-414c-bcd4-6672ab2d8e00")
+ID2D1DeviceContext3 : public ID2D1DeviceContext2
+{
+  virtual void STDMETHODCALLTYPE CreateSpriteBatch() = 0;
+  virtual void STDMETHODCALLTYPE DrawSpriteBatch() = 0;
+};
+__CRT_UUID_DECL(ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00)
+
+
+DEFINE_GUID(IID_ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38);
+MIDL_INTERFACE("af671749-d241-4db8-8e41-dcc2e5c1a438")
+ID2D1SvgGlyphStyle  : public ID2D1Resource
+{
+  virtual void STDMETHODCALLTYPE SetFill() = 0;
+  virtual void STDMETHODCALLTYPE GetFill() = 0;
+  virtual void STDMETHODCALLTYPE SetStroke() = 0;
+  virtual void STDMETHODCALLTYPE GetStrokeDashesCount() = 0;
+  virtual void STDMETHODCALLTYPE GetStroke() = 0;
+};
+__CRT_UUID_DECL(ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38)
+
+
+DEFINE_GUID(IID_ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb);
+MIDL_INTERFACE("8c427831-3d90-4476-b647-c4fae349e4db")
+ID2D1DeviceContext4 : public ID2D1DeviceContext3
+{
+  virtual void STDMETHODCALLTYPE CreateSvgGlyphStyle() = 0;
+  virtual void STDMETHODCALLTYPE DrawText() = 0;
+  virtual void STDMETHODCALLTYPE DrawTextLayout() = 0;
+  virtual void STDMETHODCALLTYPE DrawColorBitmapGlyphRun(
+    DWRITE_GLYPH_IMAGE_FORMATS          glyphImageFormat,
+    D2D1_POINT_2F                       baselineOrigin,
+    const DWRITE_GLYPH_RUN              *glyphRun,
+    DWRITE_MEASURING_MODE               measuringMode,
+    D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION bitmapSnapOption) = 0;
+
+  virtual void STDMETHODCALLTYPE DrawSvgGlyphRun(
+    D2D1_POINT_2F          baselineOrigin,
+    const DWRITE_GLYPH_RUN *glyphRun,
+    ID2D1Brush             *defaultFillBrush,
+    ID2D1SvgGlyphStyle     *svgGlyphStyle,
+    UINT32                 colorPaletteIndex,
+    DWRITE_MEASURING_MODE  measuringMode) = 0;
+
+};
+__CRT_UUID_DECL(ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb)
+
+#endif
diff --git a/src/win32/dw-extra.h b/src/win32/dw-extra.h
new file mode 100644
index 000000000..f6e37e609
--- /dev/null
+++ b/src/win32/dw-extra.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* Mingw-w64 dwrite_3.h is broken
+ *
+ * We only need the definitions of one function and its dependencies.
+ *   IDWriteFactory4::TranslateColorGlyphRun
+ *
+ * But we need to include all the prior functions in the same struct,
+ * and parent structs, so that the functions are in the correct position
+ * in the vtable. The parameters of the unused functions are not
+ * required as we only need a function in the struct to create a
+ * function pointer in the vtable.
+ */
+
+#ifndef DWRITE_EXTRA_H
+#define DWRITE_EXTRA_H
+
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+
+#include <dwrite_2.h>
+
+interface IDWriteFactory3;
+interface IDWriteFactory4;
+interface IDWriteColorGlyphRunEnumerator1;
+
+DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
+
+struct DWRITE_COLOR_GLYPH_RUN1 : DWRITE_COLOR_GLYPH_RUN
+{
+    DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat;
+    DWRITE_MEASURING_MODE measuringMode;
+};
+
+
+DEFINE_GUID(IID_IDWriteColorGlyphRunEnumerator1, 0x7c5f86da, 0xc7a1, 0x4f05, 0xb8,0xe1, 0x55,0xa1,0x79,0xfe,0x5a,0x35);
+MIDL_INTERFACE("7c5f86da-c7a1-4f05-b8e1-55a179fe5a35")
+IDWriteColorGlyphRunEnumerator1 : public IDWriteColorGlyphRunEnumerator
+{
+    virtual HRESULT STDMETHODCALLTYPE GetCurrentRun(
+        const DWRITE_COLOR_GLYPH_RUN1 **run) = 0;
+
+};
+__CRT_UUID_DECL(IDWriteColorGlyphRunEnumerator1, 0x7c5f86da, 0xc7a1, 0x4f05, 0xb8,0xe1, 0x55,0xa1,0x79,0xfe,0x5a,0x35)
+
+DEFINE_GUID(IID_IDWriteFactory3, 0x9a1b41c3, 0xd3bb, 0x466a, 0x87,0xfc, 0xfe,0x67,0x55,0x6a,0x3b,0x65);
+MIDL_INTERFACE("9a1b41c3-d3bb-466a-87fc-fe67556a3b65")
+IDWriteFactory3 : public IDWriteFactory2
+{
+  virtual void STDMETHODCALLTYPE CreateGlyphRunAnalysis() = 0;
+  virtual void STDMETHODCALLTYPE CreateCustomRenderingParams() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontFaceReference() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontFaceReference2() = 0;
+  virtual void STDMETHODCALLTYPE GetSystemFontSet() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontSetBuilder() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontCollectionFromFontSet() = 0;
+  virtual void STDMETHODCALLTYPE GetSystemFontCollection() = 0;
+  virtual void STDMETHODCALLTYPE GetFontDownloadQueue() = 0;
+};
+__CRT_UUID_DECL(IDWriteFactory3, 0x9a1b41c3, 0xd3bb, 0x466a, 0x87,0xfc, 0xfe,0x67,0x55,0x6a,0x3b,0x65)
+
+DEFINE_GUID(IID_IDWriteFactory4, 0x4b0b5bd3, 0x0797, 0x4549, 0x8a,0xc5, 0xfe,0x91,0x5c,0xc5,0x38,0x56);
+MIDL_INTERFACE("4b0b5bd3-0797-4549-8ac5-fe915cc53856")
+IDWriteFactory4 : public IDWriteFactory3
+{
+  virtual HRESULT STDMETHODCALLTYPE TranslateColorGlyphRun(
+    D2D1_POINT_2F                      baselineOrigin,
+    DWRITE_GLYPH_RUN const             *glyphRun,
+    DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription,
+    DWRITE_GLYPH_IMAGE_FORMATS         desiredGlyphImageFormats,
+    DWRITE_MEASURING_MODE              measuringMode,
+    DWRITE_MATRIX const                *worldAndDpiTransform,
+    UINT32                             colorPaletteIndex,
+    IDWriteColorGlyphRunEnumerator1    **colorLayers) = 0;
+};
+__CRT_UUID_DECL(IDWriteFactory4, 0x4b0b5bd3, 0x0797, 0x4549, 0x8a,0xc5, 0xfe,0x91,0x5c,0xc5,0x38,0x56)
+
+
+#endif /* DWRITE_EXTRA_H */
commit fdf2a9b4c0b610ef5dc328c7a095ff8e6e263f05
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Aug 11 18:49:44 2021 +0930

    dwrite_font param is not used

diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 46910c017..99e2f5c63 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -122,7 +122,7 @@ cairo_win32_get_system_text_quality (void);
  * Win32 DirectWrite font support
  */
 cairo_public cairo_font_face_t *
-cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font, void *dwrite_font_face);
+cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font_face);
 
 cairo_public void
 cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed);
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index dc03c1690..5c8d7f00c 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -298,8 +298,6 @@ _cairo_dwrite_font_face_destroy (void *font_face)
     cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face);
     if (dwrite_font_face->dwriteface)
 	dwrite_font_face->dwriteface->Release();
-    if (dwrite_font_face->font)
-	dwrite_font_face->font->Release();
     return TRUE;
 }
 
@@ -896,9 +894,8 @@ _cairo_dwrite_load_truetype_table(void                 *scaled_font,
 
 // WIN32 Helper Functions
 cairo_font_face_t*
-cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrite_font_face)
+cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font_face)
 {
-    IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font);
     IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
     // Must do malloc and not C++ new, since Cairo frees this.
     cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t *)_cairo_malloc(sizeof(cairo_dwrite_font_face_t));
@@ -907,7 +904,6 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrit
     dwriteface->AddRef();
 
     face->dwriteface = dwriteface;
-    face->font = NULL;
 
     font_face = (cairo_font_face_t*)face;
 
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index 829681c2e..b471e0830 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -213,7 +213,6 @@ private:
 /* #cairo_font_face_t implementation */
 struct _cairo_dwrite_font_face {
     cairo_font_face_t base;
-    IDWriteFont *font;
     IDWriteFontFace *dwriteface;
 };
 typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
commit 7e644409eab3a495970c6d8dafdab33610e86f87
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Aug 11 07:19:54 2021 +0930

    Fix dwrite toy fonts

diff --git a/src/cairoint.h b/src/cairoint.h
index 80b695feb..cfa77ddbb 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -677,6 +677,12 @@ extern const cairo_private struct _cairo_font_face_backend _cairo_win32_font_fac
 
 #endif
 
+#if CAIRO_HAS_DWRITE_FONT
+
+extern const cairo_private struct _cairo_font_face_backend _cairo_dwrite_font_face_backend;
+
+#endif
+
 #if CAIRO_HAS_QUARTZ_FONT
 
 extern const cairo_private struct _cairo_font_face_backend _cairo_quartz_font_face_backend;
@@ -705,11 +711,17 @@ struct _cairo_surface_attributes {
 #define CAIRO_FONT_WEIGHT_DEFAULT  CAIRO_FONT_WEIGHT_NORMAL
 
 #define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial"
+#define CAIRO_DWRITE_FONT_FAMILY_DEFAULT "Arial"
 #define CAIRO_QUARTZ_FONT_FAMILY_DEFAULT  "Helvetica"
 #define CAIRO_FT_FONT_FAMILY_DEFAULT     ""
 #define CAIRO_USER_FONT_FAMILY_DEFAULT     "@cairo:"
 
-#if   CAIRO_HAS_WIN32_FONT
+#if   CAIRO_HAS_DWRITE_FONT
+
+#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_DWRITE_FONT_FAMILY_DEFAULT
+#define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_dwrite_font_face_backend
+
+#elif CAIRO_HAS_WIN32_FONT
 
 #define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT
 #define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_win32_font_face_backend
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 42b02792b..dc03c1690 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -276,17 +276,20 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 	break;
     }
 
-    cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t));
-    HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font);
+    // Cannot use C++ style new since cairo deallocates this.
+    cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)_cairo_malloc(sizeof(cairo_dwrite_font_face_t));
+    IDWriteFont *font;
+    HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font);
     if (SUCCEEDED(hr)) {
-	// Cannot use C++ style new since cairo deallocates this.
-	*font_face = (cairo_font_face_t*)face;
-	_cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
-    } else {
-	free(face);
+	hr = font->CreateFontFace(&face->dwriteface);
+	if (SUCCEEDED(hr)) {
+	    *font_face = (cairo_font_face_t*)face;
+	    _cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
+	    return CAIRO_STATUS_SUCCESS;
+	}
     }
-
-    return CAIRO_STATUS_SUCCESS;
+    free(face);
+    return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static cairo_bool_t
commit fa76ebec03ebf3252b18e0bb319ca42e00503083
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Aug 11 06:35:49 2021 +0930

    Fix some warnings and use _cairo_malloc where applicable

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 96593c2dd..42b02792b 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -426,7 +426,8 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
     cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face);
 
     // Must do malloc and not C++ new, since Cairo frees this.
-    cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t));
+    cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)_cairo_malloc(
+	sizeof(cairo_dwrite_scaled_font_t));
     *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont);
     _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
 
@@ -645,18 +646,18 @@ public:
 	D2D1_FIGURE_BEGIN figureBegin)
     {
 	mStartPoint = startPoint;
-	cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
-							  GetFixedX(startPoint),
-							  GetFixedY(startPoint));
+	_cairo_path_fixed_move_to(mCairoPath,
+				  GetFixedX(startPoint),
+				  GetFixedY(startPoint));
     }
 
     IFACEMETHODIMP_(void) EndFigure(
 	D2D1_FIGURE_END figureEnd)
     {
 	if (figureEnd == D2D1_FIGURE_END_CLOSED) {
-	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
-							      GetFixedX(mStartPoint),
-							      GetFixedY(mStartPoint));
+	    _cairo_path_fixed_line_to(mCairoPath,
+				      GetFixedX(mStartPoint),
+				      GetFixedY(mStartPoint));
 	}
     }
 
@@ -665,13 +666,13 @@ public:
 	UINT beziersCount)
     {
 	for (unsigned int i = 0; i < beziersCount; i++) {
-	    cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
-							       GetFixedX(beziers[i].point1),
-							       GetFixedY(beziers[i].point1),
-							       GetFixedX(beziers[i].point2),
-							       GetFixedY(beziers[i].point2),
-							       GetFixedX(beziers[i].point3),
-							       GetFixedY(beziers[i].point3));
+	    _cairo_path_fixed_curve_to(mCairoPath,
+				       GetFixedX(beziers[i].point1),
+				       GetFixedY(beziers[i].point1),
+				       GetFixedX(beziers[i].point2),
+				       GetFixedY(beziers[i].point2),
+				       GetFixedX(beziers[i].point3),
+				       GetFixedY(beziers[i].point3));
 	}
     }
 
@@ -680,9 +681,9 @@ public:
 	UINT pointsCount)
     {
 	for (unsigned int i = 0; i < pointsCount; i++) {
-	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
-		GetFixedX(points[i]),
-		GetFixedY(points[i]));
+	    _cairo_path_fixed_line_to(mCairoPath,
+				      GetFixedX(points[i]),
+				      GetFixedY(points[i]));
 	}
     }
 
@@ -896,7 +897,8 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrit
 {
     IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font);
     IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
-    cairo_dwrite_font_face_t *face = new cairo_dwrite_font_face_t;
+    // Must do malloc and not C++ new, since Cairo frees this.
+    cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t *)_cairo_malloc(sizeof(cairo_dwrite_font_face_t));
     cairo_font_face_t *font_face;
 
     dwriteface->AddRef();
@@ -1014,7 +1016,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
         measureMode = DWRITE_MEASURING_MODE_NATURAL;
         break;
     }
-    HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
+    rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
     BitBlt(surface->dc,
 	   area.left, area.top,
 	   area.right - area.left, area.bottom - area.top,
commit 28ce8463af9936982a5dd23ea0c7e6bfe9df2df2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 8 12:09:23 2021 +0930

    Fix check doc errors

diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index d11f9dec0..46910c017 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -124,16 +124,16 @@ cairo_win32_get_system_text_quality (void);
 cairo_public cairo_font_face_t *
 cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font, void *dwrite_font_face);
 
-void
+cairo_public void
 cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed);
 
-cairo_bool_t
+cairo_public cairo_bool_t
 cairo_dwrite_scaled_font_get_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font);
 
-void
+cairo_public void
 cairo_dwrite_set_cleartype_params (FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
 
-int
+cairo_public int
 cairo_dwrite_get_cleartype_rendering_mode ();
 
 #endif /* CAIRO_HAS_DWRITE_FONT */
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index a47111c5a..96593c2dd 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -134,7 +134,7 @@ int DWriteFactory::mRenderingMode = -1;
 ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
 ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
 
-/* Functions cairo_font_face_backend_t */
+/* Functions #cairo_font_face_backend_t */
 static cairo_status_t
 _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 					cairo_font_face_t      **font_face);
@@ -155,7 +155,7 @@ const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = {
     _cairo_dwrite_font_face_scaled_font_create
 };
 
-/* Functions cairo_scaled_font_backend_t */
+/* Functions #cairo_scaled_font_backend_t */
 
 void _cairo_dwrite_scaled_font_fini(void *scaled_font);
 
@@ -194,12 +194,13 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
 
 
 /**
+ * _cairo_dwrite_matrix_from_matrix:
  * Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row
  * vectors where cairo uses column vectors. Hence the transposition.
  *
  * \param Cairo matrix
  * \return DirectWrite matrix
- */
+ **/
 DWRITE_MATRIX
 _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
 {
@@ -213,7 +214,7 @@ _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
     return dwmat;
 }
 
-/* Helper functions for cairo_dwrite_scaled_glyph_init */
+/* Helper functions for cairo_dwrite_scaled_glyph_init() */
 cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_metrics
     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
@@ -487,7 +488,7 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
     return _cairo_scaled_font_set_metrics (*font, &extents);
 }
 
-/* Implementation cairo_dwrite_scaled_font_backend_t */
+/* Implementation #cairo_dwrite_scaled_font_backend_t */
 void
 _cairo_dwrite_scaled_font_fini(void *scaled_font)
 {
@@ -535,7 +536,7 @@ _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
     return index;
 }
 
-/* cairo_dwrite_scaled_glyph_init helper function bodies */
+/* cairo_dwrite_scaled_glyph_init() helper function bodies */
 cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
 					     cairo_scaled_glyph_t *scaled_glyph)
@@ -578,7 +579,7 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
-/**
+/*
  * Stack-based helper implementing IDWriteGeometrySink.
  * Used to determine the path of the glyphs.
  */
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index 5f2994cbc..829681c2e 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -43,7 +43,7 @@ typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
   IUnknown **factory
 );
 
-/* cairo_scaled_font_t implementation */
+/* #cairo_scaled_font_t implementation */
 struct _cairo_dwrite_scaled_font {
     cairo_scaled_font_t base;
     cairo_matrix_t mat;
@@ -210,7 +210,7 @@ private:
     UINT16              mAutoIndices[kNumAutoGlyphs];
 };
 
-/* cairo_font_face_t implementation */
+/* #cairo_font_face_t implementation */
 struct _cairo_dwrite_font_face {
     cairo_font_face_t base;
     IDWriteFont *font;
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
index e6be49b03..4538309fc 100644
--- a/src/win32/cairo-win32-private.h
+++ b/src/win32/cairo-win32-private.h
@@ -253,7 +253,7 @@ _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);
 
-#ifdef CAIRO_HAS_DWRITE_FONT
+#if CAIRO_HAS_DWRITE_FONT
 
 cairo_int_status_t
 _cairo_dwrite_show_glyphs_on_surface (void *surface,
diff --git a/src/win32/cairo-win32-refptr.hpp b/src/win32/cairo-win32-refptr.hpp
index 7dd678668..e361e4cf7 100644
--- a/src/win32/cairo-win32-refptr.hpp
+++ b/src/win32/cairo-win32-refptr.hpp
@@ -38,7 +38,7 @@
 
 template<typename T> class TemporaryRef;
 
-/**
+/*
  * RefPtr points to a refcounted thing that has AddRef and Release
  * methods to increase/decrease the refcount, respectively.  After a
  * RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
@@ -137,7 +137,7 @@ private:
     }
 };
 
-/**
+/*
  * TemporaryRef<T> represents an object that holds a temporary
  * reference to a T.  TemporaryRef objects can't be manually ref'd or
  * unref'd (being temporaries, not lvalues), so can only relinquish
commit ed36d85bf6b2723631de4366dbdfbd05f84bd8c8
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 8 11:19:28 2021 +0930

    Fix msvc c++ compile error

diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index d23192b41..a9eb38a7f 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -313,7 +313,7 @@ _cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x,
                            cairo_atomic_int_t oldv,
                            cairo_atomic_int_t newv)
 {
-    return InterlockedCompareExchange (x, newv, oldv) == oldv;
+    return InterlockedCompareExchange ((unsigned int*)x, (unsigned int)newv, (unsigned int)oldv) == oldv;
 }
 
 static cairo_always_inline void *
commit 90ca6354722879ab6af980aeb3aed2bab0b2a7af
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 8 10:44:19 2021 +0930

    Import win32 dwrite font backend from
    
    https://hg.mozilla.org/mozilla-central/file/7338d7d940913147f8a1b1e8bd2b25ab255f4373/gfx/cairo/cairo/src
    
    and add to the meson build. I've omitted the
    cairo_surface_set_subpixel_antialiasing() API and its use in quartz
    and dwrite. Not sure if that is needed.
    
    It compiles. Not tested.

diff --git a/meson.build b/meson.build
index 75a7bdfa7..f5aab34b4 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('cairo', 'c',
+project('cairo', 'c', 'cpp',
   meson_version: '>= 0.56.0',
   version: run_command(find_program('version.py'), check: true).stdout().strip(),
   default_options: ['warning_level=2'],
@@ -501,6 +501,21 @@ if host_machine.system() == 'windows'
       'deps': win32_extra_deps,
     }
   ]
+
+  cpp_compiler = meson.get_compiler('cpp')
+  direct2d_dep = cpp_compiler.find_library('d2d1', required: false)
+  dwrite_dep = cpp_compiler.find_library('dwrite', required: false)
+  direct2d_header = cpp_compiler.has_header('d2d1.h')
+  dwrite_header = cpp_compiler.has_header('dwrite.h')
+
+  if direct2d_dep.found() and dwrite_dep.found() and direct2d_header and dwrite_header
+    feature_conf.set('CAIRO_HAS_DWRITE_FONT', 1)
+    built_features += [{
+      'name': 'cairo-win32-dwrite-font',
+      'description': 'Microsoft Windows DWrite font backend',
+      'deps': [dwrite_dep, direct2d_dep],
+    }]
+  endif
 endif
 
 # GL / GLESV2 / GLESV3 are mutually exclusive
@@ -941,6 +956,7 @@ summary({
         'FreeType': feature_conf.get('CAIRO_HAS_FT_FONT', 0) == 1,
         'Fontconfig': feature_conf.get('CAIRO_HAS_FC_FONT', 0) == 1,
         'Win32': feature_conf.get('CAIRO_HAS_WIN32_FONT', 0) == 1,
+        'Win32 DWrite': feature_conf.get('CAIRO_HAS_DWRITE_FONT', 0) == 1,
         'Quartz': feature_conf.get('CAIRO_HAS_QUARTZ_FONT', 0) == 1,
         }, section: 'Font Backends', bool_yn: true)
 
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index db4cac69f..d11f9dec0 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -69,9 +69,15 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
 cairo_public HDC
 cairo_win32_surface_get_dc (cairo_surface_t *surface);
 
+cairo_public HDC
+cairo_win32_get_dc_with_clip (cairo_t *cr);
+
 cairo_public cairo_surface_t *
 cairo_win32_surface_get_image (cairo_surface_t *surface);
 
+cairo_public cairo_status_t
+cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height);
+
 #if CAIRO_HAS_WIN32_FONT
 
 /*
@@ -105,8 +111,33 @@ cairo_public void
 cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
 					       cairo_matrix_t *device_to_logical);
 
+cairo_public BYTE
+cairo_win32_get_system_text_quality (void);
+
 #endif /* CAIRO_HAS_WIN32_FONT */
 
+#if CAIRO_HAS_DWRITE_FONT
+
+/*
+ * Win32 DirectWrite font support
+ */
+cairo_public cairo_font_face_t *
+cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font, void *dwrite_font_face);
+
+void
+cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed);
+
+cairo_bool_t
+cairo_dwrite_scaled_font_get_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font);
+
+void
+cairo_dwrite_set_cleartype_params (FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
+
+int
+cairo_dwrite_get_cleartype_rendering_mode ();
+
+#endif /* CAIRO_HAS_DWRITE_FONT */
+
 CAIRO_END_DECLS
 
 #else  /* CAIRO_HAS_WIN32_SURFACE */
diff --git a/src/cairo.h b/src/cairo.h
index fb1da4146..3aaa7a022 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1545,6 +1545,7 @@ cairo_font_face_status (cairo_font_face_t *font_face);
  * @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6, in 1.2 and
  * 1.4 it was named CAIRO_FONT_TYPE_ATSUI)
  * @CAIRO_FONT_TYPE_USER: The font was create using cairo's user font api (Since: 1.8)
+ * @CAIRO_FONT_TYPE_DWRITE: The font is of type Win32 DWrite (Since: 1.18)
  *
  * #cairo_font_type_t is used to describe the type of a given font
  * face or scaled font. The font types are also known as "font
@@ -1581,7 +1582,8 @@ typedef enum _cairo_font_type {
     CAIRO_FONT_TYPE_FT,
     CAIRO_FONT_TYPE_WIN32,
     CAIRO_FONT_TYPE_QUARTZ,
-    CAIRO_FONT_TYPE_USER
+    CAIRO_FONT_TYPE_USER,
+    CAIRO_FONT_TYPE_DWRITE
 } cairo_font_type_t;
 
 cairo_public cairo_font_type_t
diff --git a/src/meson.build b/src/meson.build
index df8764649..2b37fbc0f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -177,6 +177,9 @@ cairo_feature_sources = {
   'cairo-win32-font': [
     'win32/cairo-win32-font.c',
   ],
+  'cairo-win32-dwrite-font': [
+    'win32/cairo-dwrite-font.cpp',
+  ],
   'cairo-gl': [
     'cairo-gl-composite.c',
     'cairo-gl-device.c',
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
new file mode 100644
index 000000000..a47111c5a
--- /dev/null
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -0,0 +1,1426 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2010 Mozilla Foundation
+ *
+ * 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 the Mozilla Foundation
+ *
+ * Contributor(s):
+ *	Bas Schouten <bschouten at mozilla.com>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-win32-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-surface-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-clip-private.h"
+#include "cairo-win32-refptr.hpp"
+
+#include "cairo-dwrite-private.hpp"
+#include "cairo-truetype-subset-private.h"
+#include <float.h>
+
+typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
+    D2D1_FACTORY_TYPE factoryType,
+    REFIID iid,
+    CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
+    void **factory
+);
+
+#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
+
+// Forward declarations
+cairo_int_status_t
+_dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
+				       DWRITE_MATRIX *transform,
+				       DWRITE_GLYPH_RUN *run,
+				       COLORREF color,
+				       const RECT &area);
+
+cairo_int_status_t
+_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
+				       DWRITE_MATRIX *transform,
+				       DWRITE_GLYPH_RUN *run,
+				       COLORREF color,
+				       cairo_dwrite_scaled_font_t *scaled_font,
+				       const RECT &area);
+
+class D2DFactory
+{
+public:
+    static ID2D1Factory *Instance()
+    {
+	if (!mFactoryInstance) {
+	    D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
+		GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
+	    if (createD2DFactory) {
+		D2D1_FACTORY_OPTIONS options;
+		options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
+		createD2DFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+				 __uuidof(ID2D1Factory),
+				 &options,
+				 (void**)&mFactoryInstance);
+	    }
+	}
+	return mFactoryInstance;
+    }
+
+    static ID2D1DCRenderTarget *RenderTarget()
+    {
+	if (!mRenderTarget) {
+	    if (!Instance()) {
+		return NULL;
+	    }
+	    // Create a DC render target.
+	    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
+		D2D1_RENDER_TARGET_TYPE_DEFAULT,
+		D2D1::PixelFormat(
+		    DXGI_FORMAT_B8G8R8A8_UNORM,
+		    D2D1_ALPHA_MODE_PREMULTIPLIED),
+		0,
+		0,
+		D2D1_RENDER_TARGET_USAGE_NONE,
+		D2D1_FEATURE_LEVEL_DEFAULT
+		);
+
+	    Instance()->CreateDCRenderTarget(&props, &mRenderTarget);
+	}
+	return mRenderTarget;
+    }
+
+private:
+    static ID2D1Factory *mFactoryInstance;
+    static ID2D1DCRenderTarget *mRenderTarget;
+};
+
+IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
+IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
+IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
+IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
+IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
+FLOAT DWriteFactory::mGamma = -1.0;
+FLOAT DWriteFactory::mEnhancedContrast = -1.0;
+FLOAT DWriteFactory::mClearTypeLevel = -1.0;
+int DWriteFactory::mPixelGeometry = -1;
+int DWriteFactory::mRenderingMode = -1;
+
+ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
+ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
+
+/* Functions cairo_font_face_backend_t */
+static cairo_status_t
+_cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
+					cairo_font_face_t      **font_face);
+static cairo_bool_t
+_cairo_dwrite_font_face_destroy (void *font_face);
+
+static cairo_status_t
+_cairo_dwrite_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);
+
+const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = {
+    CAIRO_FONT_TYPE_DWRITE,
+    _cairo_dwrite_font_face_create_for_toy,
+    _cairo_dwrite_font_face_destroy,
+    _cairo_dwrite_font_face_scaled_font_create
+};
+
+/* Functions cairo_scaled_font_backend_t */
+
+void _cairo_dwrite_scaled_font_fini(void *scaled_font);
+
+static cairo_warn cairo_int_status_t
+_cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
+				cairo_scaled_glyph_t	     *scaled_glyph,
+				cairo_scaled_glyph_info_t     info,
+				const cairo_color_t          *foreground_color);
+
+cairo_int_status_t
+_cairo_dwrite_load_truetype_table(void		       *scaled_font,
+				  unsigned long         tag,
+				  long                  offset,
+				  unsigned char        *buffer,
+				  unsigned long        *length);
+
+unsigned long
+_cairo_dwrite_ucs4_to_index(void			     *scaled_font,
+			    uint32_t			ucs4);
+
+const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
+    CAIRO_FONT_TYPE_DWRITE,
+    _cairo_dwrite_scaled_font_fini,
+    _cairo_dwrite_scaled_glyph_init,
+    NULL, /* text_to_glyphs */
+    _cairo_dwrite_ucs4_to_index,
+    _cairo_dwrite_load_truetype_table,
+    NULL, /* index_to_ucs4 */
+    NULL, /* is_synthetic */
+    NULL, /* index_to_glyph_name */
+    NULL, /* load_type1_data */
+    NULL, /* has_color_glyphs */
+};
+
+/* Helper conversion functions */
+
+
+/**
+ * Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row
+ * vectors where cairo uses column vectors. Hence the transposition.
+ *
+ * \param Cairo matrix
+ * \return DirectWrite matrix
+ */
+DWRITE_MATRIX
+_cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
+{
+    DWRITE_MATRIX dwmat;
+    dwmat.m11 = (FLOAT)matrix->xx;
+    dwmat.m12 = (FLOAT)matrix->yx;
+    dwmat.m21 = (FLOAT)matrix->xy;
+    dwmat.m22 = (FLOAT)matrix->yy;
+    dwmat.dx = (FLOAT)matrix->x0;
+    dwmat.dy = (FLOAT)matrix->y0;
+    return dwmat;
+}
+
+/* Helper functions for cairo_dwrite_scaled_glyph_init */
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_metrics
+    (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_surface
+    (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_path
+    (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
+
+/* implement the font backend interface */
+
+static cairo_status_t
+_cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
+					cairo_font_face_t      **font_face)
+{
+    WCHAR *face_name;
+    int face_name_len;
+
+    if (!DWriteFactory::Instance()) {
+	return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    face_name_len = MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, NULL, 0);
+    face_name = new WCHAR[face_name_len];
+    MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len);
+
+    IDWriteFontFamily *family = DWriteFactory::FindSystemFontFamily(face_name);
+    delete face_name;
+    if (!family) {
+	*font_face = (cairo_font_face_t*)&_cairo_font_face_nil;
+	return CAIRO_STATUS_FONT_TYPE_MISMATCH;
+    }
+
+    DWRITE_FONT_WEIGHT weight;
+    switch (toy_face->weight) {
+    case CAIRO_FONT_WEIGHT_BOLD:
+	weight = DWRITE_FONT_WEIGHT_BOLD;
+	break;
+    case CAIRO_FONT_WEIGHT_NORMAL:
+    default:
+	weight = DWRITE_FONT_WEIGHT_NORMAL;
+	break;
+    }
+
+    DWRITE_FONT_STYLE style;
+    switch (toy_face->slant) {
+    case CAIRO_FONT_SLANT_ITALIC:
+	style = DWRITE_FONT_STYLE_ITALIC;
+	break;
+    case CAIRO_FONT_SLANT_OBLIQUE:
+	style = DWRITE_FONT_STYLE_OBLIQUE;
+	break;
+    case CAIRO_FONT_SLANT_NORMAL:
+    default:
+	style = DWRITE_FONT_STYLE_NORMAL;
+	break;
+    }
+
+    cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t));
+    HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font);
+    if (SUCCEEDED(hr)) {
+	// Cannot use C++ style new since cairo deallocates this.
+	*font_face = (cairo_font_face_t*)face;
+	_cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
+    } else {
+	free(face);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_cairo_dwrite_font_face_destroy (void *font_face)
+{
+    cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face);
+    if (dwrite_font_face->dwriteface)
+	dwrite_font_face->dwriteface->Release();
+    if (dwrite_font_face->font)
+	dwrite_font_face->font->Release();
+    return TRUE;
+}
+
+
+static inline unsigned short
+read_short(const char *buf)
+{
+    return be16_to_cpu(*(unsigned short*)buf);
+}
+
+void
+_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
+				    int num_glyphs,
+				    cairo_dwrite_scaled_font_t *scaled_font,
+				    AutoDWriteGlyphRun *run,
+				    cairo_bool_t *transformed)
+{
+    run->allocate(num_glyphs);
+
+    UINT16 *indices = const_cast<UINT16*>(run->glyphIndices);
+    FLOAT *advances = const_cast<FLOAT*>(run->glyphAdvances);
+    DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run->glyphOffsets);
+
+    cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->base.font_face);
+
+    run->bidiLevel = 0;
+    run->fontFace = dwriteff->dwriteface;
+    run->glyphCount = num_glyphs;
+    run->isSideways = FALSE;
+
+    if (scaled_font->mat.xy == 0 && scaled_font->mat.yx == 0 &&
+	scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
+	scaled_font->mat.yy == scaled_font->base.font_matrix.yy) {
+	// Fast route, don't actually use a transform but just
+	// set the correct font size.
+	*transformed = 0;
+
+	run->fontEmSize = (FLOAT)scaled_font->base.font_matrix.yy;
+
+	for (int i = 0; i < num_glyphs; i++) {
+	    indices[i] = (WORD) glyphs[i].index;
+
+	    offsets[i].ascenderOffset = -(FLOAT)(glyphs[i].y);
+	    offsets[i].advanceOffset = (FLOAT)(glyphs[i].x);
+	    advances[i] = 0.0;
+	}
+    } else {
+	*transformed = 1;
+        // Transforming positions by the inverse matrix, then by the original
+        // matrix later may introduce small errors, especially because the
+        // D2D matrix is single-precision whereas the cairo one is double.
+        // This is a problem when glyph positions were originally at exactly
+        // half-pixel locations, which eventually round to whole pixels for
+        // GDI rendering - the errors introduced here cause them to round in
+        // unpredictable directions, instead of all rounding in a consistent
+        // way, leading to poor glyph spacing (bug 675383).
+        // To mitigate this, nudge the positions by a tiny amount to try and
+        // ensure that after the two transforms, they'll still round in a
+        // consistent direction.
+        const double EPSILON = 0.0001;
+	for (int i = 0; i < num_glyphs; i++) {
+	    indices[i] = (WORD) glyphs[i].index;
+	    double x = glyphs[i].x + EPSILON;
+	    double y = glyphs[i].y;
+	    cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
+	    // Since we will multiply by our ctm matrix later for rotation effects
+	    // and such, adjust positions by the inverse matrix now. Y-axis is
+	    // inverted! Therefor the offset is -y.
+	    offsets[i].ascenderOffset = -(FLOAT)y;
+	    offsets[i].advanceOffset = (FLOAT)x;
+	    advances[i] = 0.0;
+	}
+	// The font matrix takes care of the scaling if we have a transform,
+	// emSize should be 1.
+	run->fontEmSize = 1.0f;
+    }
+}
+
+#define GASP_TAG 0x70736167
+#define GASP_DOGRAY 0x2
+
+static cairo_bool_t
+do_grayscale(IDWriteFontFace *dwface, unsigned int ppem)
+{
+    void *tableContext;
+    char *tableData;
+    UINT32 tableSize;
+    BOOL exists;
+    dwface->TryGetFontTable(GASP_TAG, (const void**)&tableData, &tableSize, &tableContext, &exists);
+
+    if (exists) {
+	if (tableSize < 4) {
+	    dwface->ReleaseFontTable(tableContext);
+	    return true;
+	}
+	struct gaspRange {
+	    unsigned short maxPPEM; // Stored big-endian
+	    unsigned short behavior; // Stored big-endian
+	};
+	unsigned short numRanges = read_short(tableData + 2);
+	if (tableSize < (UINT)4 + numRanges * 4) {
+	    dwface->ReleaseFontTable(tableContext);
+	    return true;
+	}
+	gaspRange *ranges = (gaspRange *)(tableData + 4);
+	for (int i = 0; i < numRanges; i++) {
+	    if (be16_to_cpu(ranges[i].maxPPEM) > ppem) {
+		if (!(be16_to_cpu(ranges[i].behavior) & GASP_DOGRAY)) {
+		    dwface->ReleaseFontTable(tableContext);
+		    return false;
+		}
+		break;
+	    }
+	}
+	dwface->ReleaseFontTable(tableContext);
+    }
+    return true;
+}
+
+static cairo_status_t
+_cairo_dwrite_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)
+{
+    cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face);
+
+    // Must do malloc and not C++ new, since Cairo frees this.
+    cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t));
+    *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont);
+    _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
+
+    cairo_font_extents_t extents;
+
+    DWRITE_FONT_METRICS metrics;
+    font_face->dwriteface->GetMetrics(&metrics);
+
+    extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm;
+    extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm;
+    extents.height = (FLOAT)(metrics.ascent + metrics.descent + metrics.lineGap) / metrics.designUnitsPerEm;
+    extents.max_x_advance = 14.0;
+    extents.max_y_advance = 0.0;
+
+    dwriteFont->mat = dwriteFont->base.ctm;
+    cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix);
+    dwriteFont->mat_inverse = dwriteFont->mat;
+    cairo_matrix_invert (&dwriteFont->mat_inverse);
+
+    cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
+
+    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
+
+    // The following code detects the system quality at scaled_font creation time,
+    // this means that if cleartype settings are changed but the scaled_fonts
+    // are re-used, they might not adhere to the new system setting until re-
+    // creation.
+    switch (cairo_win32_get_system_text_quality()) {
+	case CLEARTYPE_QUALITY:
+	    default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
+	    break;
+	case ANTIALIASED_QUALITY:
+	    default_quality = CAIRO_ANTIALIAS_GRAY;
+	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+	    break;
+	case DEFAULT_QUALITY:
+	    // _get_system_quality() seems to think aliased is default!
+	    default_quality = CAIRO_ANTIALIAS_NONE;
+	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+	    break;
+    }
+
+    if (default_quality == CAIRO_ANTIALIAS_GRAY) {
+	if (!do_grayscale(font_face->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) {
+	    default_quality = CAIRO_ANTIALIAS_NONE;
+	}
+    }
+
+    if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) {
+	dwriteFont->antialias_mode = default_quality;
+    } else {
+	dwriteFont->antialias_mode = options->antialias;
+    }
+
+    dwriteFont->rendering_mode =
+        default_quality == CAIRO_ANTIALIAS_SUBPIXEL ?
+            cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL : cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
+
+    return _cairo_scaled_font_set_metrics (*font, &extents);
+}
+
+/* Implementation cairo_dwrite_scaled_font_backend_t */
+void
+_cairo_dwrite_scaled_font_fini(void *scaled_font)
+{
+}
+
+static cairo_int_status_t
+_cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
+				cairo_scaled_glyph_t	     *scaled_glyph,
+				cairo_scaled_glyph_info_t     info,
+				const cairo_color_t          *foreground_color)
+{
+    cairo_dwrite_scaled_font_t *scaled_dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+    cairo_int_status_t status;
+
+    if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
+	status = _cairo_dwrite_scaled_font_init_glyph_metrics (scaled_dwrite_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
+	status = _cairo_dwrite_scaled_font_init_glyph_surface (scaled_dwrite_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
+	status = _cairo_dwrite_scaled_font_init_glyph_path (scaled_dwrite_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+unsigned long
+_cairo_dwrite_ucs4_to_index(void			     *scaled_font,
+			    uint32_t		      ucs4)
+{
+    cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+    cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
+
+    UINT16 index;
+    face->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index);
+    return index;
+}
+
+/* cairo_dwrite_scaled_glyph_init helper function bodies */
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
+					     cairo_scaled_glyph_t *scaled_glyph)
+{
+    UINT16 charIndex = (UINT16)_cairo_scaled_glyph_index (scaled_glyph);
+    cairo_dwrite_font_face_t *font_face = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
+    cairo_text_extents_t extents;
+
+    DWRITE_GLYPH_METRICS metrics;
+    DWRITE_FONT_METRICS fontMetrics;
+    font_face->dwriteface->GetMetrics(&fontMetrics);
+    HRESULT hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
+    if (FAILED(hr)) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    // TODO: Treat swap_xy.
+    extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) /
+	fontMetrics.designUnitsPerEm;
+    extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) /
+	fontMetrics.designUnitsPerEm;
+    extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm;
+    extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm;
+    extents.y_advance = 0.0;
+    extents.y_bearing = (FLOAT)(metrics.topSideBearing - metrics.verticalOriginY) /
+	fontMetrics.designUnitsPerEm;
+
+    // We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics
+    // for the glyph outline, without accounting for hinting/gridfitting/antialiasing,
+    // and therefore it does not always cover all pixels that will actually be touched.
+    if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE &&
+	extents.width > 0 && extents.height > 0) {
+	extents.width += scaled_font->mat_inverse.xx * 2;
+	extents.x_bearing -= scaled_font->mat_inverse.xx;
+    }
+
+    _cairo_scaled_glyph_set_metrics (scaled_glyph,
+				     &scaled_font->base,
+				     &extents);
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/**
+ * Stack-based helper implementing IDWriteGeometrySink.
+ * Used to determine the path of the glyphs.
+ */
+
+class GeometryRecorder : public IDWriteGeometrySink
+{
+public:
+    GeometryRecorder(cairo_path_fixed_t *aCairoPath)
+	: mCairoPath(aCairoPath) {}
+
+    // IUnknown interface
+    IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
+    {
+	if (iid != __uuidof(IDWriteGeometrySink))
+	    return E_NOINTERFACE;
+
+	*ppObject = static_cast<IDWriteGeometrySink*>(this);
+
+	return S_OK;
+    }
+
+    IFACEMETHOD_(ULONG, AddRef)()
+    {
+	return 1;
+    }
+
+    IFACEMETHOD_(ULONG, Release)()
+    {
+	return 1;
+    }
+
+    IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode)
+    {
+	return;
+    }
+
+    STDMETHODIMP Close()
+    {
+	return S_OK;
+    }
+
+    IFACEMETHODIMP_(void) SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags)
+    {
+	return;
+    }
+
+    cairo_fixed_t GetFixedX(const D2D1_POINT_2F &point)
+    {
+	unsigned int control_word;
+	_controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
+	return _cairo_fixed_from_double(point.x);
+    }
+
+    cairo_fixed_t GetFixedY(const D2D1_POINT_2F &point)
+    {
+	unsigned int control_word;
+	_controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
+	return _cairo_fixed_from_double(point.y);
+    }
+
+    IFACEMETHODIMP_(void) BeginFigure(
+	D2D1_POINT_2F startPoint,
+	D2D1_FIGURE_BEGIN figureBegin)
+    {
+	mStartPoint = startPoint;
+	cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
+							  GetFixedX(startPoint),
+							  GetFixedY(startPoint));
+    }
+
+    IFACEMETHODIMP_(void) EndFigure(
+	D2D1_FIGURE_END figureEnd)
+    {
+	if (figureEnd == D2D1_FIGURE_END_CLOSED) {
+	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
+							      GetFixedX(mStartPoint),
+							      GetFixedY(mStartPoint));
+	}
+    }
+
+    IFACEMETHODIMP_(void) AddBeziers(
+	const D2D1_BEZIER_SEGMENT *beziers,
+	UINT beziersCount)
+    {
+	for (unsigned int i = 0; i < beziersCount; i++) {
+	    cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
+							       GetFixedX(beziers[i].point1),
+							       GetFixedY(beziers[i].point1),
+							       GetFixedX(beziers[i].point2),
+							       GetFixedY(beziers[i].point2),
+							       GetFixedX(beziers[i].point3),
+							       GetFixedY(beziers[i].point3));
+	}
+    }
+
+    IFACEMETHODIMP_(void) AddLines(
+	const D2D1_POINT_2F *points,
+	UINT pointsCount)
+    {
+	for (unsigned int i = 0; i < pointsCount; i++) {
+	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
+		GetFixedX(points[i]),
+		GetFixedY(points[i]));
+	}
+    }
+
+private:
+    cairo_path_fixed_t *mCairoPath;
+    D2D1_POINT_2F mStartPoint;
+};
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
+					  cairo_scaled_glyph_t *scaled_glyph)
+{
+    cairo_path_fixed_t *path;
+    path = _cairo_path_fixed_create();
+    GeometryRecorder recorder(path);
+
+    DWRITE_GLYPH_OFFSET offset;
+    offset.advanceOffset = 0;
+    offset.ascenderOffset = 0;
+    UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph);
+    FLOAT advance = 0.0;
+    cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
+    dwriteff->dwriteface->GetGlyphRunOutline((FLOAT)scaled_font->base.font_matrix.yy,
+					     &glyphId,
+					     &advance,
+					     &offset,
+					     1,
+					     FALSE,
+					     FALSE,
+					     &recorder);
+    _cairo_path_fixed_close_path(path);
+
+    /* Now apply our transformation to the drawn path. */
+    _cairo_path_fixed_transform(path, &scaled_font->base.ctm);
+
+    _cairo_scaled_glyph_set_path (scaled_glyph,
+				  &scaled_font->base,
+				  path);
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/* Helper function adapted from _compute_mask in cairo-win32-font.c */
+
+/* Compute an alpha-mask from a monochrome RGB24 image
+ */
+static cairo_surface_t *
+_compute_a8_mask (cairo_surface_t *surface)
+{
+    cairo_image_surface_t *glyph;
+    cairo_image_surface_t *mask;
+    int i, j;
+
+    glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL);
+    if (unlikely (glyph->base.status))
+        return &glyph->base;
+
+    /* No quality param, just use the non-ClearType path */
+
+    /* Compute an alpha-mask by using the green channel of a (presumed monochrome)
+     * RGB24 image.
+     */
+    mask = (cairo_image_surface_t *)
+        cairo_image_surface_create (CAIRO_FORMAT_A8, glyph->width, glyph->height);
+    if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
+        for (i = 0; i < glyph->height; i++) {
+            uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride);
+            uint8_t *q = (uint8_t *) (mask->data + i * mask->stride);
+
+            for (j = 0; j < glyph->width; j++)
+                *q++ = 255 - ((*p++ & 0x0000ff00) >> 8);
+        }
+    }
+
+    cairo_surface_unmap_image (surface, &glyph->base);
+    return &mask->base;
+}
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font,
+					     cairo_scaled_glyph_t	*scaled_glyph)
+{
+    cairo_int_status_t status;
+    cairo_glyph_t glyph;
+    cairo_win32_surface_t *surface;
+    cairo_t *cr;
+    cairo_surface_t *image;
+    int width, height;
+    double 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 = (int)(x2 - x1);
+    height = (int)(y2 - y1);
+
+    glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
+    glyph.x = -x1;
+    glyph.y = -y1;
+
+    DWRITE_GLYPH_RUN run;
+    FLOAT advance = 0;
+    UINT16 index = (UINT16)glyph.index;
+    DWRITE_GLYPH_OFFSET offset;
+    double x = glyph.x;
+    double y = glyph.y;
+    RECT area;
+    DWRITE_MATRIX matrix;
+
+    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_int_status_t)cairo_status (cr);
+    cairo_destroy(cr);
+    if (status)
+	goto FAIL;
+
+    /**
+     * We transform by the inverse transformation here. This will put our glyph
+     * locations in the space in which we draw. Which is later transformed by
+     * the transformation matrix that we use. This will transform the
+     * glyph positions back to where they were before when drawing, but the
+     * glyph shapes will be transformed by the transformation matrix.
+     */
+    cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
+    offset.advanceOffset = (FLOAT)x;
+    /** Y-axis is inverted */
+    offset.ascenderOffset = -(FLOAT)y;
+
+    area.top = 0;
+    area.bottom = height;
+    area.left = 0;
+    area.right = width;
+
+    run.glyphCount = 1;
+    run.glyphAdvances = &advance;
+    run.fontFace = ((cairo_dwrite_font_face_t*)scaled_font->base.font_face)->dwriteface;
+    run.fontEmSize = 1.0f;
+    run.bidiLevel = 0;
+    run.glyphIndices = &index;
+    run.isSideways = FALSE;
+    run.glyphOffsets = &offset;
+
+    matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
+
+    status = _dwrite_draw_glyphs_to_gdi_surface_gdi (surface, &matrix, &run,
+            RGB(0,0,0), scaled_font, area);
+    if (status)
+	goto FAIL;
+
+    GdiFlush();
+
+    image = _compute_a8_mask (&surface->base);
+    status = (cairo_int_status_t)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;
+}
+
+cairo_int_status_t
+_cairo_dwrite_load_truetype_table(void                 *scaled_font,
+				  unsigned long         tag,
+				  long                  offset,
+				  unsigned char        *buffer,
+				  unsigned long        *length)
+{
+    cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+    cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
+
+    const void *data;
+    UINT32 size;
+    void *tableContext;
+    BOOL exists;
+    face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
+				      &data,
+				      &size,
+				      &tableContext,
+				      &exists);
+
+    if (!exists) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (buffer && *length && (UINT32)offset < size) {
+        size = MIN(size - (UINT32)offset, *length);
+        memcpy(buffer, (const char*)data + offset, size);
+    }
+    *length = size;
+
+    if (tableContext) {
+	face->dwriteface->ReleaseFontTable(tableContext);
+    }
+    return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
+}
+
+// WIN32 Helper Functions
+cairo_font_face_t*
+cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrite_font_face)
+{
+    IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font);
+    IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
+    cairo_dwrite_font_face_t *face = new cairo_dwrite_font_face_t;
+    cairo_font_face_t *font_face;
+
+    dwriteface->AddRef();
+
+    face->dwriteface = dwriteface;
+    face->font = NULL;
+
+    font_face = (cairo_font_face_t*)face;
+
+    _cairo_font_face_init (&((cairo_dwrite_font_face_t*)font_face)->base, &_cairo_dwrite_font_face_backend);
+
+    return font_face;
+}
+
+void
+cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force)
+{
+    cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
+    if (force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL) {
+        font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC;
+    } else if (!force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) {
+        font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL;
+    }
+}
+
+cairo_bool_t
+cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font)
+{
+    cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
+    return font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC;
+}
+
+void
+cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
+				  int geometry, int mode)
+{
+    DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode);
+}
+
+int
+cairo_dwrite_get_cleartype_rendering_mode()
+{
+    return DWriteFactory::GetClearTypeRenderingMode();
+}
+
+cairo_int_status_t
+_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
+				       DWRITE_MATRIX *transform,
+				       DWRITE_GLYPH_RUN *run,
+				       COLORREF color,
+				       cairo_dwrite_scaled_font_t *scaled_font,
+				       const RECT &area)
+{
+    IDWriteGdiInterop *gdiInterop;
+    DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
+    IDWriteBitmapRenderTarget *rt;
+    HRESULT rv;
+
+    cairo_dwrite_scaled_font_t::TextRenderingState renderingState =
+      scaled_font->rendering_mode;
+
+    rv = gdiInterop->CreateBitmapRenderTarget(surface->dc,
+					      area.right - area.left,
+					      area.bottom - area.top,
+					      &rt);
+
+    if (FAILED(rv)) {
+	if (rv == E_OUTOFMEMORY) {
+	    return (cairo_int_status_t)CAIRO_STATUS_NO_MEMORY;
+	} else {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+    }
+
+    if ((renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL ||
+         renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC)
+        /* && !surface->base.permit_subpixel_antialiasing */ ) {
+      renderingState = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
+      IDWriteBitmapRenderTarget1* rt1;
+      rv = rt->QueryInterface(&rt1);
+
+      if (SUCCEEDED(rv) && rt1) {
+        rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
+        rt1->Release();
+      }
+    }
+
+    IDWriteRenderingParams *params =
+        DWriteFactory::RenderingParams(renderingState);
+
+    /**
+     * We set the number of pixels per DIP to 1.0. This is because we always want
+     * to draw in device pixels, and not device independent pixels. On high DPI
+     * systems this value will be higher than 1.0 and automatically upscale
+     * fonts, we don't want this since we do our own upscaling for various reasons.
+     */
+    rt->SetPixelsPerDip(1.0);
+
+    if (transform) {
+	rt->SetCurrentTransform(transform);
+    }
+    BitBlt(rt->GetMemoryDC(),
+	   0, 0,
+	   area.right - area.left, area.bottom - area.top,
+	   surface->dc,
+	   area.left, area.top,
+	   SRCCOPY | NOMIRRORBITMAP);
+    DWRITE_MEASURING_MODE measureMode;
+    switch (renderingState) {
+    case cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC:
+    case cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE:
+        measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+        break;
+    default:
+        measureMode = DWRITE_MEASURING_MODE_NATURAL;
+        break;
+    }
+    HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
+    BitBlt(surface->dc,
+	   area.left, area.top,
+	   area.right - area.left, area.bottom - area.top,
+	   rt->GetMemoryDC(),
+	   0, 0,
+	   SRCCOPY | NOMIRRORBITMAP);
+    params->Release();
+    rt->Release();
+    gdiInterop->Release();
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
+				       DWRITE_MATRIX *transform,
+				       DWRITE_GLYPH_RUN *run,
+				       COLORREF color,
+				       const RECT &area)
+{
+    HRESULT rv;
+
+    ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
+
+    // XXX don't we need to set RenderingParams on this RenderTarget?
+
+    rv = rt->BindDC(surface->dc, &area);
+
+    printf("Rendering to surface: %p\n", surface->dc);
+
+    if (FAILED(rv)) {
+	rt->Release();
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    // D2D uses 0x00RRGGBB not 0x00BBGGRR like COLORREF.
+    color = (color & 0xFF) << 16 |
+	(color & 0xFF00) |
+	(color & 0xFF0000) >> 16;
+    ID2D1SolidColorBrush *brush;
+    rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
+
+    if (FAILED(rv)) {
+	rt->Release();
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (transform) {
+	rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
+					  transform->m12,
+					  transform->m21,
+					  transform->m22,
+					  transform->dx,
+					  transform->dy));
+    }
+    rt->BeginDraw();
+    rt->DrawGlyphRun(D2D1::Point2F(0, 0), run, brush);
+    rt->EndDraw();
+    if (transform) {
+	rt->SetTransform(D2D1::Matrix3x2F::Identity());
+    }
+    brush->Release();
+    if (FAILED(rv)) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/* Surface helper function */
+cairo_int_status_t
+_cairo_dwrite_show_glyphs_on_surface(void			*surface,
+				    cairo_operator_t	 op,
+				    const cairo_pattern_t	*source,
+				    cairo_glyph_t		*glyphs,
+				    int			 num_glyphs,
+				    cairo_scaled_font_t	*scaled_font,
+				    cairo_clip_t	*clip)
+{
+    // TODO: Check font & surface for types.
+    cairo_dwrite_scaled_font_t *dwritesf = reinterpret_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+    cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->font_face);
+    cairo_win32_surface_t *dst = reinterpret_cast<cairo_win32_surface_t*>(surface);
+    cairo_int_status_t status;
+    /* We can only handle dwrite fonts */
+    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE)
+	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)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* If we have a fallback mask clip set on the dst, we have
+     * to go through the fallback path */
+    if (!_cairo_surface_is_win32_printing (&dst->base)) {
+        if (clip != NULL)
+            _cairo_win32_display_surface_set_clip (to_win32_display_surface (dst), clip);
+        else
+            _cairo_win32_display_surface_unset_clip (to_win32_display_surface (dst));
+    }
+
+    /* 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. */
+
+    AutoDWriteGlyphRun run;
+    run.allocate(num_glyphs);
+
+    UINT16 *indices = const_cast<UINT16*>(run.glyphIndices);
+    FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances);
+    DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
+
+    BOOL transform = FALSE;
+    /* Needed to calculate bounding box for efficient blitting */
+    INT32 smallestX = INT_MAX;
+    INT32 largestX = 0;
+    INT32 smallestY = INT_MAX;
+    INT32 largestY = 0;
+    for (int i = 0; i < num_glyphs; i++) {
+	if (glyphs[i].x < smallestX) {
+	    smallestX = (INT32)glyphs[i].x;
+	}
+	if (glyphs[i].x > largestX) {
+	    largestX = (INT32)glyphs[i].x;
+	}
+	if (glyphs[i].y < smallestY) {
+	    smallestY = (INT32)glyphs[i].y;
+	}
+	if (glyphs[i].y > largestY) {
+	    largestY = (INT32)glyphs[i].y;
+	}
+    }
+    /**
+     * Here we try to get a rough estimate of the area that this glyph run will
+     * cover on the surface. Since we use GDI interop to draw we will be copying
+     * data around the size of the area of the surface that we map. We will want
+     * to map an area as small as possible to prevent large surfaces to be
+     * copied around. We take the X/Y-size of the font as margin on the left/top
+     * twice the X/Y-size of the font as margin on the right/bottom.
+     * This should always cover the entire area where the glyphs are.
+     */
+    RECT fontArea;
+    fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx);
+    fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2);
+    fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy);
+    fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2);
+    if (fontArea.left < 0)
+	fontArea.left = 0;
+    if (fontArea.top < 0)
+	fontArea.top = 0;
+    if (fontArea.bottom > dst->extents.height) {
+	fontArea.bottom = dst->extents.height;
+    }
+    if (fontArea.right > dst->extents.width) {
+	fontArea.right = dst->extents.width;
+    }
+    if (fontArea.right <= fontArea.left ||
+	fontArea.bottom <= fontArea.top) {
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+    if (fontArea.right > dst->extents.width) {
+	fontArea.right = dst->extents.width;
+    }
+    if (fontArea.bottom > dst->extents.height) {
+	fontArea.bottom = dst->extents.height;
+    }
+
+    run.bidiLevel = 0;
+    run.fontFace = dwriteff->dwriteface;
+    run.isSideways = FALSE;
+    if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
+	dwritesf->mat.xx == scaled_font->font_matrix.xx &&
+	dwritesf->mat.yy == scaled_font->font_matrix.yy) {
+
+	for (int i = 0; i < num_glyphs; i++) {
+	    indices[i] = (WORD) glyphs[i].index;
+	    // Since we will multiply by our ctm matrix later for rotation effects
+	    // and such, adjust positions by the inverse matrix now.
+	    offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y);
+	    offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
+	    advances[i] = 0.0;
+	}
+	run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
+    } else {
+	transform = TRUE;
+        // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs
+        const double EPSILON = 0.0001;
+	for (int i = 0; i < num_glyphs; i++) {
+	    indices[i] = (WORD) glyphs[i].index;
+	    double x = glyphs[i].x - fontArea.left + EPSILON;
+	    double y = glyphs[i].y - fontArea.top;
+	    cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
+	    /**
+	     * Since we will multiply by our ctm matrix later for rotation effects
+	     * and such, adjust positions by the inverse matrix now. The Y-axis
+	     * is inverted so the offset becomes negative.
+	     */
+	    offsets[i].ascenderOffset = -(FLOAT)y;
+	    offsets[i].advanceOffset = (FLOAT)x;
+	    advances[i] = 0.0;
+	}
+	run.fontEmSize = 1.0f;
+    }
+
+    cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source;
+    COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8,
+		((int)solid_pattern->color.green_short) >> 8,
+		((int)solid_pattern->color.blue_short) >> 8);
+
+    DWRITE_MATRIX matrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
+
+    DWRITE_MATRIX *mat;
+    if (transform) {
+	mat = &matrix;
+    } else {
+	mat = NULL;
+    }
+
+    RECT area;
+    area.left = dst->extents.x;
+    area.top = dst->extents.y;
+    area.right = area.left + dst->extents.width;
+    area.bottom = area.top + dst->extents.height;
+
+#ifdef CAIRO_TRY_D2D_TO_GDI
+    status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst,
+						    mat,
+						    &run,
+						    color,
+						    fontArea);
+
+    if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) {
+#endif
+	status = _dwrite_draw_glyphs_to_gdi_surface_gdi(dst,
+							mat,
+							&run,
+							color,
+							dwritesf,
+							fontArea);
+
+#ifdef CAIRO_TRY_D2D_TO_GDI
+    }
+#endif
+
+    return status;
+}
+
+#define ENHANCED_CONTRAST_REGISTRY_KEY \
+    HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
+
+void
+DWriteFactory::CreateRenderingParams()
+{
+    if (!Instance()) {
+	return;
+    }
+
+    Instance()->CreateRenderingParams(&mDefaultRenderingParams);
+
+    // For EnhancedContrast, we override the default if the user has not set it
+    // in the registry (by using the ClearType Tuner).
+    FLOAT contrast;
+    if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) {
+	contrast = mEnhancedContrast;
+    } else {
+	HKEY hKey;
+	if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
+			  0, KEY_READ, &hKey) == ERROR_SUCCESS)
+	{
+	    contrast = mDefaultRenderingParams->GetEnhancedContrast();
+	    RegCloseKey(hKey);
+	} else {
+	    contrast = 1.0;
+	}
+    }
+
+    // For parameters that have not been explicitly set via the SetRenderingParams API,
+    // we copy values from default params (or our overridden value for contrast)
+    FLOAT gamma =
+        mGamma >= 1.0 && mGamma <= 2.2 ?
+            mGamma : mDefaultRenderingParams->GetGamma();
+    FLOAT clearTypeLevel =
+        mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ?
+            mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel();
+    DWRITE_PIXEL_GEOMETRY pixelGeometry =
+        mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
+            (DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry();
+    DWRITE_RENDERING_MODE renderingMode =
+        mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
+            (DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode();
+    Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
+	pixelGeometry, renderingMode,
+	&mCustomClearTypeRenderingParams);
+    Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
+        pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
+        &mForceGDIClassicRenderingParams);
+}
+
+static cairo_bool_t
+_name_tables_match (cairo_scaled_font_t *font1,
+                    cairo_scaled_font_t *font2)
+{
+    unsigned long size1;
+    unsigned long size2;
+    cairo_int_status_t status1;
+    cairo_int_status_t status2;
+    unsigned char *buffer1;
+    unsigned char *buffer2;
+    cairo_bool_t result = false;
+
+    if (!font1->backend || !font2->backend ||
+        !font1->backend->load_truetype_table ||
+        !font2->backend->load_truetype_table)
+        return false;
+
+    status1 = font1->backend->load_truetype_table (font1,
+                                                   TT_TAG_name, 0, NULL, &size1);
+    status2 = font2->backend->load_truetype_table (font2,
+                                                   TT_TAG_name, 0, NULL, &size2);
+    if (status1 || status2)
+        return false;
+    if (size1 != size2)
+        return false;
+
+    buffer1 = (unsigned char*)malloc (size1);
+    buffer2 = (unsigned char*)malloc (size2);
+
+    if (buffer1 && buffer2) {
+        status1 = font1->backend->load_truetype_table (font1,
+                                                       TT_TAG_name, 0, buffer1, &size1);
+        status2 = font2->backend->load_truetype_table (font2,
+                                                       TT_TAG_name, 0, buffer2, &size2);
+        if (!status1 && !status2) {
+            result = memcmp (buffer1, buffer2, size1) == 0;
+        }
+    }
+
+    free (buffer1);
+    free (buffer2);
+    return result;
+}
+
+// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
+// of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
+// paths or blitting glyph bitmaps.
+cairo_int_status_t
+_cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
+                                                    cairo_scaled_font_t **new_font)
+{
+    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE) {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    cairo_font_face_t *face = cairo_scaled_font_get_font_face (scaled_font);
+    cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t*>(face);
+
+    RefPtr<IDWriteGdiInterop> gdiInterop;
+    DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
+    if (!gdiInterop) {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    LOGFONTW logfont;
+    if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    // DW must have been using an outline font, so we want GDI to use the same,
+    // even if there's also a bitmap face available
+    logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+
+    cairo_font_face_t *win32_face = cairo_win32_font_face_create_for_logfontw (&logfont);
+    if (!win32_face) {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    cairo_matrix_t font_matrix;
+    cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
+
+    cairo_matrix_t ctm;
+    cairo_scaled_font_get_ctm (scaled_font, &ctm);
+
+    cairo_font_options_t options;
+    cairo_scaled_font_get_font_options (scaled_font, &options);
+
+    cairo_scaled_font_t *font = cairo_scaled_font_create (win32_face,
+			                                  &font_matrix,
+			                                  &ctm,
+			                                  &options);
+    cairo_font_face_destroy (win32_face);
+
+    if (!font) {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (!_name_tables_match (font, scaled_font)) {
+        // If the font name tables aren't equal, then GDI may have failed to
+        // find the right font and substituted a different font.
+        cairo_scaled_font_destroy (font);
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    *new_font = font;
+    return CAIRO_INT_STATUS_SUCCESS;
+}
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
new file mode 100644
index 000000000..5f2994cbc
--- /dev/null
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -0,0 +1,229 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2010 Mozilla Foundation
+ *
+ * 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 the Mozilla Foundation
+ *
+ * Contributor(s):
+ *	Bas Schouten <bschouten at mozilla.com>
+ */
+#include <dwrite_1.h>
+#include <d2d1.h>
+
+// DirectWrite is not available on all platforms.
+typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
+  DWRITE_FACTORY_TYPE factoryType,
+  REFIID iid,
+  IUnknown **factory
+);
+
+/* cairo_scaled_font_t implementation */
+struct _cairo_dwrite_scaled_font {
+    cairo_scaled_font_t base;
+    cairo_matrix_t mat;
+    cairo_matrix_t mat_inverse;
+    cairo_antialias_t antialias_mode;
+    DWRITE_MEASURING_MODE measuring_mode;
+    enum TextRenderingState {
+        TEXT_RENDERING_UNINITIALIZED,
+        TEXT_RENDERING_NO_CLEARTYPE,
+        TEXT_RENDERING_NORMAL,
+        TEXT_RENDERING_GDI_CLASSIC
+    };
+    TextRenderingState rendering_mode;
+};
+typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
+
+class DWriteFactory
+{
+public:
+    static IDWriteFactory *Instance()
+    {
+	if (!mFactoryInstance) {
+	    DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
+		GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
+	    if (createDWriteFactory) {
+		HRESULT hr = createDWriteFactory(
+		    DWRITE_FACTORY_TYPE_SHARED,
+		    __uuidof(IDWriteFactory),
+		    reinterpret_cast<IUnknown**>(&mFactoryInstance));
+		assert(SUCCEEDED(hr));
+	    }
+	}
+	return mFactoryInstance;
+    }
+
+    static IDWriteFontCollection *SystemCollection()
+    {
+	if (!mSystemCollection) {
+	    if (Instance()) {
+		HRESULT hr = Instance()->GetSystemFontCollection(&mSystemCollection);
+		assert(SUCCEEDED(hr));
+	    }
+	}
+	return mSystemCollection;
+    }
+
+    static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName)
+    {
+	UINT32 idx;
+	BOOL found;
+	if (!SystemCollection()) {
+	    return NULL;
+	}
+	SystemCollection()->FindFamilyName(aFamilyName, &idx, &found);
+	if (!found) {
+	    return NULL;
+	}
+
+	IDWriteFontFamily *family;
+	SystemCollection()->GetFontFamily(idx, &family);
+	return family;
+    }
+
+    static IDWriteRenderingParams *RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode)
+    {
+	if (!mDefaultRenderingParams ||
+            !mForceGDIClassicRenderingParams ||
+            !mCustomClearTypeRenderingParams)
+        {
+	    CreateRenderingParams();
+	}
+	IDWriteRenderingParams *params;
+        if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE) {
+            params = mDefaultRenderingParams;
+        } else if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC && mRenderingMode < 0) {
+            params = mForceGDIClassicRenderingParams;
+        } else {
+            params = mCustomClearTypeRenderingParams;
+        }
+	if (params) {
+	    params->AddRef();
+	}
+	return params;
+    }
+
+    static void SetRenderingParams(FLOAT aGamma,
+				   FLOAT aEnhancedContrast,
+				   FLOAT aClearTypeLevel,
+				   int aPixelGeometry,
+				   int aRenderingMode)
+    {
+	mGamma = aGamma;
+	mEnhancedContrast = aEnhancedContrast;
+	mClearTypeLevel = aClearTypeLevel;
+        mPixelGeometry = aPixelGeometry;
+        mRenderingMode = aRenderingMode;
+	// discard any current RenderingParams objects
+	if (mCustomClearTypeRenderingParams) {
+	    mCustomClearTypeRenderingParams->Release();
+	    mCustomClearTypeRenderingParams = NULL;
+	}
+	if (mForceGDIClassicRenderingParams) {
+	    mForceGDIClassicRenderingParams->Release();
+	    mForceGDIClassicRenderingParams = NULL;
+	}
+	if (mDefaultRenderingParams) {
+	    mDefaultRenderingParams->Release();
+	    mDefaultRenderingParams = NULL;
+	}
+    }
+
+    static int GetClearTypeRenderingMode() {
+        return mRenderingMode;
+    }
+
+private:
+    static void CreateRenderingParams();
+
+    static IDWriteFactory *mFactoryInstance;
+    static IDWriteFontCollection *mSystemCollection;
+    static IDWriteRenderingParams *mDefaultRenderingParams;
+    static IDWriteRenderingParams *mCustomClearTypeRenderingParams;
+    static IDWriteRenderingParams *mForceGDIClassicRenderingParams;
+    static FLOAT mGamma;
+    static FLOAT mEnhancedContrast;
+    static FLOAT mClearTypeLevel;
+    static int mPixelGeometry;
+    static int mRenderingMode;
+};
+
+class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN
+{
+    static const int kNumAutoGlyphs = 256;
+
+public:
+    AutoDWriteGlyphRun() {
+        glyphCount = 0;
+    }
+
+    ~AutoDWriteGlyphRun() {
+        if (glyphCount > kNumAutoGlyphs) {
+            delete[] glyphIndices;
+            delete[] glyphAdvances;
+            delete[] glyphOffsets;
+        }
+    }
+
+    void allocate(int aNumGlyphs) {
+        glyphCount = aNumGlyphs;
+        if (aNumGlyphs <= kNumAutoGlyphs) {
+            glyphIndices = &mAutoIndices[0];
+            glyphAdvances = &mAutoAdvances[0];
+            glyphOffsets = &mAutoOffsets[0];
+        } else {
+            glyphIndices = new UINT16[aNumGlyphs];
+            glyphAdvances = new FLOAT[aNumGlyphs];
+            glyphOffsets = new DWRITE_GLYPH_OFFSET[aNumGlyphs];
+        }
+    }
+
+private:
+    DWRITE_GLYPH_OFFSET mAutoOffsets[kNumAutoGlyphs];
+    FLOAT               mAutoAdvances[kNumAutoGlyphs];
+    UINT16              mAutoIndices[kNumAutoGlyphs];
+};
+
+/* cairo_font_face_t implementation */
+struct _cairo_dwrite_font_face {
+    cairo_font_face_t base;
+    IDWriteFont *font;
+    IDWriteFontFace *dwriteface;
+};
+typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
+
+DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix);
+
+// This will initialize a DWrite glyph run from cairo glyphs and a scaled_font.
+void
+_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
+				    int num_glyphs,
+				    cairo_dwrite_scaled_font_t *scaled_font,
+				    AutoDWriteGlyphRun *run,
+				    cairo_bool_t *transformed);
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
index a3f224c58..841725474 100644
--- a/src/win32/cairo-win32-display-surface.c
+++ b/src/win32/cairo-win32-display-surface.c
@@ -168,7 +168,7 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
     case CAIRO_FORMAT_RGB30:
     case CAIRO_FORMAT_RGB96F:
     case CAIRO_FORMAT_RGBA128F:
-    ASSERT_NOT_REACHED;
+	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
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index ae375ae06..4cd0a1203 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -286,8 +286,8 @@ _have_cleartype_quality (void)
 	     version_info.dwMinorVersion >= 1));	/* XP or newer */
 }
 
-static BYTE
-_get_system_quality (void)
+BYTE
+cairo_win32_get_system_text_quality (void)
 {
     BOOL font_smoothing;
     UINT smoothing_type;
@@ -354,7 +354,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
      *      here is the hint_metrics options.
      */
     if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
-	f->quality = _get_system_quality ();
+	f->quality = cairo_win32_get_system_text_quality ();
     else {
 	switch (options->antialias) {
 	case CAIRO_ANTIALIAS_NONE:
diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c
index d01210745..602a4f3f0 100644
--- a/src/win32/cairo-win32-printing-surface.c
+++ b/src/win32/cairo-win32-printing-surface.c
@@ -251,7 +251,7 @@ _cairo_win32_printing_surface_acquire_image_pattern (
     case CAIRO_PATTERN_TYPE_MESH:
     default:
 	ASSERT_NOT_REACHED;
-	break;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     _cairo_pattern_init_for_surface (image_pattern, &image->base);
@@ -1818,6 +1818,7 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
     cairo_solid_pattern_t clear;
     cairo_composite_rectangles_t extents;
     cairo_bool_t overlap;
+    cairo_scaled_font_t *local_scaled_font = NULL;
 
     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
 							  &surface->win32.base,
@@ -1861,6 +1862,13 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 	}
 #endif
 
+#if CAIRO_HAS_DWRITE_FONT
+        if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) {
+            status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded);
+            goto cleanup_composite;
+        }
+#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
@@ -1901,6 +1909,23 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 	source = opaque;
     }
 
+#if CAIRO_HAS_DWRITE_FONT
+    /* For a printer, the dwrite path is not desirable as it goes through the
+     * bitmap-blitting GDI interop route. Better to create a win32 (GDI) font
+     * so that ExtTextOut can be used, giving the printer driver the chance
+     * to do the right thing with the text.
+     */
+    if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) {
+        status = _cairo_dwrite_scaled_font_create_win32_scaled_font (scaled_font, &local_scaled_font);
+        if (status == CAIRO_STATUS_SUCCESS) {
+            scaled_font = local_scaled_font;
+        } else {
+            /* Reset status; we'll fall back to drawing glyphs as paths */
+            status = CAIRO_STATUS_SUCCESS;
+        }
+    }
+#endif
+
 #if CAIRO_HAS_WIN32_FONT
     if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
 	source->type == CAIRO_PATTERN_TYPE_SOLID)
@@ -1960,6 +1985,10 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 
 cleanup_composite:
     _cairo_composite_rectangles_fini (&extents);
+
+    if (local_scaled_font)
+        cairo_scaled_font_destroy (local_scaled_font);
+
     return status;
 }
 
@@ -2193,6 +2222,12 @@ cairo_win32_printing_surface_create (HDC hdc)
     return paginated;
 }
 
+cairo_bool_t
+_cairo_surface_is_win32_printing (const cairo_surface_t *surface)
+{
+    return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING;
+}
+
 static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
     _cairo_win32_printing_surface_finish,
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
index 85f88a9e8..e6be49b03 100644
--- a/src/win32/cairo-win32-private.h
+++ b/src/win32/cairo-win32-private.h
@@ -53,6 +53,8 @@
 
 #define WIN32_FONT_LOGICAL_SCALE 32
 
+CAIRO_BEGIN_DECLS
+
 /* Surface DC flag values */
 enum {
     /* If this is a surface created for printing or not */
@@ -199,6 +201,12 @@ _cairo_win32_gdi_compositor_get (void);
 cairo_status_t
 _cairo_win32_print_gdi_error (const char *context);
 
+cairo_bool_t
+_cairo_surface_is_win32 (const cairo_surface_t *surface);
+
+cairo_bool_t
+_cairo_surface_is_win32_printing (const cairo_surface_t *surface);
+
 cairo_private void
 _cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface);
 
@@ -245,4 +253,23 @@ _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);
 
+#ifdef CAIRO_HAS_DWRITE_FONT
+
+cairo_int_status_t
+_cairo_dwrite_show_glyphs_on_surface (void *surface,
+                                      cairo_operator_t op,
+                                      const cairo_pattern_t *source,
+                                      cairo_glyph_t *glyphs,
+                                      int num_glyphs,
+                                      cairo_scaled_font_t *scaled_font,
+                                      cairo_clip_t *clip);
+
+cairo_int_status_t
+_cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
+                                                    cairo_scaled_font_t **new_font);
+
+#endif /* CAIRO_HAS_DWRITE_FONT */
+
+CAIRO_END_DECLS
+
 #endif /* CAIRO_WIN32_PRIVATE_H */
diff --git a/src/win32/cairo-win32-refptr.hpp b/src/win32/cairo-win32-refptr.hpp
new file mode 100644
index 000000000..7dd678668
--- /dev/null
+++ b/src/win32/cairo-win32-refptr.hpp
@@ -0,0 +1,178 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright <A9> 2010 Mozilla Foundation
+ *
+ * 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 the Mozilla Foundation
+ *
+ * Contributor(s):
+ *     Bas Schouten <bschouten at mozilla.com>
+ */
+#ifndef CAIRO_WIN32_REFPTR_H
+#define CAIRO_WIN32_REFPTR_H
+
+template<typename T> class TemporaryRef;
+
+/**
+ * RefPtr points to a refcounted thing that has AddRef and Release
+ * methods to increase/decrease the refcount, respectively.  After a
+ * RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
+ * as if it were a T*.
+ *
+ * A RefPtr can forget its underlying T*, which results in the T*
+ * being wrapped in a temporary object until the T* is either
+ * re-adopted from or released by the temporary.
+ */
+template<typename T>
+class RefPtr
+{
+    // To allow them to use unref()
+    friend class TemporaryRef<T>;
+
+    struct dontRef {};
+
+public:
+    RefPtr() : ptr(0) { }
+    RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
+    RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
+    RefPtr(T* t) : ptr(ref(t)) {}
+
+    template<typename U>
+    RefPtr(const RefPtr<U>& o) : ptr(ref(o.get())) {}
+
+    ~RefPtr() { unref(ptr); }
+
+    RefPtr& operator=(const RefPtr& o) {
+        assign(ref(o.ptr));
+        return *this;
+    }
+    RefPtr& operator=(const TemporaryRef<T>& o) {
+        assign(o.drop());
+        return *this;
+    }
+    RefPtr& operator=(T* t) {
+        assign(ref(t));
+        return *this;
+    }
+
+    template<typename U>
+    RefPtr& operator=(const RefPtr<U>& o) {
+        assign(ref(o.get()));
+        return *this;
+    }
+
+    TemporaryRef<T> forget() {
+        T* tmp = ptr;
+        ptr = 0;
+        return TemporaryRef<T>(tmp, dontRef());
+    }
+
+    T* get() const { return ptr; }
+    operator T*() const { return ptr; }
+    T* operator->() const { return ptr; }
+    T& operator*() const { return *ptr; }
+    template<typename U>
+    operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
+
+    /**
+     * WARNING for ease of use, passing a reference will release/clear out ptr!
+     * We null out the ptr before returning its address so people passing byref
+     * as input will most likely get functions returning errors rather than accessing
+     * freed memory. Further more accessing it after this point if it hasn't
+     * been set will produce a null pointer dereference.
+     */
+    T** operator&()
+    {
+       if (ptr) {
+           ptr->Release();
+           ptr = NULL;
+       }
+       return &ptr;
+    }
+
+private:
+    void assign(T* t) {
+        unref(ptr);
+        ptr = t;
+    }
+
+    T* ptr;
+
+    static inline T* ref(T* t) {
+        if (t) {
+            t->AddRef();
+        }
+        return t;
+    }
+
+    static inline void unref(T* t) {
+        if (t) {
+            t->Release();
+        }
+    }
+};
+
+/**
+ * TemporaryRef<T> represents an object that holds a temporary
+ * reference to a T.  TemporaryRef objects can't be manually ref'd or
+ * unref'd (being temporaries, not lvalues), so can only relinquish
+ * references to other objects, or unref on destruction.
+ */
+template<typename T>
+class TemporaryRef
+{
+    // To allow it to construct TemporaryRef from a bare T*
+    friend class RefPtr<T>;
+
+    typedef typename RefPtr<T>::dontRef dontRef;
+
+public:
+    TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
+    TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
+
+    template<typename U>
+    TemporaryRef(const TemporaryRef<U>& o) : ptr(o.drop()) {}
+
+    ~TemporaryRef() { RefPtr<T>::unref(ptr); }
+
+    T* drop() const {
+        T* tmp = ptr;
+        ptr = 0;
+        return tmp;
+    }
+
+private:
+    TemporaryRef(T* t, const dontRef&) : ptr(t) {}
+
+    mutable T* ptr;
+
+    TemporaryRef();
+    TemporaryRef& operator=(const TemporaryRef&);
+};
+
+#endif
diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c
index 73078362d..39391650f 100644
--- a/src/win32/cairo-win32-surface.c
+++ b/src/win32/cairo-win32-surface.c
@@ -48,6 +48,7 @@
 
 #include "cairoint.h"
 
+#include "cairo-backend-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
 #include "cairo-image-surface-private.h"
@@ -170,6 +171,46 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
     return NULL;
 }
 
+HDC
+cairo_win32_get_dc_with_clip (cairo_t *cr)
+{
+    cairo_surface_t *surface = cairo_get_target (cr);
+    if (cr->backend->type == CAIRO_TYPE_DEFAULT) {
+        cairo_default_context_t *c = (cairo_default_context_t *) cr;
+        cairo_clip_t *clip = _cairo_clip_copy (_cairo_gstate_get_clip (c->gstate));
+        if (_cairo_surface_is_win32 (surface)) {
+            cairo_win32_display_surface_t *winsurf = (cairo_win32_display_surface_t *) surface;
+
+            _cairo_win32_display_surface_set_clip (winsurf, clip);
+
+            _cairo_clip_destroy (clip);
+            return winsurf->win32.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)) {
+                cairo_status_t status;
+                cairo_win32_printing_surface_t *psurf = (cairo_win32_printing_surface_t *) target;
+
+                status = _cairo_surface_clipper_set_clip (&psurf->clipper, clip);
+
+                _cairo_clip_destroy (clip);
+
+                if (status)
+                    return NULL;
+
+                return psurf->win32.dc;
+            }
+        }
+        _cairo_clip_destroy (clip);
+    }
+    return NULL;
+}
+
 /**
  * _cairo_surface_is_win32:
  * @surface: a #cairo_surface_t
@@ -178,7 +219,7 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
  *
  * Return value: %TRUE if the surface is an win32 surface
  **/
-static inline cairo_bool_t
+cairo_bool_t
 _cairo_surface_is_win32 (const cairo_surface_t *surface)
 {
     /* _cairo_surface_nil sets a NULL backend so be safe */
@@ -219,6 +260,16 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
 				  cairo_scaled_font_t	 *scaled_font,
 				  cairo_bool_t		  glyph_indexing)
 {
+#if CAIRO_HAS_DWRITE_FONT
+    if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
+        if (!glyph_indexing) return CAIRO_INT_STATUS_UNSUPPORTED;
+
+        // FIXME: fake values for params that aren't currently passed in here
+        cairo_operator_t op = CAIRO_OPERATOR_SOURCE;
+        cairo_clip_t *clip = NULL;
+        return _cairo_dwrite_show_glyphs_on_surface (dst, op, source, glyphs, num_glyphs, scaled_font, clip /* , glyph_indexing */ );
+    }
+#endif
 #if CAIRO_HAS_WIN32_FONT
     WORD glyph_buf_stack[STACK_GLYPH_SIZE];
     WORD *glyph_buf = glyph_buf_stack;
@@ -335,3 +386,17 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
 #endif
 }
 #undef STACK_GLYPH_SIZE
+
+cairo_status_t
+cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height)
+{
+    if (surface->type != CAIRO_SURFACE_TYPE_WIN32)
+        return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+
+    const cairo_win32_surface_t *winsurface = (const cairo_win32_surface_t *) surface;
+
+    *width = winsurface->extents.width;
+    *height = winsurface->extents.height;
+
+    return CAIRO_STATUS_SUCCESS;
+}


More information about the cairo-commit mailing list