diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt index 744f8aef2..6a11c9b8a 100644 --- a/doc/public/cairo-sections.txt +++ b/doc/public/cairo-sections.txt @@ -30,6 +30,10 @@ cairo_win32_scaled_font_get_device_to_logical cairo-dwrite-fonts CAIRO_HAS_DWRITE_FONT cairo_dwrite_font_face_create_for_dwrite_fontface +cairo_dwrite_font_face_get_rendering_params +cairo_dwrite_font_face_set_rendering_params +cairo_dwrite_font_face_get_measuring_mode +cairo_dwrite_font_face_set_measuring_mode
diff --git a/src/cairo-dwrite.h b/src/cairo-dwrite.h index f512c3152..630fcf280 100644 --- a/src/cairo-dwrite.h +++ b/src/cairo-dwrite.h @@ -47,6 +47,18 @@ CAIRO_BEGIN_DECLS cairo_public cairo_font_face_t * cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_face); +cairo_public IDWriteRenderingParams * +cairo_dwrite_font_face_get_rendering_params (cairo_font_face_t *font_face); + +cairo_public void +cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *param); + +cairo_public DWRITE_MEASURING_MODE +cairo_dwrite_font_face_get_measuring_mode (cairo_font_face_t *font_face); + +cairo_public void +cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode); + CAIRO_END_DECLS #else /* __cplusplus */ diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index 288aec1d4..1d84fc047 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -217,13 +217,6 @@ RefPtr DWriteFactory::mFactoryInstance4; RefPtr WICImagingFactory::mFactoryInstance; RefPtr DWriteFactory::mSystemCollection; RefPtr DWriteFactory::mDefaultRenderingParams; -RefPtr DWriteFactory::mCustomClearTypeRenderingParams; -RefPtr 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 D2DFactory::mFactoryInstance; RefPtr D2DFactory::mRenderTarget; @@ -411,6 +404,8 @@ _cairo_dwrite_font_face_destroy (void *font_face) cairo_dwrite_font_face_t *dwrite_font_face = static_cast(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; } @@ -557,10 +552,28 @@ _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); + + dwrite_font->rendering_params = NULL; + if (font_face->rendering_params) { + dwrite_font->rendering_params = font_face->rendering_params; + dwrite_font->rendering_params->AddRef(); + } + dwrite_font->measuring_mode = font_face->measuring_mode; + 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; @@ -568,15 +581,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- @@ -587,12 +593,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; } @@ -608,10 +612,6 @@ _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; - return _cairo_scaled_font_set_metrics (*font, &extents); } @@ -619,6 +619,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(scaled_font); + if (dwrite_font->rendering_params) + dwrite_font->rendering_params->Release(); } static cairo_int_status_t @@ -680,17 +683,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; @@ -945,7 +961,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); @@ -1034,7 +1050,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; @@ -1045,7 +1061,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: @@ -1073,7 +1089,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s &color_run->glyphRun, color_run->glyphRunDescription, color_brush, - DWRITE_MEASURING_MODE_NATURAL); + dwrite_font_face->measuring_mode); case DWRITE_GLYPH_IMAGE_FORMATS_NONE: break; } @@ -1428,6 +1444,8 @@ cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_ 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()) { @@ -1445,35 +1463,74 @@ cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_ return font_face; } +/** + * 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_font_face_t *dwface = reinterpret_cast(font_face); + return dwface->rendering_params; +} + +/** + * 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. + * + * Since: 1.18 + **/ void -cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force) +cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *params) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast(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(font_face); + if (dwface->rendering_params) + dwface->rendering_params->Release(); + dwface->rendering_params = params; + if (dwface->rendering_params) + dwface->rendering_params->AddRef(); } -cairo_bool_t -cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font) +/** + * 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) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast(dwrite_scaled_font); - return font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC; + cairo_dwrite_font_face_t *dwface = reinterpret_cast(font_face); + return dwface->measuring_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_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, - int geometry, int mode) +cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode) { - DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode); -} - -int -cairo_dwrite_get_cleartype_rendering_mode() -{ - return DWriteFactory::GetClearTypeRenderingMode(); + cairo_dwrite_font_face_t *dwface = reinterpret_cast(font_face); + dwface->measuring_mode = mode; } static cairo_int_status_t @@ -1489,9 +1546,6 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, RefPtr 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, @@ -1505,20 +1559,11 @@ _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 rt1; - hr = rt->QueryInterface(&rt1); - - if (SUCCEEDED(hr) && rt1) { - rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE); - } - } - - RefPtr params = - DWriteFactory::RenderingParams(renderingState); + IDWriteRenderingParams *params; + if (scaled_font->rendering_params) + params = scaled_font->rendering_params; + else + params = DWriteFactory::DefaultRenderingParams(); /** * We set the number of pixels per DIP to 1.0. This is because we always want @@ -1537,17 +1582,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(0, 0, scaled_font->measuring_mode, run, params, color); BitBlt(surface->dc, area.left, area.top, area.right - area.left, area.bottom - area.top, @@ -1788,59 +1823,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, diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp index 92b096857..4857739ea 100644 --- a/src/win32/cairo-dwrite-private.hpp +++ b/src/win32/cairo-dwrite-private.hpp @@ -70,14 +70,8 @@ struct _cairo_dwrite_scaled_font { cairo_matrix_t mat; cairo_matrix_t mat_inverse; cairo_antialias_t antialias_mode; + IDWriteRenderingParams *rendering_params; DWRITE_MEASURING_MODE measuring_mode; - enum TextRenderingState { - TEXT_RENDERING_UNINITIALIZED, - TEXT_RENDERING_NO_CLEARTYPE, - TEXT_RENDERING_NORMAL, - TEXT_RENDERING_GDI_CLASSIC - }; - TextRenderingState rendering_mode; }; typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t; @@ -145,69 +139,21 @@ public: return family; } - static RefPtr RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode) + static RefPtr DefaultRenderingParams() { - if (!mDefaultRenderingParams || - !mForceGDIClassicRenderingParams || - !mCustomClearTypeRenderingParams) - { - CreateRenderingParams(); + if (!mDefaultRenderingParams) { + if (Instance()) { + Instance()->CreateRenderingParams(&mDefaultRenderingParams); + } } - RefPtr 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) { - params = mForceGDIClassicRenderingParams; - } else { - params = mCustomClearTypeRenderingParams; - } - return params; - } - - static void SetRenderingParams(FLOAT aGamma, - FLOAT aEnhancedContrast, - FLOAT aClearTypeLevel, - int aPixelGeometry, - int aRenderingMode) - { - mGamma = aGamma; - mEnhancedContrast = aEnhancedContrast; - mClearTypeLevel = aClearTypeLevel; - mPixelGeometry = aPixelGeometry; - mRenderingMode = aRenderingMode; - // discard any current RenderingParams objects - if (mCustomClearTypeRenderingParams) { - mCustomClearTypeRenderingParams->Release(); - mCustomClearTypeRenderingParams = NULL; - } - if (mForceGDIClassicRenderingParams) { - mForceGDIClassicRenderingParams->Release(); - mForceGDIClassicRenderingParams = NULL; - } - if (mDefaultRenderingParams) { - mDefaultRenderingParams->Release(); - mDefaultRenderingParams = NULL; - } - } - - static int GetClearTypeRenderingMode() { - return mRenderingMode; + return mDefaultRenderingParams; } private: - static void CreateRenderingParams(); - static RefPtr mFactoryInstance; static RefPtr mFactoryInstance4; static RefPtr mSystemCollection; static RefPtr mDefaultRenderingParams; - static RefPtr mCustomClearTypeRenderingParams; - static RefPtr mForceGDIClassicRenderingParams; - static FLOAT mGamma; - static FLOAT mEnhancedContrast; - static FLOAT mClearTypeLevel; - static int mPixelGeometry; - static int mRenderingMode; }; class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN @@ -251,5 +197,7 @@ struct _cairo_dwrite_font_face { cairo_font_face_t base; IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd. */ cairo_bool_t have_color; + IDWriteRenderingParams *rendering_params; /* Can't use RefPtr because this struct is malloc'd. */ + DWRITE_MEASURING_MODE measuring_mode; }; typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;