diff options
author | Uli Schlachter <psychon@znc.in> | 2022-04-19 16:17:26 +0000 |
---|---|---|
committer | Uli Schlachter <psychon@znc.in> | 2022-04-19 16:17:26 +0000 |
commit | a934fa66dba2b880723f4e5c3fdea92cbe0207e7 (patch) | |
tree | 5e394595892a1015e71d6dd7406a4b4e8bb8aa27 | |
parent | 0e1cffe364f802db82b811e033b06c8bbef859a8 (diff) | |
parent | e15a1e9a06483c0dd00ecc6fb8e2012f0ce6beb9 (diff) |
Merge branch 'dwrite-fixes' into 'master'
DWrite fixes
See merge request cairo/cairo!311
-rw-r--r-- | src/cairo-pdf-surface.c | 4 | ||||
-rw-r--r-- | src/cairo-scaled-font-subsets-private.h | 5 | ||||
-rwxr-xr-x | src/cairo-scaled-font.c | 5 | ||||
-rw-r--r-- | src/cairoint.h | 44 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-font-public.c | 15 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 515 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-private.hpp | 46 | ||||
-rw-r--r-- | src/win32/dw-extra.h | 91 |
8 files changed, 495 insertions, 230 deletions
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/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/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)) diff --git a/src/cairoint.h b/src/cairoint.h index 79b4ffaf0..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)) @@ -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); }; @@ -2098,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" @@ -2141,4 +2151,6 @@ _cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip); #define TRACE_(x) #endif +CAIRO_END_DECLS + #endif 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 4c9270a59..ec44d3180 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> @@ -65,7 +66,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 +83,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; @@ -107,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__ @@ -131,7 +132,7 @@ public: return mFactoryInstance; } - static IDWriteFactory4 *Instance4() + static RefPtr<IDWriteFactory4> Instance4() { if (!mFactoryInstance4) { if (Instance()) { @@ -141,7 +142,7 @@ public: return mFactoryInstance4; } - static ID2D1DCRenderTarget *RenderTarget() + static RefPtr<ID2D1DCRenderTarget> RenderTarget() { if (!mRenderTarget) { if (!Instance()) { @@ -165,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); @@ -185,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 @@ -229,7 +230,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,21 +238,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 -_cairo_dwrite_ucs4_to_index(void *scaled_font, - uint32_t ucs4); +static unsigned long +_cairo_dwrite_ucs4_to_index(void *scaled_font, + uint32_t ucs4); + +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, @@ -259,7 +264,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 @@ -276,7 +281,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; @@ -290,7 +295,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); @@ -299,11 +304,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); @@ -324,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. */ @@ -336,7 +341,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; } } @@ -365,17 +370,18 @@ _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 (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"); + + RefPtr<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 @@ -387,7 +393,6 @@ _cairo_dwrite_font_face_destroy (void *font_face) return TRUE; } - static inline unsigned short read_short(const char *buf) { @@ -513,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; @@ -582,7 +595,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) { } @@ -623,7 +636,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) { @@ -636,7 +649,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) { @@ -794,7 +807,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) { @@ -809,18 +822,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, @@ -828,7 +853,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) @@ -861,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; /** @@ -909,20 +934,20 @@ _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 */ 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, WICBitmapCacheOnLoad, &bitmap); - if (!SUCCEEDED(hr)) + if (FAILED(hr)) return _cairo_dwrite_error (hr, "CreateBitmap failed"); D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties( @@ -935,16 +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 (!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"); + 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, @@ -955,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 */ @@ -972,11 +998,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) { @@ -1025,11 +1052,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"); - - color_brush->Release(); - foreground_color_brush->Release(); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "EndDraw failed"); cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); int stride = cairo_image_surface_get_stride (image); @@ -1039,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, @@ -1085,7 +1108,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) { @@ -1179,7 +1202,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, @@ -1193,11 +1216,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; @@ -1215,6 +1241,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; + } + + RefPtr<IDWriteFontFace5> fontFace5; + if (FAILED(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; + } + + RefPtr<IDWriteFontResource> fontResource; + hr = fontFace5->GetFontResource(&fontResource); + if (FAILED(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 (FAILED(hr)) { + status = _cairo_dwrite_error (hr, "GetDefaultFontAxisValues failed"); + goto cleanup; + } + + hr = fontFace5->GetFontAxisValues(axis_values, axis_count); + if (FAILED(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) { @@ -1229,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; @@ -1283,7 +1384,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, @@ -1291,21 +1392,21 @@ _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; - HRESULT rv; + RefPtr<IDWriteBitmapRenderTarget> rt; + 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; @@ -1316,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; - rv = rt->QueryInterface(&rt1); + RefPtr<IDWriteBitmapRenderTarget1> rt1; + hr = rt->QueryInterface(&rt1); - if (SUCCEEDED(rv) && rt1) { + if (SUCCEEDED(hr) && rt1) { rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE); - rt1->Release(); } } - IDWriteRenderingParams *params = + RefPtr<IDWriteRenderingParams> params = DWriteFactory::RenderingParams(renderingState); /** @@ -1347,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; @@ -1362,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; } @@ -1375,30 +1472,24 @@ _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(); + RefPtr<ID2D1DCRenderTarget> rt = D2DFactory::RenderTarget(); // XXX don't we need to set RenderingParams on this RenderTarget? - rv = rt->BindDC(surface->dc, &area); - - if (FAILED(rv)) { - rt->Release(); + hr = rt->BindDC(surface->dc, &area); + 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; - rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush); - - if (FAILED(rv)) { - rt->Release(); + RefPtr<ID2D1SolidColorBrush> brush; + hr = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush); + if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; - } if (transform) { rt->SetTransform(D2D1::Matrix3x2F(transform->m11, @@ -1410,14 +1501,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; - } return CAIRO_INT_STATUS_SUCCESS; } @@ -1650,61 +1739,110 @@ 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); } -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; } -// 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. +/* 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. + */ cairo_int_status_t _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font, cairo_scaled_font_t **new_font) @@ -1726,12 +1864,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; } @@ -1750,14 +1891,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; } diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp index 07fb0e765..34f86e8f1 100644 --- a/src/win32/cairo-dwrite-private.hpp +++ b/src/win32/cairo-dwrite-private.hpp @@ -35,11 +35,12 @@ */ #include "cairoint.h" +#include "cairo-win32-refptr.hpp" #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 @@ -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,17 +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; - -DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix); - -// This will initialize a DWrite glyph run from cairo glyphs and a scaled_font. -void -_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs, - int num_glyphs, - cairo_dwrite_scaled_font_t *scaled_font, - AutoDWriteGlyphRun *run, - cairo_bool_t *transformed); diff --git a/src/win32/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 */ |