[cairo-commit] 13 commits - src/cairoint.h src/cairo-pdf-surface.c src/cairo-scaled-font.c src/cairo-scaled-font-subsets-private.h src/win32

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 19 16:17:28 UTC 2022


 src/cairo-pdf-surface.c                 |    4 
 src/cairo-scaled-font-subsets-private.h |    5 
 src/cairo-scaled-font.c                 |    5 
 src/cairoint.h                          |   44 +-
 src/win32/cairo-dwrite-font-public.c    |   15 
 src/win32/cairo-dwrite-font.cpp         |  515 +++++++++++++++++++++-----------
 src/win32/cairo-dwrite-private.hpp      |   46 +-
 src/win32/dw-extra.h                    |   91 +++++
 8 files changed, 495 insertions(+), 230 deletions(-)

New commits:
commit a934fa66dba2b880723f4e5c3fdea92cbe0207e7
Merge: 0e1cffe36 e15a1e9a0
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Apr 19 16:17:26 2022 +0000

    Merge branch 'dwrite-fixes' into 'master'
    
    DWrite fixes
    
    See merge request cairo/cairo!311

commit e15a1e9a06483c0dd00ecc6fb8e2012f0ce6beb9
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Apr 19 15:17:50 2022 +0930

    Fix mingw warning
    
    it doesn't like '%lld' in snprintf

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d8ef47db8..d2581ce77 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -6802,7 +6802,6 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
     cairo_pdf_object_t *object;
     int num_objects, i;
     long long offset;
-    char buffer[11];
 
     num_objects = _cairo_array_num_elements (&surface->objects);
 
