diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2021-11-22 06:32:55 +0100 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2021-11-23 19:29:38 +0100 |
commit | c2a581ffc1f4e3888c5c243932b71c3d96e8ba8f (patch) | |
tree | a17b611d6702aac833763c051817ac7829ce1881 /vcl | |
parent | 90db4351138dec97f8dd2ebc350e8aef18a5358f (diff) |
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 <serval2412@yahoo.fr>
Tested-by: Jenkins
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/win/salgdi.h | 2 | ||||
-rw-r--r-- | vcl/inc/win/winlayout.hxx | 4 | ||||
-rw-r--r-- | vcl/win/gdi/salfont.cxx | 129 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 3 |
4 files changed, 54 insertions, 84 deletions
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); } |