vcl/inc/win/salgdi.h | 7 -- vcl/win/gdi/salfont.cxx | 120 +++++++++++++++--------------------------------- 2 files changed, 41 insertions(+), 86 deletions(-)
New commits: commit 8f9638424f7f88c99ff16a8015ca343f3042b26d Author: Khaled Hosny <kha...@aliftype.com> AuthorDate: Sun Sep 4 19:08:08 2022 +0200 Commit: خالد حسني <kha...@aliftype.com> CommitDate: Mon Sep 5 06:08:41 2022 +0200 vcl: make WinFontFace less indirect Create the associated HFONT right from the start and avoid the UpdateFromDC() dance. We want to be able to get table data at any point after the face is created, and for this we need a HDC with the right HFONT set on it. Change-Id: Ie1f8a5afa03e0eae49f51359ebb0dbd732269c12 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139375 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@aliftype.com> diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index cddd59774b43..3f442614c3d3 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -61,15 +61,12 @@ class ImplFontMetricData; class WinFontFace : public vcl::font::PhysicalFontFace { public: - explicit WinFontFace( const FontAttributes&, - BYTE eWinCharSet, - BYTE nPitchAndFamily ); + explicit WinFontFace(const ENUMLOGFONTEXW&, const NEWTEXTMETRICW&); virtual ~WinFontFace() override; virtual rtl::Reference<LogicalFontInstance> CreateFontInstance( const vcl::font::FontSelectPattern& ) const override; virtual sal_IntPtr GetFontId() const override; void SetFontId( sal_IntPtr nId ) { mnId = nId; } - void UpdateFromHDC( HDC ) const; bool HasChar( sal_uInt32 cChar ) const; @@ -93,7 +90,7 @@ private: BYTE mnPitchAndFamily; bool mbAliasSymbolsHigh; bool mbAliasSymbolsLow; - mutable HDC mhDC; + HFONT mhFont; void ReadCmapTable() const; void GetFontCapabilities() const; diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 2135c7a02860..f2922c186c01 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -169,19 +169,8 @@ class WinGlyphFallbackSubstititution : public vcl::font::GlyphFallbackFontSubstitution { public: - explicit WinGlyphFallbackSubstititution() - : mhDC(GetDC(nullptr)) - { - }; - - ~WinGlyphFallbackSubstititution() override - { - ReleaseDC(nullptr, mhDC); - }; - bool FindFontSubstitute(vcl::font::FontSelectPattern&, LogicalFontInstance* pLogicalFont, OUString& rMissingChars) const override; private: - HDC mhDC; bool HasMissingChars(vcl::font::PhysicalFontFace*, OUString& rMissingChars) const; }; @@ -192,29 +181,6 @@ bool WinGlyphFallbackSubstititution::HasMissingChars(vcl::font::PhysicalFontFace { WinFontFace* pWinFont = static_cast< WinFontFace* >(pFace); FontCharMapRef xFontCharMap = pWinFont->GetFontCharMap(); - if( !xFontCharMap.is() ) - { - // create a FontSelectPattern object for getting s LOGFONT - const vcl::font::FontSelectPattern aFSD( *pFace, Size(), 0.0, 0, false ); - // construct log font - LOGFONTW aLogFont; - ImplGetLogFontFromFontSelect( aFSD, pFace, aLogFont ); - - // create HFONT from log font - HFONT hNewFont = ::CreateFontIndirectW( &aLogFont ); - // select the new font into device - HFONT hOldFont = ::SelectFont( mhDC, hNewFont ); - - // read CMAP table to update their xFontCharMap - pWinFont->UpdateFromHDC( mhDC ); - - // cleanup temporary font - ::SelectFont( mhDC, hOldFont ); - ::DeleteFont( hNewFont ); - - // get the new charmap - xFontCharMap = pWinFont->GetFontCharMap(); - } // avoid fonts with unknown CMAP subtables for glyph fallback if( !xFontCharMap.is() || xFontCharMap->IsDefaultMap() ) @@ -577,18 +543,6 @@ static FontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXW& rEnumFont return aDFA; } - -static rtl::Reference<WinFontFace> ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW* pLogFont, - const NEWTEXTMETRICW* pMetric) -{ - rtl::Reference<WinFontFace> pData = new WinFontFace( - WinFont2DevFontAttributes(*pLogFont, *pMetric), - pLogFont->elfLogFont.lfCharSet, - pMetric->tmPitchAndFamily ); - - return pData; -} - void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont ) { OUString aFontName( o3tl::toU(rLogFont.lfFaceName) ); @@ -626,32 +580,31 @@ void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont ) } } -WinFontFace::WinFontFace( const FontAttributes& rDFS, - BYTE eWinCharSet, BYTE nPitchAndFamily ) -: vcl::font::PhysicalFontFace( rDFS ), +WinFontFace::WinFontFace(const ENUMLOGFONTEXW& rEnumFont, const NEWTEXTMETRICW& rMetric) +: vcl::font::PhysicalFontFace(WinFont2DevFontAttributes(rEnumFont, rMetric)), mnId( 0 ), mbFontCapabilitiesRead( false ), - meWinCharSet( eWinCharSet ), - mnPitchAndFamily( nPitchAndFamily ), + meWinCharSet(rEnumFont.elfLogFont.lfCharSet), + mnPitchAndFamily(rMetric.tmPitchAndFamily), mbAliasSymbolsHigh( false ), mbAliasSymbolsLow( false ), - mhDC( nullptr ) + mhFont(CreateFontIndirectW(&rEnumFont.elfLogFont)) { - if( eWinCharSet == SYMBOL_CHARSET ) + if (meWinCharSet == SYMBOL_CHARSET) { - if( (nPitchAndFamily & TMPF_TRUETYPE) != 0 ) + if ((mnPitchAndFamily & TMPF_TRUETYPE) != 0) { // truetype fonts need their symbols as U+F0xx mbAliasSymbolsHigh = true; } - else if( (nPitchAndFamily & (TMPF_VECTOR|TMPF_DEVICE)) - == (TMPF_VECTOR|TMPF_DEVICE) ) + else if ((mnPitchAndFamily & (TMPF_VECTOR|TMPF_DEVICE)) + == (TMPF_VECTOR|TMPF_DEVICE)) { // scalable device fonts (e.g. builtin printer fonts) // need their symbols as U+00xx mbAliasSymbolsLow = true; } - else if( (nPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE)) == 0 ) + else if ((mnPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE)) == 0) { // bitmap fonts need their symbols as U+F0xx mbAliasSymbolsHigh = true; @@ -661,6 +614,7 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS, WinFontFace::~WinFontFace() { + DeleteFont(mhFont); mxUnicodeMap.clear(); } @@ -731,18 +685,22 @@ hb_blob_t* WinFontFace::GetHbTable(hb_tag_t nTag) const return it->second.mpBlob; } - assert(mhDC); - sal_uLong nLength = 0; unsigned char* pBuffer = nullptr; - nLength = ::GetFontData(mhDC, OSL_NETDWORD(nTag), 0, nullptr, 0); + HDC hDC(::GetDC(nullptr)); + HFONT hOldFont = ::SelectFont(hDC, mhFont); + + nLength = ::GetFontData(hDC, OSL_NETDWORD(nTag), 0, nullptr, 0); if (nLength > 0 && nLength != GDI_ERROR) { pBuffer = new unsigned char[nLength]; - ::GetFontData(mhDC, OSL_NETDWORD(nTag), 0, pBuffer, nLength); + ::GetFontData(hDC, OSL_NETDWORD(nTag), 0, pBuffer, nLength); } + ::SelectFont(hDC, hOldFont); + ::ReleaseDC(nullptr, hDC); + hb_blob_t* pBlob = nullptr; if (pBuffer) @@ -755,25 +713,17 @@ hb_blob_t* WinFontFace::GetHbTable(hb_tag_t nTag) const static DWORD CalcTag( const char p[5]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); } -void WinFontFace::UpdateFromHDC( HDC hDC ) const -{ - mhDC = hDC; - - // short circuit if already initialized - if( mxUnicodeMap.is() ) - return; - - ReadCmapTable(); - GetFontCapabilities(); -} - FontCharMapRef WinFontFace::GetFontCharMap() const { + if (!mxUnicodeMap.is()) + ReadCmapTable(); return mxUnicodeMap; } bool WinFontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const { + if (!mbFontCapabilitiesRead) + GetFontCapabilities(); rFontCapabilities = maFontCapabilities; return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange; } @@ -783,10 +733,13 @@ void WinFontFace::ReadCmapTable() const if( mxUnicodeMap.is() ) return; + HDC hDC(::GetDC(nullptr)); + HFONT hOldFont = ::SelectFont(hDC, mhFont); + bool bIsSymbolFont = (meWinCharSet == SYMBOL_CHARSET); // get the CMAP table from the font which is selected into the DC const DWORD nCmapTag = CalcTag( "cmap" ); - const RawFontData aRawFontData( mhDC, nCmapTag ); + const RawFontData aRawFontData( hDC, nCmapTag ); // parse the CMAP table if available if( aRawFontData.get() ) { CmapResult aResult; @@ -799,6 +752,9 @@ void WinFontFace::ReadCmapTable() const } } + ::SelectFont(hDC, hOldFont); + ::ReleaseDC(nullptr, hDC); + if( !mxUnicodeMap.is() ) { mxUnicodeMap = FontCharMap::GetDefaultMap( bIsSymbolFont ); @@ -813,16 +769,22 @@ void WinFontFace::GetFontCapabilities() const mbFontCapabilitiesRead = true; + HDC hDC(::GetDC(nullptr)); + HFONT hOldFont = ::SelectFont(hDC, mhFont); + // OS/2 table const DWORD OS2Tag = CalcTag( "OS/2" ); - DWORD nLength = ::GetFontData( mhDC, OS2Tag, 0, nullptr, 0 ); + DWORD nLength = ::GetFontData( hDC, OS2Tag, 0, nullptr, 0 ); if( (nLength != GDI_ERROR) && nLength ) { std::vector<unsigned char> aTable( nLength ); unsigned char* pTable = aTable.data(); - ::GetFontData( mhDC, OS2Tag, 0, pTable, nLength ); + ::GetFontData( hDC, OS2Tag, 0, pTable, nLength ); vcl::getTTCoverage(maFontCapabilities.oUnicodeRange, maFontCapabilities.oCodePageRange, pTable, nLength); } + + ::SelectFont(hDC, hOldFont); + ::ReleaseDC(nullptr, hDC); } void WinSalGraphics::SetTextColor( Color nColor ) @@ -1006,10 +968,6 @@ void WinSalGraphics::SetFont(LogicalFontInstance* pFont, int nFallbackLevel) for( int i = nFallbackLevel + 1; i < MAX_FALLBACK && mpWinFontEntry[i].is(); ++i ) mpWinFontEntry[i] = nullptr; } - - // now the font is live => update font face - const WinFontFace* pFontFace = pFontInstance->GetFontFace(); - pFontFace->UpdateFromHDC(getHDC()); } void WinSalGraphics::GetFontMetric( ImplFontMetricDataRef& rxFontMetric, int nFallbackLevel ) @@ -1109,7 +1067,7 @@ static int CALLBACK SalEnumFontsProcExW( const LOGFONTW* lpelfe, return 1; } - rtl::Reference<WinFontFace> pData = ImplLogMetricToDevFontDataW(pLogFont, &(pMetric->ntmTm)); + rtl::Reference<WinFontFace> pData = new WinFontFace(*pLogFont, pMetric->ntmTm); pData->SetFontId( sal_IntPtr( pInfo->mnFontCount++ ) ); pInfo->mpList->Add( pData.get() );