@@ -6816,9 +6815,8 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
 				 "0000000000 65535 f \n");
     for (i = 0; i < num_objects; i++) {
 	object = _cairo_array_index (&surface->objects, i);
-	snprintf (buffer, sizeof buffer, "%010lld", object->u.offset);
 	_cairo_output_stream_printf (surface->output,
-				     "%s 00000 n \n", buffer);
+				     "%010lld 00000 n \n", object->u.offset);
     }
 
     return offset;
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index d92d05dc0..ec44d3180 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -523,7 +523,7 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
 	sizeof(cairo_dwrite_scaled_font_t));
     if (unlikely(dwrite_font == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    
+
     *font = reinterpret_cast<cairo_scaled_font_t*>(dwrite_font);
     status = _cairo_scaled_font_init (&dwrite_font->base,
 				      &font_face->base,
@@ -1332,7 +1332,7 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_font_face_t*)&_cairo_font_face_nil;
     }
-    
+
     dwriteface->AddRef();
     face->dwriteface = dwriteface;
     face->have_color = false;
commit 90e6f2a9f7818172ea62ae5449a1a36740efdcdb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Apr 18 22:05:05 2022 +0930

    DWrite: Replace manual or missing ref counting with RefPtr

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 8eb7c1208..d92d05dc0 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -108,7 +108,7 @@ _cairo_dwrite_error (HRESULT hr, const char *context)
 class D2DFactory
 {
 public:
-    static ID2D1Factory *Instance()
+    static RefPtr<ID2D1Factory> Instance()
     {
 	if (!mFactoryInstance) {
 #ifdef __GNUC__
@@ -132,7 +132,7 @@ public:
 	return mFactoryInstance;
     }
 
-    static IDWriteFactory4 *Instance4()
+    static RefPtr<IDWriteFactory4> Instance4()
     {
 	if (!mFactoryInstance4) {
 	    if (Instance()) {
@@ -142,7 +142,7 @@ public:
 	return mFactoryInstance4;
     }
 
-    static ID2D1DCRenderTarget *RenderTarget()
+    static RefPtr<ID2D1DCRenderTarget> RenderTarget()
     {
 	if (!mRenderTarget) {
 	    if (!Instance()) {
@@ -166,15 +166,15 @@ public:
     }
 
 private:
-    static ID2D1Factory *mFactoryInstance;
-    static IDWriteFactory4 *mFactoryInstance4;
-    static ID2D1DCRenderTarget *mRenderTarget;
+    static RefPtr<ID2D1Factory> mFactoryInstance;
+    static RefPtr<IDWriteFactory4> mFactoryInstance4;
+    static RefPtr<ID2D1DCRenderTarget> mRenderTarget;
 };
 
 class WICImagingFactory
 {
 public:
-    static IWICImagingFactory *Instance()
+    static RefPtr<IWICImagingFactory> Instance()
     {
 	if (!mFactoryInstance) {
 	    CoInitialize(NULL);
@@ -186,26 +186,26 @@ public:
 	return mFactoryInstance;
     }
 private:
-    static IWICImagingFactory *mFactoryInstance;
+    static RefPtr<IWICImagingFactory> mFactoryInstance;
 };
 
 
-IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
-IDWriteFactory4 *DWriteFactory::mFactoryInstance4 = NULL;
+RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance;
+RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4;
 
-IWICImagingFactory *WICImagingFactory::mFactoryInstance = NULL;
-IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
-IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
-IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
-IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
+RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance;
+RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection;
+RefPtr<IDWriteRenderingParams> DWriteFactory::mDefaultRenderingParams;
+RefPtr<IDWriteRenderingParams> DWriteFactory::mCustomClearTypeRenderingParams;
+RefPtr<IDWriteRenderingParams> DWriteFactory::mForceGDIClassicRenderingParams;
 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;
+RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance;
+RefPtr<ID2D1DCRenderTarget> D2DFactory::mRenderTarget;
 
 /* Functions #cairo_font_face_backend_t */
 static cairo_status_t
@@ -329,7 +329,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
     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);
+    RefPtr<IDWriteFontFamily> family = DWriteFactory::FindSystemFontFamily(face_name);
     delete face_name;
     if (!family) {
 	/* If the family is not found, use the default that should always exist. */
@@ -370,12 +370,12 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 	break;
     }
 
-    IDWriteFont *font;
+    RefPtr<IDWriteFont> font;
     HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font);
     if (FAILED(hr))
 	return (cairo_status_t)_cairo_dwrite_error (hr, "GetFirstMatchingFont failed");
 
-    IDWriteFontFace *dwriteface;
+    RefPtr<IDWriteFontFace> dwriteface;
     hr = font->CreateFontFace(&dwriteface);
     if (FAILED(hr))
 	return (cairo_status_t)_cairo_dwrite_error (hr, "CreateFontFace failed");
@@ -393,7 +393,6 @@ _cairo_dwrite_font_face_destroy (void *font_face)
     return TRUE;
 }
 
-
 static inline unsigned short
 read_short(const char *buf)
 {
@@ -519,11 +518,19 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
     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.
+    /* Must do malloc and not C++ new, since Cairo frees this. */
     cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_malloc(
 	sizeof(cairo_dwrite_scaled_font_t));
+    if (unlikely(dwrite_font == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    
     *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);
+    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;
@@ -879,7 +886,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     double y = -glyph.y;
     DWRITE_MATRIX matrix;
     D2D1_POINT_2F origin = {0, 0};
-    IDWriteColorGlyphRunEnumerator1 *run_enumerator;
+    RefPtr<IDWriteColorGlyphRunEnumerator1> run_enumerator;
     HRESULT hr;
 
     /**
@@ -934,7 +941,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     if (!WICImagingFactory::Instance() || !D2DFactory::Instance())
 	return _cairo_dwrite_error (hr, "Instance failed");
 
-    IWICBitmap *bitmap = NULL;
+    RefPtr<IWICBitmap> bitmap;
     hr = WICImagingFactory::Instance()->CreateBitmap ((UINT)width,
 						      (UINT)height,
 						      GUID_WICPixelFormat32bppPBGRA,
@@ -953,17 +960,17 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 	D2D1_RENDER_TARGET_USAGE_NONE,
 	D2D1_FEATURE_LEVEL_DEFAULT);
 
-    ID2D1RenderTarget* rt = NULL;
+    RefPtr<ID2D1RenderTarget> rt;
     hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt);
     if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed");
 
-    ID2D1DeviceContext4* dc4 = NULL;
+    RefPtr<ID2D1DeviceContext4> dc4;
     hr = rt->QueryInterface(&dc4);
     if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed");
 
-    ID2D1SolidColorBrush *foreground_color_brush;
+    RefPtr<ID2D1SolidColorBrush> foreground_color_brush;
     if (foreground_color) {
 	dc4->CreateSolidColorBrush(
 	    D2D1::ColorF(foreground_color->red,
@@ -974,7 +981,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 	dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &foreground_color_brush);
     }
 
-    ID2D1SolidColorBrush *color_brush;
+    RefPtr<ID2D1SolidColorBrush> color_brush;
     dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush);
 
     dc4->SetDpi(96, 96); /* 1 unit = 1 pixel */
@@ -1048,9 +1055,6 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "EndDraw 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 };
@@ -1059,7 +1063,6 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 		       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,
@@ -1252,7 +1255,7 @@ _cairo_dwrite_is_synthetic(void                      *scaled_font,
 	return CAIRO_INT_STATUS_SUCCESS;
     }
 
-    IDWriteFontFace5 *fontFace5 = NULL;
+    RefPtr<IDWriteFontFace5> fontFace5;
     if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) {
 	/* If IDWriteFontFace5 is not available, assume this version of
 	 * DirectWrite does not support variations.
@@ -1266,7 +1269,7 @@ _cairo_dwrite_is_synthetic(void                      *scaled_font,
 	return CAIRO_INT_STATUS_SUCCESS;
     }
 
-    IDWriteFontResource *fontResource = NULL;
+    RefPtr<IDWriteFontResource> fontResource;
     hr = fontFace5->GetFontResource(&fontResource);
     if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "GetFontResource failed");
@@ -1325,24 +1328,26 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac
     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));
-    cairo_font_face_t *font_face;
-
+    if (unlikely (face == NULL)) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_font_face_t*)&_cairo_font_face_nil;
+    }
+    
     dwriteface->AddRef();
-
     face->dwriteface = dwriteface;
-
     face->have_color = false;
+
     /* Ensure IDWriteFactory4 is available before enabling color fonts */
     if (DWriteFactory::Instance4()) {
-	IDWriteFontFace2 *fontFace2;
+	RefPtr<IDWriteFontFace2> fontFace2;
 	if (SUCCEEDED(dwriteface->QueryInterface(&fontFace2))) {
 	    if (fontFace2->IsColorFont())
 		face->have_color = true;
 	}
     }
 
+    cairo_font_face_t *font_face;
     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;
@@ -1387,9 +1392,9 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 				       cairo_dwrite_scaled_font_t *scaled_font,
 				       const RECT &area)
 {
-    IDWriteGdiInterop *gdiInterop;
+    RefPtr<IDWriteGdiInterop> gdiInterop;
     DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
-    IDWriteBitmapRenderTarget *rt;
+    RefPtr<IDWriteBitmapRenderTarget> rt;
     HRESULT hr;
 
     cairo_dwrite_scaled_font_t::TextRenderingState renderingState =
@@ -1412,16 +1417,15 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
          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;
+      RefPtr<IDWriteBitmapRenderTarget1> rt1;
       hr = rt->QueryInterface(&rt1);
 
       if (SUCCEEDED(hr) && rt1) {
         rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
-        rt1->Release();
       }
     }
 
-    IDWriteRenderingParams *params =
+    RefPtr<IDWriteRenderingParams> params =
         DWriteFactory::RenderingParams(renderingState);
 
     /**
@@ -1443,9 +1447,9 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 	   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;
+	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;
@@ -1458,9 +1462,6 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 	   rt->GetMemoryDC(),
 	   0, 0,
 	   SRCCOPY | NOMIRRORBITMAP);
-    params->Release();
-    rt->Release();
-    gdiInterop->Release();
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
@@ -1473,27 +1474,22 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
 {
     HRESULT hr;
 
-    ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
+    RefPtr<ID2D1DCRenderTarget> rt = D2DFactory::RenderTarget();
 
     // XXX don't we need to set RenderingParams on this RenderTarget?
 
     hr = rt->BindDC(surface->dc, &area);
-
-    if (FAILED(hr)) {
-	rt->Release();
+    if (FAILED(hr))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
 
     // D2D uses 0x00RRGGBB not 0x00BBGGRR like COLORREF.
     color = (color & 0xFF) << 16 |
 	(color & 0xFF00) |
 	(color & 0xFF0000) >> 16;
-    ID2D1SolidColorBrush *brush;
+    RefPtr<ID2D1SolidColorBrush> brush;
     hr = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
-    if (FAILED(hr)) {
-	rt->Release();
+    if (FAILED(hr))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
 
     if (transform) {
 	rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
@@ -1509,10 +1505,8 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
     if (transform) {
 	rt->SetTransform(D2D1::Matrix3x2F::Identity());
     }
-    brush->Release();
-    if (FAILED(hr)) {
+    if (FAILED(hr))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
 
     return CAIRO_INT_STATUS_SUCCESS;
 }
@@ -1745,9 +1739,11 @@ DWriteFactory::CreateRenderingParams()
     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);
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index 1a43b5c38..34f86e8f1 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -35,6 +35,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-win32-refptr.hpp"
 #include <dwrite.h>
 #include <d2d1.h>
 
@@ -82,7 +83,7 @@ typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
 class DWriteFactory
 {
 public:
-    static IDWriteFactory *Instance()
+    static RefPtr<IDWriteFactory> Instance()
     {
 	if (!mFactoryInstance) {
 #ifdef __GNUC__
@@ -105,7 +106,7 @@ public:
 	return mFactoryInstance;
     }
 
-    static IDWriteFactory4 *Instance4()
+    static RefPtr<IDWriteFactory4> Instance4()
     {
 	if (!mFactoryInstance4) {
 	    if (Instance()) {
@@ -115,7 +116,7 @@ public:
 	return mFactoryInstance4;
     }
 
-    static IDWriteFontCollection *SystemCollection()
+    static RefPtr<IDWriteFontCollection> SystemCollection()
     {
 	if (!mSystemCollection) {
 	    if (Instance()) {
@@ -126,7 +127,7 @@ public:
 	return mSystemCollection;
     }
 
-    static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName)
+    static RefPtr<IDWriteFontFamily> FindSystemFontFamily(const WCHAR *aFamilyName)
     {
 	UINT32 idx;
 	BOOL found;
@@ -138,12 +139,12 @@ public:
 	    return NULL;
 	}
 
-	IDWriteFontFamily *family;
+	RefPtr<IDWriteFontFamily> family;
 	SystemCollection()->GetFontFamily(idx, &family);
 	return family;
     }
 
-    static IDWriteRenderingParams *RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode)
+    static RefPtr<IDWriteRenderingParams> RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode)
     {
 	if (!mDefaultRenderingParams ||
             !mForceGDIClassicRenderingParams ||
@@ -151,7 +152,7 @@ public:
         {
 	    CreateRenderingParams();
 	}
-	IDWriteRenderingParams *params;
+	RefPtr<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) {
@@ -159,9 +160,6 @@ public:
         } else {
             params = mCustomClearTypeRenderingParams;
         }
-	if (params) {
-	    params->AddRef();
-	}
 	return params;
     }
 
@@ -198,12 +196,12 @@ public:
 private:
     static void CreateRenderingParams();
 
-    static IDWriteFactory *mFactoryInstance;
-    static IDWriteFactory4 *mFactoryInstance4;
-    static IDWriteFontCollection *mSystemCollection;
-    static IDWriteRenderingParams *mDefaultRenderingParams;
-    static IDWriteRenderingParams *mCustomClearTypeRenderingParams;
-    static IDWriteRenderingParams *mForceGDIClassicRenderingParams;
+    static RefPtr<IDWriteFactory> mFactoryInstance;
+    static RefPtr<IDWriteFactory4> mFactoryInstance4;
+    static RefPtr<IDWriteFontCollection> mSystemCollection;
+    static RefPtr<IDWriteRenderingParams> mDefaultRenderingParams;
+    static RefPtr<IDWriteRenderingParams> mCustomClearTypeRenderingParams;
+    static RefPtr<IDWriteRenderingParams> mForceGDIClassicRenderingParams;
     static FLOAT mGamma;
     static FLOAT mEnhancedContrast;
     static FLOAT mClearTypeLevel;
@@ -250,7 +248,7 @@ private:
 /* #cairo_font_face_t implementation */
 struct _cairo_dwrite_font_face {
     cairo_font_face_t base;
-    IDWriteFontFace *dwriteface;
+    IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd.  */
     cairo_bool_t have_color;
 };
 typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
commit 3998a79cc23fdcc7b3c0539fbe43e39472d54621
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Apr 18 13:38:50 2022 +0930

    DWrite: check 'head' table as well as 'name' when comparing fonts
    
    There may be different versions of fonts with the same name. As an
    additional check, compare the 'head' table wich contains the checksum
    for the font.
    
    Also, load the DWrite tables directly to avoid the memcpy in
    load_truetype_table.

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index e7809f03a..5b531d298 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -41,6 +41,8 @@
 
 #if CAIRO_HAS_FONT_SUBSET
 
+CAIRO_BEGIN_DECLS
+
 typedef struct _cairo_scaled_font_subsets_glyph {
     unsigned int font_id;
     unsigned int subset_id;
@@ -735,6 +737,9 @@ cairo_private void
 dump_scaled_font_subsets (cairo_scaled_font_subsets_t *font_subsets);
 #endif
 
+CAIRO_END_DECLS
+
+
 #endif /* CAIRO_HAS_FONT_SUBSET */
 
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/win32/cairo-dwrite-font-public.c b/src/win32/cairo-dwrite-font-public.c
index c23cb6029..9e4e56ba8 100644
--- a/src/win32/cairo-dwrite-font-public.c
+++ b/src/win32/cairo-dwrite-font-public.c
@@ -44,10 +44,10 @@
 /**
  * SECTION:cairo-dwrite-fonts
  * @Title: DWrite Fonts
- * @Short_Description: Font support for Microsoft DWrite
+ * @Short_Description: Font support for Microsoft DirectWrite
  * @See_Also: #cairo_font_face_t
  *
- * The Microsoft DWrite font backend is primarily used to render text on
+ * The Microsoft DirectWrite font backend is primarily used to render text on
  * Microsoft Windows systems.
  **/
 
@@ -106,6 +106,17 @@
  * cairo_show_text(cr, "😃");
  * ]]></programlisting></informalexample>
  *
+ * Note: When printing a DWrite font to a
+ * #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface, the printing surface
+ * will substitute each DWrite font with a Win32 font created from the same
+ * underlying font file. If the matching font file can not be found,
+ * the #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface will convert each
+ * glyph to a filled path. If a DWrite font was not created from a system
+ * font, it is recommended that the font used to create the DWrite
+ * font be made available to GDI to avoid the undesirable fallback
+ * to emitting paths. This can be achieved using the GDI font loading functions
+ * such as AddFontMemResourceEx().
+ *
  * Return value: a newly created #cairo_font_face_t. Free with
  *  cairo_font_face_destroy() when you are done using it.
  *
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index a18e303d1..8eb7c1208 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -44,6 +44,7 @@
 #include "cairo-win32-refptr.hpp"
 #include "cairo-dwrite-private.hpp"
 #include "cairo-truetype-subset-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 #include <float.h>
 
 #include <wincodec.h>
@@ -1752,53 +1753,100 @@ DWriteFactory::CreateRenderingParams()
         &mForceGDIClassicRenderingParams);
 }
 
-static cairo_bool_t
-_name_tables_match (cairo_scaled_font_t *font1,
-                    cairo_scaled_font_t *font2)
+/* Check if a specific font table in a DWrite font and a scaled font is identical */
+static cairo_int_status_t
+compare_font_tables (cairo_dwrite_font_face_t *dwface,
+		     cairo_scaled_font_t      *scaled_font,
+		     unsigned long             tag,
+		     cairo_bool_t             *match)
 {
-    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;
-        }
+    unsigned long size;
+    cairo_int_status_t status;
+    unsigned char *buffer = NULL;
+    const void *dw_data;
+    UINT32 dw_size;
+    void *dw_tableContext = NULL;
+    BOOL dw_exists = FALSE;
+    HRESULT hr;
+
+    hr = dwface->dwriteface->TryGetFontTable(be32_to_cpu (tag),
+					     &dw_data,
+					     &dw_size,
+					     &dw_tableContext,
+					     &dw_exists);
+    if (FAILED(hr))
+	return _cairo_dwrite_error (hr, "TryGetFontTable failed");
+
+    if (!dw_exists) {
+	*match = FALSE;
+	status = CAIRO_INT_STATUS_SUCCESS;
+	goto cleanup;
     }
 
-    free (buffer1);
-    free (buffer2);
-    return result;
+    status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, NULL, &size);
+    if (unlikely(status))
+	goto cleanup;
+
+    if (size != dw_size) {
+	*match = FALSE;
+	status = CAIRO_INT_STATUS_SUCCESS;
+	goto cleanup;
+    }
+
+    buffer = (unsigned char *) _cairo_malloc (size);
+    if (unlikely (buffer == NULL)) {
+	status = (cairo_int_status_t) _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto cleanup;
+    }
+
+    status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, buffer, &size);
+    if (unlikely(status))
+	goto cleanup;
+
+    *match = memcmp (dw_data, buffer, size) == 0;
+    status = CAIRO_INT_STATUS_SUCCESS;
+
+cleanup:
+    free (buffer);
+    if (dw_tableContext)
+	dwface->dwriteface->ReleaseFontTable(dw_tableContext);
+
+    return status;
+}
+
+/* Check if a DWrite font and a scaled font areis identical
+ *
+ * DWrite does not allow accessing the entire font data using tag=0 so we compare
+ * two of the font tables:
+ * - 'name' table
+ * - 'head' table since this contains the checksum for the entire font
+ */
+static cairo_int_status_t
+font_tables_match (cairo_dwrite_font_face_t *dwface,
+		   cairo_scaled_font_t      *scaled_font,
+		   cairo_bool_t             *match)
+{
+    cairo_int_status_t status;
+
+    status = compare_font_tables (dwface, scaled_font, TT_TAG_name, match);
+    if (unlikely(status))
+	return status;
+
+    if (!*match)
+	return CAIRO_INT_STATUS_SUCCESS;
+
+    status = compare_font_tables (dwface, scaled_font, TT_TAG_head, match);
+    if (unlikely(status))
+	return status;
+
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
-// 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.
+/*
+ * 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)
@@ -1820,12 +1868,15 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
     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
+
+    /* DWrite 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) {
+    if (cairo_font_face_status (win32_face)) {
+	cairo_font_face_destroy (win32_face);
         return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
@@ -1844,14 +1895,36 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
 			                                  &options);
     cairo_font_face_destroy (win32_face);
 
-    if (!font) {
+    if (cairo_scaled_font_status(font)) {
+	cairo_scaled_font_destroy (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);
+    cairo_bool_t match;
+    cairo_int_status_t status;
+    status = font_tables_match (dwface, font, &match);
+    if (status) {
+	cairo_scaled_font_destroy (font);
+	return status;
+    }
+
+    /* If the font tables aren't equal, then GDI may have failed to
+     * find the right font and substituted a different font.
+     */
+    if (!match) {
+#if 0
+	char *ps_name;
+	char *font_name;
+	status = _cairo_truetype_read_font_name (scaled_font, &ps_name, &font_name);
+	printf("dwrite fontname: %s PS name: %s\n", font_name, ps_name);
+	free (font_name);
+	free (ps_name);
+	status = _cairo_truetype_read_font_name (font, &ps_name, &font_name);
+	printf("win32  fontname: %s PS name: %s\n", font_name, ps_name);
+	free (font_name);
+	free (ps_name);
+#endif
+	cairo_scaled_font_destroy (font);
         return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
commit 2b355954a894182fe92315d38b44015a1d6e2f0d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 14:38:15 2022 +0930

    DWrite: ensure all private functions are static

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 3aa7bd0bc..a18e303d1 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -65,7 +65,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
 				       COLORREF color,
 				       const RECT &area);
 
-cairo_int_status_t
+static cairo_int_status_t
 _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 				       DWRITE_MATRIX *transform,
 				       DWRITE_GLYPH_RUN *run,
@@ -82,7 +82,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
  *
  * Return value: A cairo status code for the error code
  **/
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_error (HRESULT hr, const char *context)
 {
     void *lpMsgBuf;
@@ -229,7 +229,7 @@ const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = {
 
 /* Functions #cairo_scaled_font_backend_t */
 
-void _cairo_dwrite_scaled_font_fini(void *scaled_font);
+static void _cairo_dwrite_scaled_font_fini(void *scaled_font);
 
 static cairo_warn cairo_int_status_t
 _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
@@ -237,25 +237,25 @@ _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
 				cairo_scaled_glyph_info_t     info,
 				const cairo_color_t          *foreground_color);
 
-cairo_int_status_t
+static 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
+static unsigned long
 _cairo_dwrite_ucs4_to_index(void		       *scaled_font,
 			    uint32_t                    ucs4);
 
-cairo_int_status_t
-static _cairo_dwrite_is_synthetic(void                *scaled_font,
+static cairo_int_status_t
+_cairo_dwrite_is_synthetic(void                       *scaled_font,
 			   cairo_bool_t               *is_synthetic);
 
 static cairo_bool_t
 _cairo_dwrite_has_color_glyphs(void *scaled_font);
 
-const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
+static 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,
@@ -280,7 +280,7 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
  * \param Cairo matrix
  * \return DirectWrite matrix
  **/
-DWRITE_MATRIX
+static DWRITE_MATRIX
 _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
 {
     DWRITE_MATRIX dwmat;
@@ -294,7 +294,7 @@ _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
 }
 
 /* Helper functions for cairo_dwrite_scaled_glyph_init() */
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_metrics
     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
 
@@ -303,11 +303,11 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 						   cairo_scaled_glyph_t	      *scaled_glyph,
 						   const cairo_color_t        *foreground_color);
 
-cairo_int_status_t
+static 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
+static cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_path
     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
 
@@ -587,7 +587,7 @@ _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
 }
 
 /* Implementation #cairo_dwrite_scaled_font_backend_t */
-void
+static void
 _cairo_dwrite_scaled_font_fini(void *scaled_font)
 {
 }
@@ -628,7 +628,7 @@ _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
-unsigned long
+static unsigned long
 _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
 			    uint32_t		      ucs4)
 {
@@ -641,7 +641,7 @@ _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
 }
 
 /* cairo_dwrite_scaled_glyph_init() helper function bodies */
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
 					     cairo_scaled_glyph_t *scaled_glyph)
 {
@@ -799,7 +799,7 @@ private:
     D2D1_POINT_2F mStartPoint;
 };
 
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
 					  cairo_scaled_glyph_t *scaled_glyph)
 {
@@ -845,7 +845,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
     return status;
 }
 
