vcl/inc/win/salgdi.h      |    2 
 vcl/inc/win/winlayout.hxx |    4 -
 vcl/win/gdi/salfont.cxx   |  129 ++++++++++++++++++----------------------------
 vcl/win/gdi/winlayout.cxx |    3 -
 4 files changed, 54 insertions(+), 84 deletions(-)

New commits:
commit c2a581ffc1f4e3888c5c243932b71c3d96e8ba8f
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Mon Nov 22 06:32:55 2021 +0100
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Tue Nov 23 19:29:38 2021 +0100

    tdf#62812 WIN use a compatible DC for font funcs
    
    All these function work on a temporary font. It's not clear, if
    the CreateCompatibleDC is actually needed and if the ScopedFontDC
    could actually just use the SalGraphics DC and restore its HFONT,
    but this at least now works as expected.
    
    A later patch can just drop the CreateCompatibleDC and DeleteDC
    calls.
    
    Change-Id: I6e86d660e69a58fa2eab89ece80c61e2635fc792
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125652
    Tested-by: Julien Nabet <serval2...@yahoo.fr>
    Tested-by: Jenkins
    Reviewed-by: Julien Nabet <serval2...@yahoo.fr>
    Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de>

diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 974c58ae81ad..8c6c1adcdbed 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -181,7 +181,7 @@ private:
     void DeInitGraphics();
 
 public:
-    HFONT ImplDoSetFont(vcl::font::FontSelectPattern const & i_rFont, const 
vcl::font::PhysicalFontFace * i_pFontFace, HFONT& o_rOldFont);
+    HFONT ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern const & i_rFont, 
const vcl::font::PhysicalFontFace * i_pFontFace, HFONT& o_rOldFont);
 
     HDC getHDC() const { return mhLocalDC; }
     // NOTE: this doesn't transfer ownership! See class comment.
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 93aa0a3d00de..29bccf5acf4f 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -45,10 +45,6 @@ public:
     HFONT GetHFONT() const { return m_hFont; }
     float GetScale() const { return m_fScale; }
 
-    // Prevent deletion of the HFONT in the WinFontInstance destructor
-    // Used for the ScopedFont handling
-    void SetHFONT(HFONT hFont) { m_hFont = hFont; }
-
     const WinFontFace * GetFontFace() const { return static_cast<const 
WinFontFace *>(LogicalFontInstance::GetFontFace()); }
     WinFontFace * GetFontFace() { return static_cast<WinFontFace 
*>(LogicalFontInstance::GetFontFace()); }
 
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index f1c621cd5947..7e3197807d10 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -811,7 +811,7 @@ void ImplGetLogFontFromFontSelect( const 
vcl::font::FontSelectPattern& rFont,
 
 }
 
