vcl/inc/skia/win/gdiimpl.hxx | 2 +- vcl/inc/win/DWriteTextRenderer.hxx | 2 +- vcl/inc/win/salgdi.h | 3 +++ vcl/skia/win/gdiimpl.cxx | 33 +++++++++++---------------------- vcl/win/gdi/DWriteTextRenderer.cxx | 26 ++++++++++++-------------- vcl/win/gdi/salfont.cxx | 28 ++++++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 38 deletions(-)
New commits: commit a80239ede3236c84d7a05d0fbc0f299811fee6c0 Author: Khaled Hosny <kha...@aliftype.com> AuthorDate: Sat Nov 19 03:03:15 2022 +0200 Commit: خالد حسني <kha...@aliftype.com> CommitDate: Sat Nov 19 12:44:10 2022 +0100 vcl: move creating DWFontFace to WinFontFace Change-Id: Ie0e94787d962eaec7753ae50d548ad8655dbc209 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142957 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@aliftype.com> diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 92f873ca7d43..c5b12d08811a 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -63,7 +63,7 @@ public: protected: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; - static sk_sp<SkTypeface> createDirectWriteTypeface(HDC hdc, HFONT hfont); + static sk_sp<SkTypeface> createDirectWriteTypeface(const WinFontInstance* pWinFont); static void initFontInfo(); inline static sal::systools::COMReference<IDWriteFontSetBuilder> dwriteFontSetBuilder; inline static sal::systools::COMReference<IDWriteFontCollection1> dwritePrivateCollection; diff --git a/vcl/inc/win/DWriteTextRenderer.hxx b/vcl/inc/win/DWriteTextRenderer.hxx index 5f0dc35ddd58..b2d685b20365 100644 --- a/vcl/inc/win/DWriteTextRenderer.hxx +++ b/vcl/inc/win/DWriteTextRenderer.hxx @@ -60,7 +60,7 @@ private: D2DWriteTextOutRenderer(const D2DWriteTextOutRenderer &) = delete; D2DWriteTextOutRenderer & operator = (const D2DWriteTextOutRenderer &) = delete; - bool GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** ppFontFace, float * lfSize) const; + IDWriteFontFace* GetDWriteFace(const WinFontInstance& rWinFont, float * lfSize) const; bool performRender(GenericSalLayout const &rLayout, SalGraphics &rGraphics, HDC hDC, bool& bRetry, bool bRenderingModeNatural); ID2D1Factory * mpD2DFactory; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index db00ff03455a..c21c36db2dec 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -72,6 +72,8 @@ public: BYTE GetCharSet() const { return meWinCharSet; } BYTE GetPitchAndFamily() const { return mnPitchAndFamily; } + IDWriteFontFace* GetDWFontFace() const; + virtual hb_blob_t* GetHbTable(hb_tag_t nTag) const override; private: @@ -80,6 +82,7 @@ private: BYTE meWinCharSet; BYTE mnPitchAndFamily; LOGFONTW maLogFont; + mutable sal::systools::COMReference<IDWriteFontFace> mxDWFontFace; }; /** Class that creates (and destroys) a compatible Device Context. diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 74bc3cce5ec5..a9df26cb53a1 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -121,12 +121,12 @@ bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, C return true; } -sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFONT hfont) try +sk_sp<SkTypeface> +WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const WinFontInstance* pWinFont) try { using sal::systools::ThrowIfFailed; IDWriteFactory* dwriteFactory; - IDWriteGdiInterop* dwriteGdiInterop; - WinSalGraphics::getDWriteFactory(&dwriteFactory, &dwriteGdiInterop); + WinSalGraphics::getDWriteFactory(&dwriteFactory); if (!dwriteDone) { dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory); @@ -135,30 +135,20 @@ sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO if (!dwriteFontMgr) return nullptr; - // tdf#137122: We need to get the exact same font as HFONT refers to, - // since VCL core computes things like glyph ids based on that, and getting - // a different font could lead to mismatches (e.g. if there's a slightly - // different version of the same font installed system-wide). - // For that CreateFromFaceFromHdc() is necessary. The simpler - // CreateFontFromLOGFONT() seems to search for the best matching font, - // which may not be the exact font. - sal::systools::COMReference<IDWriteFontFace> fontFace; - { - comphelper::ScopeGuard g( - [ hdc, oldFont(SelectFont(hdc, hfont)) ] { SelectFont(hdc, oldFont); }); - ThrowIfFailed(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, &fontFace), SAL_WHERE); - } + IDWriteFontFace* fontFace = pWinFont->GetFontFace()->GetDWFontFace(); + if (!fontFace) + return nullptr; sal::systools::COMReference<IDWriteFontCollection> collection; ThrowIfFailed(dwriteFactory->GetSystemFontCollection(&collection), SAL_WHERE); sal::systools::COMReference<IDWriteFont> font; // As said above, this fails for our fonts. - if (FAILED(collection->GetFontFromFontFace(fontFace.get(), &font))) + if (FAILED(collection->GetFontFromFontFace(fontFace, &font))) { // If not found in system collection, try our private font collection. // If that's not possible we'll fall back to Skia's GDI-based font rendering. if (!dwritePrivateCollection - || FAILED(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font))) + || FAILED(dwritePrivateCollection->GetFontFromFontFace(fontFace, &font))) { // Our private fonts are installed using AddFontResourceExW( FR_PRIVATE ) // and that does not make them available to the DWrite system font @@ -206,14 +196,13 @@ sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO ThrowIfFailed(dwriteFactory3->CreateFontCollectionFromFontSet(fontSet.get(), &dwritePrivateCollection), SAL_WHERE); - ThrowIfFailed(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font), - SAL_WHERE); + ThrowIfFailed(dwritePrivateCollection->GetFontFromFontFace(fontFace, &font), SAL_WHERE); } } sal::systools::COMReference<IDWriteFontFamily> fontFamily; ThrowIfFailed(font->GetFontFamily(&fontFamily), SAL_WHERE); return sk_sp<SkTypeface>( - SkCreateTypefaceDirectWrite(dwriteFontMgr, fontFace.get(), font.get(), fontFamily.get())); + SkCreateTypefaceDirectWrite(dwriteFontMgr, fontFace, font.get(), fontFamily.get())); } catch (const sal::systools::ComError& e) { @@ -240,7 +229,7 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) sk_sp<SkTypeface> typeface = pWinFont->GetSkiaTypeface(); if (!typeface) { - typeface = createDirectWriteTypeface(mWinParent.getHDC(), hLayoutFont); + typeface = createDirectWriteTypeface(pWinFont); bool dwrite = true; if (!typeface) // fall back to GDI text rendering { diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx index 1e44d95ad2cb..c09eeb410199 100644 --- a/vcl/win/gdi/DWriteTextRenderer.cxx +++ b/vcl/win/gdi/DWriteTextRenderer.cxx @@ -108,7 +108,7 @@ D2DWriteTextOutRenderer::D2DWriteTextOutRenderer(bool bRenderingModeNatural) mbRenderingModeNatural(bRenderingModeNatural), meTextAntiAliasMode(D2DTextAntiAliasMode::Default) { - WinSalGraphics::getDWriteFactory(&mpDWriteFactory, &mpGdiInterop); + WinSalGraphics::getDWriteFactory(&mpDWriteFactory); HRESULT hr = S_OK; hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), nullptr, reinterpret_cast<void **>(&mpD2DFactory)); if (SUCCEEDED(hr)) @@ -217,14 +217,14 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa return ExTextOutRenderer()(rLayout, rGraphics, hDC, bRenderingModeNatural); } - IDWriteFontFace* pFontFace; - float lfEmHeight = 0; - if (!GetDWriteFaceFromHDC(hDC, &pFontFace, &lfEmHeight)) - return false; - const WinFontInstance& rWinFont = static_cast<const WinFontInstance&>(rLayout.GetFont()); float fHScale = rWinFont.getHScale(); + float lfEmHeight = 0; + IDWriteFontFace* pFontFace = GetDWriteFace(rWinFont, &lfEmHeight); + if (!pFontFace) + return false; + tools::Rectangle bounds; bool succeeded = rLayout.GetBoundRect(bounds); if (succeeded) @@ -276,8 +276,6 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa if (pBrush) pBrush->Release(); - pFontFace->Release(); - if (hr == D2DERR_RECREATE_TARGET) { CreateRenderTarget(bRenderingModeNatural); @@ -287,14 +285,14 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa return succeeded; } -bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** ppFontFace, float * lfSize) const +IDWriteFontFace* D2DWriteTextOutRenderer::GetDWriteFace(const WinFontInstance& rWinFont, + float* lfSize) const { - bool succeeded = SUCCEEDED(CHECKHR(mpGdiInterop->CreateFontFaceFromHdc(hDC, ppFontFace))); - - if (succeeded) + auto pFontFace = rWinFont.GetFontFace()->GetDWFontFace(); + if (pFontFace) { LOGFONTW aLogFont; - HFONT hFont = static_cast<HFONT>(::GetCurrentObject(hDC, OBJ_FONT)); + HFONT hFont = rWinFont.GetHFONT(); GetObjectW(hFont, sizeof(LOGFONTW), &aLogFont); float dpix, dpiy; @@ -305,7 +303,7 @@ bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** p *lfSize *= -1; } - return succeeded; + return pFontFace; } WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget, float fHScale, diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index c41d0427f5cb..1db4f0d8c2b0 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -51,6 +51,7 @@ #include <vcl/metric.hxx> #include <vcl/fontcharmap.hxx> #include <comphelper/scopeguard.hxx> +#include <comphelper/windowserrorstring.hxx> #include <font/FontSelectPattern.hxx> #include <font/PhysicalFontCollection.hxx> @@ -531,6 +532,33 @@ rtl::Reference<LogicalFontInstance> WinFontFace::CreateFontInstance(const vcl::f return new WinFontInstance(*this, rFSD); } +IDWriteFontFace* WinFontFace::GetDWFontFace() const +{ + if (!mxDWFontFace) + { + IDWriteGdiInterop* pDWriteGdiInterop; + WinSalGraphics::getDWriteFactory(nullptr, &pDWriteGdiInterop); + + HDC hDC(::GetDC(nullptr)); + HFONT hFont = ::CreateFontIndirectW(&maLogFont); + HFONT hOldFont = ::SelectFont(hDC, hFont); + + HRESULT hr = pDWriteGdiInterop->CreateFontFaceFromHdc(hDC, &mxDWFontFace); + if (FAILED(hr)) + { + SAL_WARN("vcl.fonts", "HRESULT 0x" << OUString::number(hr, 16) << ": " + << WindowsErrorStringFromHRESULT(hr)); + mxDWFontFace = nullptr; + } + + ::SelectFont(hDC, hOldFont); + ::DeleteFont(hFont); + ::ReleaseDC(nullptr, hDC); + } + + return mxDWFontFace; +} + namespace { struct BlobReference