-cairo_int_status_t
+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)
@@ -1104,7 +1104,7 @@ _compute_a8_mask (cairo_surface_t *surface)
     return &mask->base;
 }
 
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font,
 					     cairo_scaled_glyph_t	*scaled_glyph)
 {
@@ -1198,7 +1198,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
     return status;
 }
 
-cairo_int_status_t
+static cairo_int_status_t
 _cairo_dwrite_load_truetype_table(void                 *scaled_font,
 				  unsigned long         tag,
 				  long                  offset,
@@ -1378,7 +1378,7 @@ cairo_dwrite_get_cleartype_rendering_mode()
     return DWriteFactory::GetClearTypeRenderingMode();
 }
 
-cairo_int_status_t
+static cairo_int_status_t
 _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
 				       DWRITE_MATRIX *transform,
 				       DWRITE_GLYPH_RUN *run,
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index d9b8ec653..1a43b5c38 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -254,13 +254,3 @@ struct _cairo_dwrite_font_face {
     cairo_bool_t have_color;
 };
 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);
commit 655a8a40a766f6adb1fbafb468562f3446632307
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:56:39 2022 +0930

    Dwrite glyph_path fails when the font matrix is not a positive uniform scale

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 93d98bfec..3aa7bd0bc 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -814,18 +814,30 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
     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);