-HFONT WinSalGraphics::ImplDoSetFont(vcl::font::FontSelectPattern const & 
i_rFont,
+HFONT WinSalGraphics::ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern 
const & i_rFont,
                                     const vcl::font::PhysicalFontFace * 
i_pFontFace,
                                     HFONT& o_rOldFont)
 {
@@ -834,17 +834,17 @@ HFONT 
WinSalGraphics::ImplDoSetFont(vcl::font::FontSelectPattern const & i_rFont
         // "PRB: Fonts Not Drawn Antialiased on Device Context for DirectDraw 
Surface"
         SelectFont( hdcScreen, SelectFont( hdcScreen , hNewFont ) );
     }
-    o_rOldFont = ::SelectFont( getHDC(), hNewFont );
+    o_rOldFont = ::SelectFont(hDC, hNewFont);
 
     TEXTMETRICW aTextMetricW;
-    if( !::GetTextMetricsW( getHDC(), &aTextMetricW ) )
+    if (!::GetTextMetricsW(hDC, &aTextMetricW))
     {
         // the selected font doesn't work => try a replacement
         // TODO: use its font fallback instead
         lstrcpynW( aLogFont.lfFaceName, L"Courier New", 12 );
         aLogFont.lfPitchAndFamily = FIXED_PITCH;
         HFONT hNewFont2 = CreateFontIndirectW( &aLogFont );
-        SelectFont( getHDC(), hNewFont2 );
+        SelectFont(hDC, hNewFont2);
         DeleteFont( hNewFont );
         hNewFont = hNewFont2;
     }
@@ -857,8 +857,6 @@ HFONT 
WinSalGraphics::ImplDoSetFont(vcl::font::FontSelectPattern const & i_rFont
 
 void WinSalGraphics::SetFont(LogicalFontInstance* pFont, int nFallbackLevel)
 {
-    // check that we don't change the first font while ScopedFont has replaced 
HFONT
-    assert(!mpWinFontEntry[0].is() || nFallbackLevel != 0 || 
mpWinFontEntry[0]->GetHFONT());
     assert(nFallbackLevel >= 0 && nFallbackLevel < MAX_FALLBACK);
 
     // return early if there is no new font
@@ -1470,40 +1468,40 @@ bool WinFontInstance::GetGlyphOutline(sal_GlyphId nId, 
basegfx::B2DPolyPolygon&
     return true;
 }
 
-class ScopedFont
-{
-public:
-    explicit ScopedFont(WinSalGraphics & rData);
-
-    ~ScopedFont();
-
-private:
-    WinSalGraphics & m_rData;
-    HFONT m_hOrigFont;
-};
+namespace {
 
-ScopedFont::ScopedFont(WinSalGraphics & rData): m_rData(rData), 
m_hOrigFont(nullptr)
+class ScopedFontHDC final
 {
-    if (m_rData.mpWinFontEntry[0])
+public:
+    explicit ScopedFontHDC(WinSalGraphics& rGraphics, const 
vcl::font::PhysicalFontFace& rFontFace)
+        : m_hDC(nullptr)
+        , m_hOrigFont(nullptr)
+        // use height=1000 for easier debugging (to match psprint's font units)
+        , m_aFSP(rFontFace, Size(0,1000), 1000.0, 0, false)
     {
-        m_hOrigFont = m_rData.mpWinFontEntry[0]->GetHFONT();
-        m_rData.mpWinFontEntry[0]->SetHFONT(nullptr);
+        m_hDC = CreateCompatibleDC(rGraphics.getHDC());
+        if (!m_hDC)
+            return;
+
+        rGraphics.ImplDoSetFont(m_hDC, m_aFSP, &rFontFace, m_hOrigFont);
     }
-}
 
-ScopedFont::~ScopedFont()
-{
-    if( m_hOrigFont )
+    ~ScopedFontHDC()
     {
-        // restore original font, destroy temporary font
-        HFONT hTempFont = m_rData.mpWinFontEntry[0]->GetHFONT();
-        m_rData.mpWinFontEntry[0]->SetHFONT(m_hOrigFont);
-        SelectObject( m_rData.getHDC(), m_hOrigFont );
-        DeleteObject( hTempFont );
+        if (m_hOrigFont)
+            ::DeleteFont(SelectFont(m_hDC, m_hOrigFont));
+        if (m_hDC)
+            DeleteDC(m_hDC);
     }
-}
 
-namespace {
+    HDC hdc() const { return m_hDC; }
+    const vcl::font::FontSelectPattern& fsp() const { return m_aFSP; }
+
+private:
+    vcl::font::FontSelectPattern m_aFSP;
+    HDC m_hDC;
+    HFONT m_hOrigFont;
+};
 
 class ScopedTrueTypeFont
 {
@@ -1539,25 +1537,16 @@ bool WinSalGraphics::CreateFontSubset( const OUString& 
rToFile,
     const vcl::font::PhysicalFontFace* pFont, const sal_GlyphId* pGlyphIds, 
const sal_uInt8* pEncoding,
     sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo )
 {
-    // TODO: use more of the central font-subsetting code, move stuff there if 
needed
-
-    // create matching FontSelectPattern
-    // we need just enough to get to the font file data
-    // use height=1000 for easier debugging (to match psprint's font units)
-    vcl::font::FontSelectPattern aIFSD( *pFont, Size(0,1000), 1000.0, 0, false 
);
-
-    // TODO: much better solution: move SetFont and restoration of old font to 
caller
-    ScopedFont aOldFont(*this);
-    HFONT hOldFont = nullptr;
-    ImplDoSetFont(aIFSD, pFont, hOldFont);
-
-    WinFontFace const * pWinFontData = static_cast<WinFontFace const *>(pFont);
+    ScopedFontHDC aScopedFontHDC(*this, *pFont);
+    HDC hDC = aScopedFontHDC.hdc();
+    if (!hDC)
+        return false;
 
 #if OSL_DEBUG_LEVEL > 1
     // get font metrics
     TEXTMETRICW aWinMetric;
-    if( !::GetTextMetricsW( getHDC(), &aWinMetric ) )
-        return FALSE;
+    if (!::GetTextMetricsW(hDC, &aWinMetric))
+        return false;
 
     SAL_WARN_IF( (aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "vcl", "cannot 
subset device font" );
     SAL_WARN_IF( !(aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE), "vcl", "can 
only subset TT font" );
@@ -1571,17 +1560,14 @@ bool WinSalGraphics::CreateFontSubset( const OUString& 
rToFile,
 
     // check if the font has a CFF-table
     const DWORD nCffTag = CalcTag( "CFF " );
-    const RawFontData aRawCffData( getHDC(), nCffTag );
+    const RawFontData aRawCffData(hDC, nCffTag);
     if (aRawCffData.get())
-    {
-        pWinFontData->UpdateFromHDC( getHDC() );
         return SalGraphics::CreateCFFfontSubset(aRawCffData.get(), 
aRawCffData.size(), aToFile,
                                                 pGlyphIds, pEncoding, 
pGlyphWidths, nGlyphCount,
                                                 rInfo);
-    }
 
     // get raw font file data
-    const RawFontData xRawFontData( getHDC(), 0 );
+    const RawFontData xRawFontData(hDC, 0);
     if( !xRawFontData.get() )
         return false;
 
@@ -1601,29 +1587,21 @@ bool WinSalGraphics::CreateFontSubset( const OUString& 
rToFile,
     FillFontSubsetInfo(aTTInfo, aPSName, rInfo);
 
     // write subset into destination file
-    return SalGraphics::CreateTTFfontSubset(*aSftTTF.get(), aToFile, 
aIFSD.mbVertical, pGlyphIds,
-                                            pEncoding, pGlyphWidths, 
nGlyphCount);
+    return SalGraphics::CreateTTFfontSubset(*aSftTTF.get(), aToFile, 
aScopedFontHDC.fsp().mbVertical,
+                                            pGlyphIds, pEncoding, 
pGlyphWidths, nGlyphCount);
 }
 
 const void* WinSalGraphics::GetEmbedFontData(const 
vcl::font::PhysicalFontFace* pFont, tools::Long* pDataLen)
 {
-    // create matching FontSelectPattern
-    // we need just enough to get to the font file data
-    vcl::font::FontSelectPattern aIFSD( *pFont, Size(0,1000), 1000.0, 0, false 
);
-
-    ScopedFont aOldFont(*this);
-
-    HFONT hOldFont = nullptr;
-    ImplDoSetFont(aIFSD, pFont, hOldFont);
+    ScopedFontHDC aScopedFontHDC(*this, *pFont);
+    HDC hDC = aScopedFontHDC.hdc();
+    if (!hDC)
+        return nullptr;
 
     // get the raw font file data
-    RawFontData aRawFontData( getHDC() );
+    RawFontData aRawFontData(hDC);
     *pDataLen = aRawFontData.size();
-    if( !aRawFontData.get() )
-        return nullptr;
-
-    const unsigned char* pData = aRawFontData.steal();
-    return pData;
+    return aRawFontData.get() ? aRawFontData.steal() : nullptr;
 }
 
 void WinSalGraphics::FreeEmbedFontData( const void* pData, tools::Long 
/*nLen*/ )
@@ -1636,18 +1614,13 @@ void WinSalGraphics::GetGlyphWidths( const 
vcl::font::PhysicalFontFace* pFont,
                                      std::vector< sal_Int32 >& rWidths,
                                      Ucs2UIntMap& rUnicodeEnc )
 {
-    // create matching FontSelectPattern
-    // we need just enough to get to the font file data
-    vcl::font::FontSelectPattern aIFSD( *pFont, Size(0,1000), 1000.0, 0, false 
);
-
-    // TODO: much better solution: move SetFont and restoration of old font to 
caller
-    ScopedFont aOldFont(*this);
-
-    HFONT hOldFont = nullptr;
-    ImplDoSetFont(aIFSD, pFont, hOldFont);
+    ScopedFontHDC aScopedFontHDC(*this, *pFont);
+    HDC hDC = aScopedFontHDC.hdc();
+    if (!hDC)
+        return;
 
     // get raw font file data
-    const RawFontData xRawFontData( getHDC() );
+    const RawFontData xRawFontData(hDC);
     if( !xRawFontData.get() )
         return;
 
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 68ee4aa45865..862539083d29 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -260,7 +260,8 @@ void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics)
     if (m_hFont)
         return;
     HFONT hOrigFont;
-    m_hFont = m_pGraphics->ImplDoSetFont(GetFontSelectPattern(), 
GetFontFace(), hOrigFont);
+    m_hFont = m_pGraphics->ImplDoSetFont(m_pGraphics->getHDC(), 
GetFontSelectPattern(),
+                                         GetFontFace(), hOrigFont);
     SelectObject(m_pGraphics->getHDC(), hOrigFont);
 }
 

Reply via email to