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

Reply via email to