+
+    /* GetGlyphRunOutline seems to ignore hinting so just use the em size to get the outline
+     * to avoid rounding errors when converting to cairo_path_fixed_t.
+     */
+    DWRITE_FONT_METRICS metrics;
+    dwriteff->dwriteface->GetMetrics(&metrics);
+    HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(metrics.designUnitsPerEm,
+							  &glyphId,
+							  &advance,
+							  &offset,
+							  1,
+							  FALSE,
+							  FALSE,
+							  &recorder);
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "GetGlyphRunOutline failed");
+
     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);
+    /* Now scale the em size down to 1.0 and apply the font matrix and font ctm. */
+    cairo_matrix_t mat = scaled_font->base.ctm;
+    cairo_matrix_multiply(&mat, &scaled_font->base.font_matrix, &mat);
+    cairo_matrix_scale (&mat, 1.0/metrics.designUnitsPerEm, 1.0/metrics.designUnitsPerEm);
+    _cairo_path_fixed_transform(path, &mat);
 
     _cairo_scaled_glyph_set_path (scaled_glyph,
 				  &scaled_font->base,
commit 75f0ecb34e8f9d890bf0c27c09544202db8dc4a7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:52:33 2022 +0930

    Fix Win64 compile warning

diff --git a/src/cairoint.h b/src/cairoint.h
index 09831ddb2..987bf9a58 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -407,7 +407,7 @@ _cairo_hash_bytes (uintptr_t hash,
 		   unsigned int length);
 
 /* We use bits 24-27 to store phases for subpixel positions */
-#define _cairo_scaled_glyph_index(g) ((g)->hash_entry.hash & 0xffffff)
+#define _cairo_scaled_glyph_index(g) ((unsigned long)((g)->hash_entry.hash & 0xffffff))
 #define _cairo_scaled_glyph_xphase(g) (int)(((g)->hash_entry.hash >> 24) & 3)
 #define _cairo_scaled_glyph_yphase(g) (int)(((g)->hash_entry.hash >> 26) & 3)
 #define _cairo_scaled_glyph_set_index(g, i)  ((g)->hash_entry.hash = (i))
commit 1cc23206bde186d4aef948bba11e591120c99dcd
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:49:30 2022 +0930

    Fix scaled_glyph hash lookup on Win64
    
    This was failing due to sizeof(uintptr_t) != sizeof(long) on Win64

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index e0b586589..30611dca4 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -3001,6 +3001,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
     cairo_int_status_t		 status = CAIRO_INT_STATUS_SUCCESS;
     cairo_scaled_glyph_t	*scaled_glyph;
     cairo_scaled_glyph_info_t	 need_info;
+    cairo_hash_entry_t           key;
 
     *scaled_glyph_ret = NULL;
 
@@ -3019,8 +3020,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
     /*
      * Check cache for glyph
      */
-    scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs,
-					     (cairo_hash_entry_t *) &index);
+    key.hash = index;
+    scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs, &key);
     if (scaled_glyph == NULL) {
 	status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph);
 	if (unlikely (status))
