diff options
Diffstat (limited to 'src/win32/cairo-dwrite-font.cpp')
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 760 |
1 files changed, 409 insertions, 351 deletions
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index c58827555..cf516d41c 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -45,10 +45,31 @@ #include "cairo-dwrite-private.hpp" #include "cairo-truetype-subset-private.h" #include "cairo-scaled-font-subsets-private.h" +#include "cairo-dwrite.h" + #include <float.h> #include <wincodec.h> +/** + * SECTION:cairo-dwrite-fonts + * @Title: DWrite Fonts + * @Short_Description: Font support for Microsoft DirectWrite + * @See_Also: #cairo_font_face_t + * + * The Microsoft DirectWrite font backend is primarily used to render text on + * Microsoft Windows systems. + **/ + +/** + * CAIRO_HAS_DWRITE_FONT: + * + * Defined if the Microsoft DWrite font backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.18 + **/ + typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( D2D1_FACTORY_TYPE factoryType, REFIID iid, @@ -191,22 +212,119 @@ private: RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance; +RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1; +RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2; +RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3; RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4; 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; RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance; RefPtr<ID2D1DCRenderTarget> D2DFactory::mRenderTarget; +static int +_quality_from_antialias_mode(cairo_antialias_t antialias) +{ + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + return NONANTIALIASED_QUALITY; + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GRAY: + return ANTIALIASED_QUALITY; + default: + break; + } + return CLEARTYPE_QUALITY; +} + +static RefPtr<IDWriteRenderingParams> +_create_rendering_params(IDWriteRenderingParams *params, + const cairo_font_options_t *options, + cairo_antialias_t antialias) +{ + if (!params) + params = DWriteFactory::DefaultRenderingParams(); + FLOAT gamma = params->GetGamma(); + FLOAT enhanced_contrast = params->GetEnhancedContrast(); + FLOAT clear_type_level = params->GetClearTypeLevel(); + DWRITE_PIXEL_GEOMETRY pixel_geometry = params->GetPixelGeometry(); + DWRITE_RENDERING_MODE rendering_mode = params->GetRenderingMode(); + + cairo_bool_t modified = FALSE; + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + if (rendering_mode != DWRITE_RENDERING_MODE_ALIASED) { + rendering_mode = DWRITE_RENDERING_MODE_ALIASED; + modified = TRUE; + } + break; + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GRAY: + if (clear_type_level) { + clear_type_level = 0; + modified = TRUE; + } + break; + default: + break; + } + auto subpixel_order = cairo_font_options_get_subpixel_order (options); + switch (subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_RGB: + if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_RGB) { + pixel_geometry = DWRITE_PIXEL_GEOMETRY_RGB; + modified = TRUE; + } + break; + case CAIRO_SUBPIXEL_ORDER_BGR: + if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_BGR) { + pixel_geometry = DWRITE_PIXEL_GEOMETRY_BGR; + modified = TRUE; + } + break; + default: + break; + } + if (!modified) + return params; + + HRESULT hr; + RefPtr<IDWriteRenderingParams1> params1; + hr = params->QueryInterface(¶ms1); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams> ret; + DWriteFactory::Instance()->CreateCustomRenderingParams(gamma, enhanced_contrast, clear_type_level, pixel_geometry, rendering_mode, &ret); + return ret; + } + + FLOAT grayscaleEnhancedContrast = params1->GetGrayscaleEnhancedContrast(); + RefPtr<IDWriteRenderingParams2> params2; + hr = params->QueryInterface(¶ms2); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams1> ret; + DWriteFactory::Instance1()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, &ret); + return ret; + } + + DWRITE_GRID_FIT_MODE gridFitMode = params2->GetGridFitMode(); + RefPtr<IDWriteRenderingParams3> params3; + hr = params->QueryInterface(¶ms3); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams2> ret; + DWriteFactory::Instance2()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, gridFitMode, &ret); + return ret; + } + + DWRITE_RENDERING_MODE1 rendering_mode1 = params3->GetRenderingMode1(); + if (antialias == CAIRO_ANTIALIAS_NONE) + rendering_mode1 = DWRITE_RENDERING_MODE1_ALIASED; + RefPtr<IDWriteRenderingParams3> ret; + DWriteFactory::Instance3()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode1, gridFitMode, &ret); + return ret; +} + /* Functions #cairo_font_face_backend_t */ static cairo_status_t _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, @@ -330,7 +448,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len); RefPtr<IDWriteFontFamily> family = DWriteFactory::FindSystemFontFamily(face_name); - delete face_name; + delete[] face_name; if (!family) { /* If the family is not found, use the default that should always exist. */ face_name_len = MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, NULL, 0); @@ -338,7 +456,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, face_name, face_name_len); family = DWriteFactory::FindSystemFontFamily(face_name); - delete face_name; + delete[] face_name; if (!family) { *font_face = (cairo_font_face_t*)&_cairo_font_face_nil; return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED; @@ -390,6 +508,8 @@ _cairo_dwrite_font_face_destroy (void *font_face) cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face); if (dwrite_font_face->dwriteface) dwrite_font_face->dwriteface->Release(); + if (dwrite_font_face->rendering_params) + dwrite_font_face->rendering_params->Release(); return TRUE; } @@ -536,10 +656,21 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, return status; } + 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_font_extents_t extents; DWRITE_FONT_METRICS metrics; - font_face->dwriteface->GetMetrics(&metrics); + if (dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || + dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { + DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&dwrite_font->mat); + font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics); + } else { + font_face->dwriteface->GetMetrics(&metrics); + } extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm; extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm; @@ -547,15 +678,8 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, extents.max_x_advance = 14.0; extents.max_y_advance = 0.0; - 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; - 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 // are re-used, they might not adhere to the new system setting until re- @@ -566,12 +690,10 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, break; case ANTIALIASED_QUALITY: default_quality = CAIRO_ANTIALIAS_GRAY; - 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; - dwrite_font->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC; break; } @@ -587,9 +709,8 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, dwrite_font->antialias_mode = options->antialias; } - 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; + dwrite_font->rendering_params = _create_rendering_params(font_face->rendering_params, options, dwrite_font->antialias_mode).forget().drop(); + dwrite_font->measuring_mode = font_face->measuring_mode; return _cairo_scaled_font_set_metrics (*font, &extents); } @@ -598,6 +719,9 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, static void _cairo_dwrite_scaled_font_fini(void *scaled_font) { + cairo_dwrite_scaled_font_t *dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); + if (dwrite_font->rendering_params) + dwrite_font->rendering_params->Release(); } static cairo_int_status_t @@ -659,17 +783,30 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ DWRITE_GLYPH_METRICS metrics; DWRITE_FONT_METRICS fontMetrics; - font_face->dwriteface->GetMetrics(&fontMetrics); - HRESULT hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); + HRESULT hr; + if (font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || + font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { + DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&scaled_font->mat); + font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics); + BOOL natural = font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL; + hr = font_face->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE); + } else { + font_face->dwriteface->GetMetrics(&fontMetrics); + hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); + } if (FAILED(hr)) { return CAIRO_INT_STATUS_UNSUPPORTED; } + // GetGdiCompatibleMetrics may return a glyph metrics that yields a small nagative glyph height. + INT32 glyph_width = metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing; + INT32 glyph_height = metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing; + glyph_width = MAX(glyph_width, 0); + glyph_height = MAX(glyph_height, 0); + // TODO: Treat swap_xy. - extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) / - fontMetrics.designUnitsPerEm; - extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) / - fontMetrics.designUnitsPerEm; + extents.width = (FLOAT)glyph_width / fontMetrics.designUnitsPerEm; + extents.height = (FLOAT)glyph_height / fontMetrics.designUnitsPerEm; extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm; extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm; extents.y_advance = 0.0; @@ -679,10 +816,15 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ // We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics // for the glyph outline, without accounting for hinting/gridfitting/antialiasing, // and therefore it does not always cover all pixels that will actually be touched. - if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE && - extents.width > 0 && extents.height > 0) { - extents.width += scaled_font->mat_inverse.xx * 2; - extents.x_bearing -= scaled_font->mat_inverse.xx; + if (extents.width > 0 && extents.height > 0) { + double x = 1, y = 1; + cairo_matrix_transform_distance (&scaled_font->mat_inverse, &x, &y); + x = fabs(x); + y = fabs(y); + extents.width += x * 2; + extents.x_bearing -= x; + extents.height += y * 2; + extents.y_bearing -= y; } _cairo_scaled_glyph_set_metrics (scaled_glyph, @@ -699,8 +841,9 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ class GeometryRecorder : public IDWriteGeometrySink { public: - GeometryRecorder(cairo_path_fixed_t *aCairoPath) - : mCairoPath(aCairoPath) {} + GeometryRecorder(cairo_path_fixed_t *aCairoPath, const cairo_matrix_t &matrix) + : mCairoPath(aCairoPath) + , mMatrix(matrix) {} // IUnknown interface IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) @@ -738,28 +881,18 @@ public: return; } - cairo_fixed_t GetFixedX(const D2D1_POINT_2F &point) - { - unsigned int control_word; - _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC); - return _cairo_fixed_from_double(point.x); - } - - cairo_fixed_t GetFixedY(const D2D1_POINT_2F &point) - { - unsigned int control_word; - _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC); - return _cairo_fixed_from_double(point.y); - } - IFACEMETHODIMP_(void) BeginFigure( D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) { - mStartPoint = startPoint; + double x = startPoint.x; + double y = startPoint.y; + cairo_matrix_transform_point(&mMatrix, &x, &y); + mStartPointX = _cairo_fixed_from_double(x); + mStartPointY = _cairo_fixed_from_double(y); cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath, - GetFixedX(startPoint), - GetFixedY(startPoint)); + mStartPointX, + mStartPointY); (void)status; /* squelch warning */ } @@ -768,8 +901,8 @@ public: { if (figureEnd == D2D1_FIGURE_END_CLOSED) { cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - GetFixedX(mStartPoint), - GetFixedY(mStartPoint)); + mStartPointX, + mStartPointY); (void)status; /* squelch warning */ } } @@ -779,13 +912,22 @@ public: UINT beziersCount) { for (unsigned int i = 0; i < beziersCount; i++) { + double x1 = beziers[i].point1.x; + double y1 = beziers[i].point1.y; + double x2 = beziers[i].point2.x; + double y2 = beziers[i].point2.y; + double x3 = beziers[i].point3.x; + double y3 = beziers[i].point3.y; + cairo_matrix_transform_point(&mMatrix, &x1, &y1); + cairo_matrix_transform_point(&mMatrix, &x2, &y2); + cairo_matrix_transform_point(&mMatrix, &x3, &y3); cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath, - GetFixedX(beziers[i].point1), - GetFixedY(beziers[i].point1), - GetFixedX(beziers[i].point2), - GetFixedY(beziers[i].point2), - GetFixedX(beziers[i].point3), - GetFixedY(beziers[i].point3)); + _cairo_fixed_from_double(x1), + _cairo_fixed_from_double(y1), + _cairo_fixed_from_double(x2), + _cairo_fixed_from_double(y2), + _cairo_fixed_from_double(x3), + _cairo_fixed_from_double(y3)); (void)status; /* squelch warning */ } } @@ -795,16 +937,21 @@ public: UINT pointsCount) { for (unsigned int i = 0; i < pointsCount; i++) { + double x = points[i].x; + double y = points[i].y; + cairo_matrix_transform_point(&mMatrix, &x, &y); cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - GetFixedX(points[i]), - GetFixedY(points[i])); + _cairo_fixed_from_double(x), + _cairo_fixed_from_double(y)); (void)status; /* squelch warning */ } } private: cairo_path_fixed_t *mCairoPath; - D2D1_POINT_2F mStartPoint; + const cairo_matrix_t &mMatrix; + cairo_fixed_t mStartPointX; + cairo_fixed_t mStartPointY; }; static cairo_int_status_t @@ -814,7 +961,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon cairo_int_status_t status; cairo_path_fixed_t *path; path = _cairo_path_fixed_create(); - GeometryRecorder recorder(path); + GeometryRecorder recorder(path, scaled_font->base.scale); DWRITE_GLYPH_OFFSET offset; offset.advanceOffset = 0; @@ -823,12 +970,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon FLOAT advance = 0.0; cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face; - /* 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, + HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1, &glyphId, &advance, &offset, @@ -841,12 +983,6 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon status = (cairo_int_status_t)_cairo_path_fixed_close_path(path); - /* 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, path); @@ -860,7 +996,6 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s { 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; @@ -877,22 +1012,18 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s 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; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; - double x = -glyph.x; - double y = -glyph.y; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); DWRITE_MATRIX matrix; D2D1_POINT_2F origin = {0, 0}; RefPtr<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 @@ -901,7 +1032,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s */ cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y); offset.advanceOffset = (FLOAT)x; - /** Y-axis is inverted */ + /* Y-axis is inverted */ offset.ascenderOffset = -(FLOAT)y; run.fontFace = dwrite_font_face->dwriteface; @@ -938,7 +1069,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s &run, NULL, /* glyphRunDescription */ supported_formats, - DWRITE_MEASURING_MODE_NATURAL, + dwrite_font_face->measuring_mode, &matrix, palette_index, &run_enumerator); @@ -1013,8 +1144,8 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s if (FAILED(hr) || !have_run) break; - DWRITE_COLOR_GLYPH_RUN1 const* color_run; - hr = run_enumerator->GetCurrentRun(&color_run); + DWRITE_COLOR_GLYPH_RUN1_WORKAROUND const* color_run; + hr = run_enumerator->GetCurrentRun(reinterpret_cast<const DWRITE_COLOR_GLYPH_RUN1**>(&color_run)); if (FAILED(hr)) return _cairo_dwrite_error (hr, "GetCurrentRun failed"); @@ -1027,7 +1158,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat, origin, &color_run->glyphRun, - DWRITE_MEASURING_MODE_NATURAL, + dwrite_font_face->measuring_mode, D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT); break; @@ -1038,7 +1169,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s foreground_color_brush, nullptr, palette_index, - DWRITE_MEASURING_MODE_NATURAL); + dwrite_font_face->measuring_mode); uses_foreground_color = TRUE; break; case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE: @@ -1050,14 +1181,23 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s color_brush->SetColor(&color); uses_foreground_color = TRUE; } else { - color_brush->SetColor(color_run->runColor); + double red, green, blue, alpha; + cairo_status_t status; + status = cairo_font_options_get_custom_palette_color (&scaled_font->base.options, + color_run->paletteIndex, + &red, &blue, &green, &alpha); + if (status == CAIRO_STATUS_SUCCESS) { + color_brush->SetColor(D2D1::ColorF(red, blue, green, alpha)); + } else { + color_brush->SetColor(color_run->runColor); + } } dc4->DrawGlyphRun(origin, &color_run->glyphRun, color_run->glyphRunDescription, color_brush, - DWRITE_MEASURING_MODE_NATURAL); + dwrite_font_face->measuring_mode); case DWRITE_GLYPH_IMAGE_FORMATS_NONE: break; } @@ -1079,55 +1219,18 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s _cairo_scaled_glyph_set_color_surface (scaled_glyph, &scaled_font->base, (cairo_image_surface_t *) image, - uses_foreground_color); + uses_foreground_color ? foreground_color : NULL); scaled_glyph->color_glyph = TRUE; scaled_glyph->color_glyph_set = TRUE; return CAIRO_INT_STATUS_SUCCESS; } -/* Helper function adapted from _compute_mask in cairo-win32-font.c */ - -/* Compute an alpha-mask from a monochrome RGB24 image - */ -static cairo_surface_t * -_compute_a8_mask (cairo_surface_t *surface) -{ - cairo_image_surface_t *glyph; - cairo_image_surface_t *mask; - int i, j; - - glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL); - if (unlikely (glyph->base.status)) - return &glyph->base; - - /* No quality param, just use the non-ClearType path */ - - /* Compute an alpha-mask by using the green channel of a (presumed monochrome) - * RGB24 image. - */ - mask = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_A8, glyph->width, glyph->height); - if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) { - for (i = 0; i < glyph->height; i++) { - uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride); - uint8_t *q = (uint8_t *) (mask->data + i * mask->stride); - - for (j = 0; j < glyph->width; j++) - *q++ = 255 - ((*p++ & 0x0000ff00) >> 8); - } - } - - cairo_surface_unmap_image (surface, &glyph->base); - return &mask->base; -} - 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 status; - cairo_glyph_t glyph; cairo_win32_surface_t *surface; cairo_t *cr; cairo_surface_t *image; @@ -1141,16 +1244,12 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ 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; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; - double x = glyph.x; - double y = glyph.y; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); RECT area; DWRITE_MATRIX matrix; @@ -1165,7 +1264,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ if (status) goto FAIL; - /** + /* * We transform by the inverse transformation here. This will put our glyph * locations in the space in which we draw. Which is later transformed by * the transformation matrix that we use. This will transform the @@ -1174,7 +1273,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ */ cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y); offset.advanceOffset = (FLOAT)x; - /** Y-axis is inverted */ + /* Y-axis is inverted */ offset.ascenderOffset = -(FLOAT)y; area.top = 0; @@ -1200,7 +1299,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ GdiFlush(); - image = _compute_a8_mask (&surface->base); + image = _cairo_compute_glyph_mask (&surface->base, _quality_from_antialias_mode(scaled_font->antialias_mode)); status = (cairo_int_status_t)image->status; if (status) goto FAIL; @@ -1336,8 +1435,70 @@ _cairo_dwrite_has_color_glyphs(void *scaled_font) return ((cairo_dwrite_font_face_t *)dwritesf->base.font_face)->have_color; } -cairo_font_face_t* -cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_face) +/** + * cairo_dwrite_font_face_create_for_dwrite_fontface: + * @dwrite_font_face: A pointer to an #IDWriteFontFace specifying the + * DWrite font to use. + * + * Creates a new font for the DWrite font backend based on a + * DWrite font face. This font can then be used with + * cairo_set_font_face() or cairo_scaled_font_create(). + * + * Here is an example of how this function might be used: + * <informalexample><programlisting><![CDATA[ + * #include <cairo-dwrite.h> + * #include <dwrite.h> + * + * IDWriteFactory* dWriteFactory = NULL; + * HRESULT hr = DWriteCreateFactory( + * DWRITE_FACTORY_TYPE_SHARED, + * __uuidof(IDWriteFactory), + * reinterpret_cast<IUnknown**>(&dWriteFactory)); + * + * IDWriteFontCollection *systemCollection; + * hr = dWriteFactory->GetSystemFontCollection(&systemCollection); + * + * UINT32 idx; + * BOOL found; + * systemCollection->FindFamilyName(L"Segoe UI Emoji", &idx, &found); + * + * IDWriteFontFamily *family; + * systemCollection->GetFontFamily(idx, &family); + * + * IDWriteFont *dwritefont; + * DWRITE_FONT_WEIGHT weight = DWRITE_FONT_WEIGHT_NORMAL; + * DWRITE_FONT_STYLE style = DWRITE_FONT_STYLE_NORMAL; + * hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &dwritefont); + * + * IDWriteFontFace *dwriteface; + * hr = dwritefont->CreateFontFace(&dwriteface); + * + * cairo_font_face_t *face; + * face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface); + * cairo_set_font_face(cr, face); + * cairo_set_font_size(cr, 70); + * cairo_move_to(cr, 100, 100); + * 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. + * + * Since: 1.18 + **/ +cairo_font_face_t * +cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_face) { IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face); // Must do malloc and not C++ new, since Cairo frees this. @@ -1350,6 +1511,8 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac dwriteface->AddRef(); face->dwriteface = dwriteface; face->have_color = false; + face->rendering_params = NULL; + face->measuring_mode = DWRITE_MEASURING_MODE_NATURAL; /* Ensure IDWriteFactory4 is available before enabling color fonts */ if (DWriteFactory::Instance4()) { @@ -1367,35 +1530,77 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac return font_face; } -void -cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force) +/** + * cairo_dwrite_font_face_get_rendering_params: + * @font_face: The #cairo_dwrite_font_face_t object to query + * + * Gets the #IDWriteRenderingParams object of @font_face. + * + * Return value: the #IDWriteRenderingParams object or %NULL if none. + * + * Since: 1.18 + **/ +IDWriteRenderingParams * +cairo_dwrite_font_face_get_rendering_params (cairo_font_face_t *font_face) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); - if (force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL) { - font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC; - } else if (!force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) { - font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL; - } + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + return dwface->rendering_params; } -cairo_bool_t -cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font) +/** + * cairo_dwrite_font_face_set_rendering_params: + * @font_face: The #cairo_dwrite_font_face_t object to modify + * @params: The #IDWriteRenderingParams object + * + * Sets the #IDWriteRenderingParams object to @font_face. + * This #IDWriteRenderingParams is used to render glyphs if default values of font options are used. + * If non-defalut values of font options are specified when creating a #cairo_scaled_font_t, + * cairo creates a new #IDWriteRenderingParams object for the #cairo_scaled_font_t object by overwriting the corresponding parameters. + * + * Since: 1.18 + **/ +void +cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *params) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); - return font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC; + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + if (dwface->rendering_params) + dwface->rendering_params->Release(); + dwface->rendering_params = params; + if (dwface->rendering_params) + dwface->rendering_params->AddRef(); } -void -cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, - int geometry, int mode) +/** + * cairo_dwrite_font_face_get_measuring_mode: + * @font_face: The #cairo_dwrite_font_face_t object to query + * + * Gets the #DWRITE_MEASURING_MODE enum of @font_face. + * + * Return value: The #DWRITE_MEASURING_MODE enum of @font_face. + * + * Since: 1.18 + **/ +DWRITE_MEASURING_MODE +cairo_dwrite_font_face_get_measuring_mode (cairo_font_face_t *font_face) { - DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode); + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + return dwface->measuring_mode; } -int -cairo_dwrite_get_cleartype_rendering_mode() +/** + * cairo_dwrite_font_face_set_measuring_mode: + * @font_face: The #cairo_dwrite_font_face_t object to modify + * @mode: The #DWRITE_MEASURING_MODE enum. + * + * Sets the #DWRITE_MEASURING_MODE enum to @font_face. + * + * Since: 1.18 + **/ +void +cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode) { - return DWriteFactory::GetClearTypeRenderingMode(); + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + dwface->measuring_mode = mode; } static cairo_int_status_t @@ -1411,9 +1616,6 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, RefPtr<IDWriteBitmapRenderTarget> rt; HRESULT hr; - cairo_dwrite_scaled_font_t::TextRenderingState renderingState = - scaled_font->rendering_mode; - hr = gdiInterop->CreateBitmapRenderTarget(surface->dc, area.right - area.left, area.bottom - area.top, @@ -1427,22 +1629,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, } } - if ((renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL || - renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) - /* && !surface->base.permit_subpixel_antialiasing */ ) { - renderingState = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE; - RefPtr<IDWriteBitmapRenderTarget1> rt1; - hr = rt->QueryInterface(&rt1); - - if (SUCCEEDED(hr) && rt1) { - rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE); - } - } - - RefPtr<IDWriteRenderingParams> params = - DWriteFactory::RenderingParams(renderingState); - - /** + /* * We set the number of pixels per DIP to 1.0. This is because we always want * to draw in device pixels, and not device independent pixels. On high DPI * systems this value will be higher than 1.0 and automatically upscale @@ -1450,8 +1637,15 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, */ rt->SetPixelsPerDip(1.0); + float x = 0, y = 0; if (transform) { - rt->SetCurrentTransform(transform); + DWRITE_MATRIX matrix = *transform; + matrix.dx -= area.left; + matrix.dy -= area.top; + rt->SetCurrentTransform(&matrix); + } else { + x = (float) -area.left; + y = (float) -area.top; } BitBlt(rt->GetMemoryDC(), 0, 0, @@ -1459,17 +1653,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, surface->dc, area.left, area.top, SRCCOPY | NOMIRRORBITMAP); - DWRITE_MEASURING_MODE measureMode; - switch (renderingState) { - case cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC: - case cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE: - measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; - break; - default: - measureMode = DWRITE_MEASURING_MODE_NATURAL; - break; - } - rt->DrawGlyphRun(0, 0, measureMode, run, params, color); + rt->DrawGlyphRun(x, y, scaled_font->measuring_mode, run, scaled_font->rendering_params, color); BitBlt(surface->dc, area.left, area.top, area.right - area.left, area.bottom - area.top, @@ -1505,6 +1689,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; + float x = 0, y = 0; if (transform) { rt->SetTransform(D2D1::Matrix3x2F(transform->m11, transform->m12, @@ -1553,15 +1738,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) return CAIRO_INT_STATUS_UNSUPPORTED; - /* If we have a fallback mask clip set on the dst, we have - * to go through the fallback path */ - if (!_cairo_surface_is_win32_printing (&dst->base)) { - if (clip != NULL) - _cairo_win32_display_surface_set_clip (to_win32_display_surface (dst), clip); - else - _cairo_win32_display_surface_unset_clip (to_win32_display_surface (dst)); - } - /* It is vital that dx values for dxy_buf are calculated from the delta of * _logical_ x coordinates (not user x coordinates) or else the sum of all * previous dx values may start to diverge from the current glyph's x @@ -1576,96 +1752,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets); BOOL transform = FALSE; - /* Needed to calculate bounding box for efficient blitting */ - INT32 smallestX = INT_MAX; - INT32 largestX = 0; - INT32 smallestY = INT_MAX; - INT32 largestY = 0; - for (int i = 0; i < num_glyphs; i++) { - if (glyphs[i].x < smallestX) { - smallestX = (INT32)glyphs[i].x; - } - if (glyphs[i].x > largestX) { - largestX = (INT32)glyphs[i].x; - } - if (glyphs[i].y < smallestY) { - smallestY = (INT32)glyphs[i].y; - } - if (glyphs[i].y > largestY) { - largestY = (INT32)glyphs[i].y; - } - } - /** - * Here we try to get a rough estimate of the area that this glyph run will - * cover on the surface. Since we use GDI interop to draw we will be copying - * data around the size of the area of the surface that we map. We will want - * to map an area as small as possible to prevent large surfaces to be - * copied around. We take the X/Y-size of the font as margin on the left/top - * twice the X/Y-size of the font as margin on the right/bottom. - * This should always cover the entire area where the glyphs are. - */ - RECT fontArea; - fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx); - fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2); - fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy); - fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2); - if (fontArea.left < 0) - fontArea.left = 0; - if (fontArea.top < 0) - fontArea.top = 0; - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.right <= fontArea.left || - fontArea.bottom <= fontArea.top) { - return CAIRO_INT_STATUS_SUCCESS; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } - - run.bidiLevel = 0; - run.fontFace = dwriteff->dwriteface; - run.isSideways = FALSE; - if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 && - dwritesf->mat.xx == scaled_font->font_matrix.xx && - dwritesf->mat.yy == scaled_font->font_matrix.yy) { - - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - // Since we will multiply by our ctm matrix later for rotation effects - // and such, adjust positions by the inverse matrix now. - offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y); - offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left); - advances[i] = 0.0; - } - run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy; - } else { - transform = TRUE; - // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs - const double EPSILON = 0.0001; - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - double x = glyphs[i].x - fontArea.left + EPSILON; - double y = glyphs[i].y - fontArea.top; - cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y); - /** - * Since we will multiply by our ctm matrix later for rotation effects - * and such, adjust positions by the inverse matrix now. The Y-axis - * is inverted so the offset becomes negative. - */ - offsets[i].ascenderOffset = -(FLOAT)y; - offsets[i].advanceOffset = (FLOAT)x; - advances[i] = 0.0; - } - run.fontEmSize = 1.0f; - } + _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform); cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source; COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8, @@ -1681,18 +1768,31 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, mat = NULL; } - RECT area; - area.left = dst->extents.x; - area.top = dst->extents.y; - area.right = area.left + dst->extents.width; - area.bottom = area.top + dst->extents.height; + RefPtr<IDWriteGlyphRunAnalysis> runAnalysis; + HRESULT hr = DWriteFactory::Instance()-> + CreateGlyphRunAnalysis(&run, 1, mat, + DWRITE_RENDERING_MODE_ALIASED, + dwritesf->measuring_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &runAnalysis); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + RECT fontArea; + hr = runAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1, &fontArea); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + InflateRect(&fontArea, 1, 1); + /* Needed to calculate bounding box for efficient blitting */ + RECT copyArea, dstArea = { 0, 0, dst->extents.width, dst->extents.height }; + IntersectRect(©Area, &fontArea, &dstArea); #ifdef CAIRO_TRY_D2D_TO_GDI status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst, mat, &run, color, - fontArea); + copyArea); if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) { #endif @@ -1701,7 +1801,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, &run, color, dwritesf, - fontArea); + copyArea); #ifdef CAIRO_TRY_D2D_TO_GDI } @@ -1710,59 +1810,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, return status; } -#define ENHANCED_CONTRAST_REGISTRY_KEY \ - HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel" - -void -DWriteFactory::CreateRenderingParams() -{ - if (!Instance()) { - return; - } - - Instance()->CreateRenderingParams(&mDefaultRenderingParams); - - // For EnhancedContrast, we override the default if the user has not set it - // in the registry (by using the ClearType Tuner). - FLOAT contrast; - if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) { - contrast = mEnhancedContrast; - } else { - HKEY hKey; - if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY, - 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - contrast = mDefaultRenderingParams->GetEnhancedContrast(); - RegCloseKey(hKey); - } else { - contrast = 1.0; - } - } - - // For parameters that have not been explicitly set via the SetRenderingParams API, - // we copy values from default params (or our overridden value for contrast) - FLOAT gamma = - mGamma >= 1.0 && mGamma <= 2.2 ? - mGamma : mDefaultRenderingParams->GetGamma(); - FLOAT clearTypeLevel = - mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? - mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel(); - DWRITE_PIXEL_GEOMETRY pixelGeometry = - mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ? - (DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry(); - DWRITE_RENDERING_MODE renderingMode = - mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ? - (DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode(); - - Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel, - pixelGeometry, renderingMode, - &mCustomClearTypeRenderingParams); - - Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel, - pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, - &mForceGDIClassicRenderingParams); -} - /* 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, @@ -1866,6 +1913,16 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ } cairo_font_face_t *face = cairo_scaled_font_get_font_face (scaled_font); + if (cairo_font_face_status (face) == CAIRO_STATUS_SUCCESS && + cairo_font_face_get_type (face) == CAIRO_FONT_TYPE_TOY) + { + face = ((cairo_toy_font_face_t *)face)->impl_face; + } + + if (face == NULL || cairo_font_face_get_type (face) != CAIRO_FONT_TYPE_DWRITE) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t*>(face); RefPtr<IDWriteGdiInterop> gdiInterop; @@ -1897,6 +1954,7 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ cairo_scaled_font_get_ctm (scaled_font, &ctm); cairo_font_options_t options; + _cairo_font_options_init_default (&options); cairo_scaled_font_get_font_options (scaled_font, &options); cairo_scaled_font_t *font = cairo_scaled_font_create (win32_face, |