summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2021-08-14 15:38:14 +0930
committerAdrian Johnson <ajohnson@redneon.com>2022-02-27 20:20:24 +1030
commit5635c75a2c99a901fa1410d4a297c1a1c913c0ee (patch)
tree36983c34acfa163f6d476f1e90c3ddaa7e5747c2
parentfdf2a9b4c0b610ef5dc328c7a095ff8e6e263f05 (diff)
downloadcairo-5635c75a2c99a901fa1410d4a297c1a1c913c0ee.tar.gz
dwrite: add color font support
-rw-r--r--meson.build22
-rw-r--r--src/cairo-device.c1
-rw-r--r--src/cairo-error-private.h1
-rw-r--r--src/cairo-misc.c2
-rw-r--r--src/cairo-region.c1
-rw-r--r--src/cairo-spans.c2
-rw-r--r--src/cairo-surface.c1
-rw-r--r--src/cairo.c4
-rw-r--r--src/cairo.h2
-rw-r--r--src/win32/cairo-dwrite-font.cpp412
-rw-r--r--src/win32/cairo-dwrite-private.hpp40
-rw-r--r--src/win32/d2d1-extra.h111
-rw-r--r--src/win32/dw-extra.h78
13 files changed, 629 insertions, 48 deletions
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@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 */