commit 6454f65ec5b5ce7e7aa93fabcf9b5957f617cabe
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:38:03 2022 +0930

    Allow the C++ code in dwrite-font to use the debug functions

diff --git a/src/cairoint.h b/src/cairoint.h
index b2874e169..09831ddb2 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2109,7 +2109,6 @@ slim_hidden_proto (cairo_surface_write_to_png_stream);
 
 #endif
 
-CAIRO_END_DECLS
 
 #include "cairo-mutex-private.h"
 #include "cairo-fixed-private.h"
@@ -2152,4 +2151,6 @@ _cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip);
 #define TRACE_(x)
 #endif
 
+CAIRO_END_DECLS
+
 #endif
commit b4014daedf8960098c12c519bb7455b87f524137
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:34:11 2022 +0930

    DWrite: Use twin font if default font not found
    
    If the default font is not found, return CAIRO_INT_STATUS_UNSUPPORTED
    to cause _cairo_toy_font_face_create_impl_face to create the Twin user
    font fallback.

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 1e9781ec8..93d98bfec 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -340,7 +340,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 	delete face_name;
 	if (!family) {
 	    *font_face = (cairo_font_face_t*)&_cairo_font_face_nil;
-	    return CAIRO_STATUS_FONT_TYPE_MISMATCH;
+	    return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
 	}
     }
 
commit 672c92e19c9fab1a5fa0b3bfc5076b3cab3b5319
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 13:33:02 2022 +0930

    Fix DWrite error handling
    
    - Fix a few cases of incorrect error handling
    - Use a consistent style and variable names for errors

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index d4f21c561..1e9781ec8 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -371,15 +371,16 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 
     IDWriteFont *font;
     HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font);
-    if (SUCCEEDED(hr)) {
-	IDWriteFontFace *dwriteface;
-	hr = font->CreateFontFace(&dwriteface);
-	if (SUCCEEDED(hr)) {
-	    *font_face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface);
-	    return CAIRO_STATUS_SUCCESS;
-	}
-    }
-    return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
+    if (FAILED(hr))
+	return (cairo_status_t)_cairo_dwrite_error (hr, "GetFirstMatchingFont failed");
+
+    IDWriteFontFace *dwriteface;
+    hr = font->CreateFontFace(&dwriteface);
+    if (FAILED(hr))
+	return (cairo_status_t)_cairo_dwrite_error (hr, "CreateFontFace failed");
+
+    *font_face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface);
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
@@ -913,7 +914,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     if (hr == DWRITE_E_NOCOLOR)
 	return CAIRO_INT_STATUS_UNSUPPORTED; /* No color glyphs */
 
-    if (!SUCCEEDED(hr))
+    if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed");
 
     /* We have a color glyph(s). Use Direct2D to render it to a bitmap */
@@ -926,7 +927,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 						      GUID_WICPixelFormat32bppPBGRA,
 						      WICBitmapCacheOnLoad,
 						      &bitmap);
-    if (!SUCCEEDED(hr))
+    if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "CreateBitmap failed");
 
     D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
@@ -941,12 +942,13 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
 
     ID2D1RenderTarget* rt = NULL;
     hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt);
-    if (!SUCCEEDED(hr))
+    if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed");
 
     ID2D1DeviceContext4* dc4 = NULL;
