diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2021-08-14 15:38:14 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2022-02-27 20:20:24 +1030 |
commit | 5635c75a2c99a901fa1410d4a297c1a1c913c0ee (patch) | |
tree | 36983c34acfa163f6d476f1e90c3ddaa7e5747c2 | |
parent | fdf2a9b4c0b610ef5dc328c7a095ff8e6e263f05 (diff) | |
download | cairo-5635c75a2c99a901fa1410d4a297c1a1c913c0ee.tar.gz |
dwrite: add color font support
-rw-r--r-- | meson.build | 22 | ||||
-rw-r--r-- | src/cairo-device.c | 1 | ||||
-rw-r--r-- | src/cairo-error-private.h | 1 | ||||
-rw-r--r-- | src/cairo-misc.c | 2 | ||||
-rw-r--r-- | src/cairo-region.c | 1 | ||||
-rw-r--r-- | src/cairo-spans.c | 2 | ||||
-rw-r--r-- | src/cairo-surface.c | 1 | ||||
-rw-r--r-- | src/cairo.c | 4 | ||||
-rw-r--r-- | src/cairo.h | 2 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 412 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-private.hpp | 40 | ||||
-rw-r--r-- | src/win32/d2d1-extra.h | 111 | ||||
-rw-r--r-- | src/win32/dw-extra.h | 78 |
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 */ |