-    if (!SUCCEEDED(rt->QueryInterface(&dc4)))
-	return _cairo_dwrite_error (hr, "QueryInterface failed");
+    hr = rt->QueryInterface(&dc4);
+    if (FAILED(hr))
+	return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed");
 
     ID2D1SolidColorBrush *foreground_color_brush;
     if (foreground_color) {
@@ -976,11 +978,12 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     while (true) {
 	BOOL have_run;
 	hr = run_enumerator->MoveNext(&have_run);
-	if (!SUCCEEDED(hr) || !have_run)
+	if (FAILED(hr) || !have_run)
 	    break;
 
 	DWRITE_COLOR_GLYPH_RUN1 const* color_run;
-	if (!SUCCEEDED(run_enumerator->GetCurrentRun (&color_run)))
+	hr = run_enumerator->GetCurrentRun(&color_run);
+	if (FAILED(hr))
 	    return _cairo_dwrite_error (hr, "GetCurrentRun failed");
 
 	switch (color_run->glyphImageFormat) {
@@ -1029,8 +1032,8 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
     }
 
     hr = dc4->EndDraw();
-    if (!SUCCEEDED(hr))
-	return _cairo_dwrite_error (hr, "dc4 failed");
+    if (FAILED(hr))
+	return _cairo_dwrite_error (hr, "EndDraw failed");
 
     color_brush->Release();
     foreground_color_brush->Release();
@@ -1197,11 +1200,14 @@ _cairo_dwrite_load_truetype_table(void                 *scaled_font,
     UINT32 size;
     void *tableContext;
     BOOL exists;
-    face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
-				      &data,
-				      &size,
-				      &tableContext,
-				      &exists);
+    HRESULT hr;
+    hr = face->dwriteface->TryGetFontTable (be32_to_cpu (tag),
+					    &data,
+					    &size,
+					    &tableContext,
+					    &exists);
+    if (FAILED(hr))
+	return _cairo_dwrite_error (hr, "TryGetFontTable failed");
 
     if (!exists) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1234,7 +1240,7 @@ _cairo_dwrite_is_synthetic(void                      *scaled_font,
     }
 
     IDWriteFontFace5 *fontFace5 = NULL;
-    if (!SUCCEEDED(face->dwriteface->QueryInterface(&fontFace5))) {
+    if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) {
 	/* If IDWriteFontFace5 is not available, assume this version of
 	 * DirectWrite does not support variations.
 	 */
@@ -1249,7 +1255,7 @@ _cairo_dwrite_is_synthetic(void                      *scaled_font,
 
     IDWriteFontResource *fontResource = NULL;
     hr = fontFace5->GetFontResource(&fontResource);
-    if (!SUCCEEDED(hr))
+    if (FAILED(hr))
 	return _cairo_dwrite_error (hr, "GetFontResource failed");
 
     UINT32 axis_count = fontResource->GetFontAxisCount();
@@ -1257,13 +1263,13 @@ _cairo_dwrite_is_synthetic(void                      *scaled_font,
     DWRITE_FONT_AXIS_VALUE *axis_values = new DWRITE_FONT_AXIS_VALUE[axis_count];
 
     hr = fontResource->GetDefaultFontAxisValues(axis_defaults, axis_count);
-    if (!SUCCEEDED(hr)) {
+    if (FAILED(hr)) {
 	status = _cairo_dwrite_error (hr, "GetDefaultFontAxisValues failed");
 	goto cleanup;
     }
 
     hr = fontFace5->GetFontAxisValues(axis_values, axis_count);
-    if (!SUCCEEDED(hr)) {
+    if (FAILED(hr)) {
 	status = _cairo_dwrite_error (hr, "GetFontAxisValues failed");
 	goto cleanup;
     }
@@ -1371,18 +1377,18 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
     IDWriteGdiInterop *gdiInterop;
     DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
     IDWriteBitmapRenderTarget *rt;
-    HRESULT rv;
+    HRESULT hr;
 
     cairo_dwrite_scaled_font_t::TextRenderingState renderingState =
       scaled_font->rendering_mode;
 
-    rv = gdiInterop->CreateBitmapRenderTarget(surface->dc,
+    hr = gdiInterop->CreateBitmapRenderTarget(surface->dc,
 					      area.right - area.left,
 					      area.bottom - area.top,
 					      &rt);
 
-    if (FAILED(rv)) {
-	if (rv == E_OUTOFMEMORY) {
+    if (FAILED(hr)) {
+	if (hr == E_OUTOFMEMORY) {
 	    return (cairo_int_status_t)CAIRO_STATUS_NO_MEMORY;
 	} else {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1394,9 +1400,9 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
         /* && !surface->base.permit_subpixel_antialiasing */ ) {
       renderingState = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
       IDWriteBitmapRenderTarget1* rt1;
-      rv = rt->QueryInterface(&rt1);
+      hr = rt->QueryInterface(&rt1);
 
-      if (SUCCEEDED(rv) && rt1) {
+      if (SUCCEEDED(hr) && rt1) {
         rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
         rt1->Release();
       }
@@ -1452,15 +1458,15 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
 				       COLORREF color,
 				       const RECT &area)
 {
-    HRESULT rv;
+    HRESULT hr;
 
     ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
 
     // XXX don't we need to set RenderingParams on this RenderTarget?
 
-    rv = rt->BindDC(surface->dc, &area);
+    hr = rt->BindDC(surface->dc, &area);
 
-    if (FAILED(rv)) {
+    if (FAILED(hr)) {
 	rt->Release();
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -1470,9 +1476,8 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
 	(color & 0xFF00) |
 	(color & 0xFF0000) >> 16;
     ID2D1SolidColorBrush *brush;
-    rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
-
-    if (FAILED(rv)) {
+    hr = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
+    if (FAILED(hr)) {
 	rt->Release();
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -1487,12 +1492,12 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
     }
     rt->BeginDraw();
     rt->DrawGlyphRun(D2D1::Point2F(0, 0), run, brush);
-    rt->EndDraw();
+    hr = rt->EndDraw();
     if (transform) {
 	rt->SetTransform(D2D1::Matrix3x2F::Identity());
     }
     brush->Release();
-    if (FAILED(rv)) {
+    if (FAILED(hr)) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
commit d2f65a73069fdd63f83a4129d7770a602fcaffcf
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 09:21:45 2022 +0930

    Dwrite: implement is_synthetic()

diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 4c9270a59..d4f21c561 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -245,8 +245,12 @@ _cairo_dwrite_load_truetype_table(void		       *scaled_font,
 				  unsigned long        *length);
 
 unsigned long
-_cairo_dwrite_ucs4_to_index(void			     *scaled_font,
-			    uint32_t			ucs4);
+_cairo_dwrite_ucs4_to_index(void		       *scaled_font,
+			    uint32_t                    ucs4);
+
+cairo_int_status_t
+static _cairo_dwrite_is_synthetic(void                *scaled_font,
+			   cairo_bool_t               *is_synthetic);
 
 static cairo_bool_t
 _cairo_dwrite_has_color_glyphs(void *scaled_font);
@@ -259,7 +263,7 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
     _cairo_dwrite_ucs4_to_index,
     _cairo_dwrite_load_truetype_table,
     NULL, /* index_to_ucs4 */
-    NULL, /* is_synthetic */
+    _cairo_dwrite_is_synthetic,
     NULL, /* index_to_glyph_name */
     NULL, /* load_type1_data */
     _cairo_dwrite_has_color_glyphs
@@ -1215,6 +1219,79 @@ _cairo_dwrite_load_truetype_table(void                 *scaled_font,
     return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_int_status_t
+_cairo_dwrite_is_synthetic(void                      *scaled_font,
+			   cairo_bool_t              *is_synthetic)
+{
+    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);
+    HRESULT hr;
+    cairo_int_status_t status;
+
+    if (face->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
+	*is_synthetic = FALSE;
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    IDWriteFontFace5 *fontFace5 = NULL;
+    if (!SUCCEEDED(face->dwriteface->QueryInterface(&fontFace5))) {
+	/* If IDWriteFontFace5 is not available, assume this version of
+	 * DirectWrite does not support variations.
+	 */
+	*is_synthetic = FALSE;
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    if (!fontFace5->HasVariations()) {
+	*is_synthetic = FALSE;
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    IDWriteFontResource *fontResource = NULL;
+    hr = fontFace5->GetFontResource(&fontResource);
+    if (!SUCCEEDED(hr))
+	return _cairo_dwrite_error (hr, "GetFontResource failed");
+
+    UINT32 axis_count = fontResource->GetFontAxisCount();
+    DWRITE_FONT_AXIS_VALUE *axis_defaults = new DWRITE_FONT_AXIS_VALUE[axis_count];
+    DWRITE_FONT_AXIS_VALUE *axis_values = new DWRITE_FONT_AXIS_VALUE[axis_count];
+
+    hr = fontResource->GetDefaultFontAxisValues(axis_defaults, axis_count);
+    if (!SUCCEEDED(hr)) {
+	status = _cairo_dwrite_error (hr, "GetDefaultFontAxisValues failed");
+	goto cleanup;
+    }
+
+    hr = fontFace5->GetFontAxisValues(axis_values, axis_count);
+    if (!SUCCEEDED(hr)) {
+	status = _cairo_dwrite_error (hr, "GetFontAxisValues failed");
+	goto cleanup;
+    }
+
+    /* The DirectWrite documentation does not state if the tags of the returned
+     * defaults and values arrays are in the same order. So assume they are not.
+     */
+    *is_synthetic = FALSE;
+    status = CAIRO_INT_STATUS_SUCCESS;
+    for (UINT32 i = 0; i< axis_count; i++) {
+	for (UINT32 j = 0; j < axis_count; j++) {
+	    if (axis_values[i].axisTag == axis_defaults[j].axisTag) {
+		if (axis_values[i].value != axis_defaults[j].value) {
+		    *is_synthetic = TRUE;
+		    goto cleanup;
+		}
+		break;
+	    }
+	}
+    }
+
+  cleanup:
+    delete[] axis_defaults;
+    delete[] axis_values;
+    
+    return status;
+}
+
 static cairo_bool_t
 _cairo_dwrite_has_color_glyphs(void *scaled_font)
 {
diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp
index 07fb0e765..d9b8ec653 100644
--- a/src/win32/cairo-dwrite-private.hpp
+++ b/src/win32/cairo-dwrite-private.hpp
@@ -38,8 +38,8 @@
 #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 either of the dwrite_3.h or d2d1_3.h headers required for color fonts
+ * are not available, include our own version containing just the functions we need.
  */
 
 #if HAVE_DWRITE_3_H
diff --git a/src/win32/dw-extra.h b/src/win32/dw-extra.h
index f6e37e609..4203f3427 100644
--- a/src/win32/dw-extra.h
+++ b/src/win32/dw-extra.h
@@ -2,8 +2,15 @@
 
 /* Mingw-w64 dwrite_3.h is broken
  *
- * We only need the definitions of one function and its dependencies.
- *   IDWriteFactory4::TranslateColorGlyphRun
+ * We only need the definitions of the following functions and their dependencies.
+ *   IDWriteFactory4::TranslateColorGlyphRun()
+ *   IDWriteFontResource::GetDefaultFontAxisValues()
+ *   IDWriteFontResource::GetFontAxisCount()
+ *   IDWriteFontResource::HasVariations()
+ *   IDWriteFontFace5::GetFontAxisValueCount()
+ *   IDWriteFontFace5::GetFontAxisValues()
+ *   IDWriteFontFace5::HasVariations()
+ *   IDWriteFontFace5::GetFontResource()
  *
  * 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
@@ -74,5 +81,85 @@ IDWriteFactory4 : public IDWriteFactory3
 };
 __CRT_UUID_DECL(IDWriteFactory4, 0x4b0b5bd3, 0x0797, 0x4549, 0x8a,0xc5, 0xfe,0x91,0x5c,0xc5,0x38,0x56)
 
+typedef enum DWRITE_FONT_AXIS_TAG {
+    DWRITE_FONT_AXIS_TAG_WEIGHT = 0x74686777,
+    DWRITE_FONT_AXIS_TAG_WIDTH = 0x68746477,
+    DWRITE_FONT_AXIS_TAG_SLANT = 0x746e6c73,
+    DWRITE_FONT_AXIS_TAG_OPTICAL_SIZE = 0x7a73706f,
+    DWRITE_FONT_AXIS_TAG_ITALIC = 0x6c617469
+} DWRITE_FONT_AXIS_TAG;
+
+typedef struct DWRITE_FONT_AXIS_VALUE {
+    DWRITE_FONT_AXIS_TAG axisTag;
+    FLOAT value;
+} DWRITE_FONT_AXIS_VALUE;
+
+DEFINE_GUID(IID_IDWriteFontResource, 0x1f803a76, 0x6871, 0x48e8, 0x98,0x7f, 0xb9,0x75,0x55,0x1c,0x50,0xf2);
+MIDL_INTERFACE("1f803a76-6871-48e8-987f-b975551c50f2")
+IDWriteFontResource : public IUnknown
+{
+  virtual void STDMETHODCALLTYPE GetFontFile() = 0;
+  virtual void STDMETHODCALLTYPE GetFontFaceIndex() = 0;
+  virtual UINT32 STDMETHODCALLTYPE GetFontAxisCount() = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetDefaultFontAxisValues(
+    const DWRITE_FONT_AXIS_VALUE *values,
+    UINT32 num_values) = 0;
+  virtual void STDMETHODCALLTYPE GetFontAxisRanges() = 0;
+  virtual void STDMETHODCALLTYPE GetFontAxisAttributes() = 0;
+  virtual void STDMETHODCALLTYPE GetAxisNames() = 0;
+  virtual void STDMETHODCALLTYPE GetAxisValueNameCount() = 0;
+  virtual void STDMETHODCALLTYPE GetAxisValueNames() = 0;
+  virtual WINBOOL STDMETHODCALLTYPE HasVariations() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontFace() = 0;
+  virtual void STDMETHODCALLTYPE CreateFontFaceReference() = 0;
+};
+__CRT_UUID_DECL(IDWriteFontResource, 0x1f803a76, 0x6871, 0x48e8, 0x98,0x7f, 0xb9,0x75,0x55,0x1c,0x50,0xf2)
+
+DEFINE_GUID(IID_IDWriteFontFace3, 0xd37d7598, 0x09be, 0x4222, 0xa2,0x36, 0x20,0x81,0x34,0x1c,0xc1,0xf2);
+MIDL_INTERFACE("d37d7598-09be-4222-a236-2081341cc1f2")
+IDWriteFontFace3 : public IDWriteFontFace2
+{
+  virtual void STDMETHODCALLTYPE GetFontFaceReference() = 0;
+  virtual void STDMETHODCALLTYPE GetPanose() = 0;
+  virtual void STDMETHODCALLTYPE GetWeight() = 0;
+  virtual void STDMETHODCALLTYPE GetStretch() = 0;
+  virtual void STDMETHODCALLTYPE GetStyle() = 0;
+  virtual void STDMETHODCALLTYPE GetFamilyNames() = 0;
+  virtual void STDMETHODCALLTYPE GetFaceNames() = 0;
+  virtual void STDMETHODCALLTYPE GetInformationalStrings() = 0;
+  virtual void STDMETHODCALLTYPE HasCharacter() = 0;
+  virtual void STDMETHODCALLTYPE GetRecommendedRenderingMode() = 0;
+  virtual void STDMETHODCALLTYPE IsCharacterLocal() = 0;
+  virtual void STDMETHODCALLTYPE IsGlyphLocal() = 0;
+  virtual void STDMETHODCALLTYPE AreCharactersLocal() = 0;
+  virtual void STDMETHODCALLTYPE AreGlyphsLocal() = 0;
+};
+__CRT_UUID_DECL(IDWriteFontFace3, 0xd37d7598, 0x09be, 0x4222, 0xa2,0x36, 0x20,0x81,0x34,0x1c,0xc1,0xf2)
+
+DEFINE_GUID(IID_IDWriteFontFace4, 0x27f2a904, 0x4eb8, 0x441d, 0x96,0x78, 0x05,0x63,0xf5,0x3e,0x3e,0x2f);
+MIDL_INTERFACE("27f2a904-4eb8-441d-9678-0563f53e3e2f")
+IDWriteFontFace4 : public IDWriteFontFace3
+{
+  virtual void STDMETHODCALLTYPE GetGlyphImageFormats_() = 0;
+  virtual void STDMETHODCALLTYPE GetGlyphImageFormats() = 0;
+  virtual void STDMETHODCALLTYPE GetGlyphImageData() = 0;
+  virtual void STDMETHODCALLTYPE ReleaseGlyphImageData() = 0;
+};
+__CRT_UUID_DECL(IDWriteFontFace4, 0x27f2a904, 0x4eb8, 0x441d, 0x96,0x78, 0x05,0x63,0xf5,0x3e,0x3e,0x2f)
+
+DEFINE_GUID(IID_IDWriteFontFace5, 0x98eff3a5, 0xb667, 0x479a, 0xb1,0x45, 0xe2,0xfa,0x5b,0x9f,0xdc,0x29);
+MIDL_INTERFACE("98eff3a5-b667-479a-b145-e2fa5b9fdc29")
+IDWriteFontFace5 : public IDWriteFontFace4
+{
+  virtual UINT32 STDMETHODCALLTYPE GetFontAxisValueCount() = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetFontAxisValues(
+    DWRITE_FONT_AXIS_VALUE *values,
+    UINT32 value_count) = 0;
+  virtual WINBOOL STDMETHODCALLTYPE HasVariations() = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetFontResource(
+    IDWriteFontResource **resource) = 0;
+  virtual void STDMETHODCALLTYPE Equals() = 0;
+};
+__CRT_UUID_DECL(IDWriteFontFace5, 0x98eff3a5, 0xb667, 0x479a, 0xb1,0x45, 0xe2,0xfa,0x5b,0x9f,0xdc,0x29)
 
 #endif /* DWRITE_EXTRA_H */
commit 0321ac99a4baa97cdfe8cfcd00c1dd35ed5cedaf
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 09:21:25 2022 +0930

    cairoint.h: update some comments

diff --git a/src/cairoint.h b/src/cairoint.h
index 79b4ffaf0..b2874e169 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -488,19 +488,19 @@ struct _cairo_scaled_font_backend {
     void
     (*fini)		(void			*scaled_font);
 
-/*
- * Get the requested glyph info.
- * @scaled_font: a #cairo_scaled_font_t
- * @scaled_glyph: a #cairo_scaled_glyph_t the glyph
- * @info: a #cairo_scaled_glyph_info_t which information to retrieve
- *  %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
- *  %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
- *  %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
- *  %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph
- *  %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image
- * @foreground_color - foreground color to use when rendering color fonts. Use NULL
- * if not requesting CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE or foreground color is unknown.
- */
+    /*
+     * Get the requested glyph info.
+     * @scaled_font: a #cairo_scaled_font_t
+     * @scaled_glyph: a #cairo_scaled_glyph_t the glyph
+     * @info: a #cairo_scaled_glyph_info_t which information to retrieve
+     *  %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
+     *  %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
+     *  %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
+     *  %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph
+     *  %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image
+     * @foreground_color - foreground color to use when rendering color fonts. Use NULL
+     * if not requesting CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE or foreground color is unknown.
+     */
     cairo_warn cairo_int_status_t
     (*scaled_glyph_init)	(void			     *scaled_font,
 				 cairo_scaled_glyph_t	     *scaled_glyph,
@@ -523,6 +523,11 @@ struct _cairo_scaled_font_backend {
 		       int		          *num_clusters,
 		       cairo_text_cluster_flags_t *cluster_flags);
 
+    /* Get the glyph index for the given unicode code point.
+     * @scaled_font: a #cairo_scaled_font_t
+     * @ucs4: unicode code point
+     * Returns glyph index or 0 if not found.
+     */
     unsigned long
     (*ucs4_to_index)		(void			     *scaled_font,
 				 uint32_t		      ucs4);
@@ -561,6 +566,9 @@ struct _cairo_scaled_font_backend {
 
     /* Determine if this scaled font differs from the outlines in the font tables.
      * eg synthesized bold/italic or a non default variant of a variable font.
+     * @scaled_font: font
+     * @is_sythetic: returns TRUE if scaled font is synthetic
+     * Returns cairo status
      */
     cairo_warn cairo_int_status_t
     (*is_synthetic)(void                       *scaled_font,
@@ -577,7 +585,6 @@ struct _cairo_scaled_font_backend {
      * @glyph_array_index: (index into glyph_names) the glyph name corresponding
      *  to the glyph_index
      */
-
     cairo_warn cairo_int_status_t
     (*index_to_glyph_name)(void                 *scaled_font,
 			   char                **glyph_names,
@@ -605,6 +612,10 @@ struct _cairo_scaled_font_backend {
                            unsigned char        *buffer,
                            unsigned long        *length);
 
+    /* Check if font has any color glyphs.
+     * @scaled_font: font
+     * Returns TRUE if font contains any color glyphs
+     */
     cairo_bool_t
     (*has_color_glyphs)   (void                 *scaled_font);
 };


More information about the cairo-commit mailing list