diff options
author | Khaled Hosny <khaled@aliftype.com> | 2022-09-03 03:14:08 +0200 |
---|---|---|
committer | خالد حسني <khaled@aliftype.com> | 2022-09-04 02:10:17 +0200 |
commit | dc92a4d973086ce8a6a5f75ba0f4d4c9ca05537a (patch) | |
tree | 9380a4db2bb8ee1ea131b62c6cfab2957ccd5fef /vcl | |
parent | b87f4dfd33b48bb2f6cec9732ace51f2a272308d (diff) |
vcl: Create hb_face_t in PhysicalFontFace
The two map to each other, and we want to access hb_face_t to provide
some functionality scattered currently in platform-specific
implementations.
Change-Id: Ib3842752ec240b8254db828dba95a6a0ad65f16a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139275
Tested-by: Jenkins
Reviewed-by: خالد حسني <khaled@aliftype.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/font/PhysicalFontFace.hxx | 9 | ||||
-rw-r--r-- | vcl/inc/fontinstance.hxx | 17 | ||||
-rw-r--r-- | vcl/inc/qt5/QtFont.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/qt5/QtFontFace.hxx | 3 | ||||
-rw-r--r-- | vcl/inc/quartz/salgdi.h | 4 | ||||
-rw-r--r-- | vcl/inc/unx/freetype_glyphcache.hxx | 5 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 7 | ||||
-rw-r--r-- | vcl/inc/win/winlayout.hxx | 2 | ||||
-rw-r--r-- | vcl/qt5/QtFont.cxx | 21 | ||||
-rw-r--r-- | vcl/qt5/QtFontFace.cxx | 16 | ||||
-rw-r--r-- | vcl/quartz/ctfonts.cxx | 15 | ||||
-rw-r--r-- | vcl/source/font/PhysicalFontFace.cxx | 19 | ||||
-rw-r--r-- | vcl/source/font/fontinstance.cxx | 6 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 18 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/glyphcache.cxx | 24 | ||||
-rw-r--r-- | vcl/win/gdi/salfont.cxx | 94 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 94 |
17 files changed, 177 insertions, 179 deletions
diff --git a/vcl/inc/font/PhysicalFontFace.hxx b/vcl/inc/font/PhysicalFontFace.hxx index bd3093562a06..d4851ba507be 100644 --- a/vcl/inc/font/PhysicalFontFace.hxx +++ b/vcl/inc/font/PhysicalFontFace.hxx @@ -29,6 +29,8 @@ #include <fontattributes.hxx> +#include <hb.h> + class LogicalFontInstance; struct FontMatchStatus; namespace vcl::font @@ -66,6 +68,8 @@ public: class VCL_PLUGIN_PUBLIC PhysicalFontFace : public FontAttributes, public salhelper::SimpleReferenceObject { public: + ~PhysicalFontFace(); + virtual rtl::Reference<LogicalFontInstance> CreateFontInstance(const vcl::font::FontSelectPattern&) const = 0; virtual sal_IntPtr GetFontId() const = 0; @@ -75,7 +79,12 @@ public: bool IsBetterMatch( const vcl::font::FontSelectPattern&, FontMatchStatus& ) const; sal_Int32 CompareIgnoreSize( const PhysicalFontFace& ) const; + virtual hb_face_t* GetHbFace() const; + virtual hb_blob_t* GetHbTable(hb_tag_t) const { assert(false); return nullptr; } + protected: + mutable hb_face_t* mpHbFace; + explicit PhysicalFontFace(const FontAttributes&); }; diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx index 5cb05b1d3804..2b382009e263 100644 --- a/vcl/inc/fontinstance.hxx +++ b/vcl/inc/fontinstance.hxx @@ -103,16 +103,14 @@ public: // TODO: make data members private int GetKashidaWidth() const; void GetScale(double* nXScale, double* nYScale) const; - static inline void DecodeOpenTypeTag(const uint32_t nTableTag, char* pTagName); protected: explicit LogicalFontInstance(const vcl::font::PhysicalFontFace&, const vcl::font::FontSelectPattern&); virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const = 0; - // Takes ownership of pHbFace. - static hb_font_t* InitHbFont(hb_face_t* pHbFace); - virtual hb_font_t* ImplInitHbFont() { assert(false); return hb_font_get_empty(); } + hb_font_t* InitHbFont(); + virtual void ImplInitHbFont(hb_font_t*) { } private: struct MapEntry @@ -142,17 +140,8 @@ private: inline hb_font_t* LogicalFontInstance::GetHbFont() { if (!m_pHbFont) - m_pHbFont = ImplInitHbFont(); + m_pHbFont = InitHbFont(); return m_pHbFont; } -inline void LogicalFontInstance::DecodeOpenTypeTag(const uint32_t nTableTag, char* pTagName) -{ - pTagName[0] = static_cast<char>(nTableTag >> 24); - pTagName[1] = static_cast<char>(nTableTag >> 16); - pTagName[2] = static_cast<char>(nTableTag >> 8); - pTagName[3] = static_cast<char>(nTableTag); - pTagName[4] = 0; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/qt5/QtFont.hxx b/vcl/inc/qt5/QtFont.hxx index 237523e2d10a..2ba6f49e557f 100644 --- a/vcl/inc/qt5/QtFont.hxx +++ b/vcl/inc/qt5/QtFont.hxx @@ -35,8 +35,6 @@ class QtFont final : public QFont, public LogicalFontInstance bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const override; bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override; - virtual hb_font_t* ImplInitHbFont() override; - explicit QtFont(const vcl::font::PhysicalFontFace&, const vcl::font::FontSelectPattern&); }; diff --git a/vcl/inc/qt5/QtFontFace.hxx b/vcl/inc/qt5/QtFontFace.hxx index 2df5ab7eb009..eb4846ef772d 100644 --- a/vcl/inc/qt5/QtFontFace.hxx +++ b/vcl/inc/qt5/QtFontFace.hxx @@ -51,7 +51,6 @@ public: sal_IntPtr GetFontId() const override; QFont CreateFont() const; - int GetFontTable(const char pTagName[5], unsigned char*) const; FontCharMapRef GetFontCharMap() const override; bool GetFontCapabilities(vcl::FontCapabilities&) const override; @@ -60,6 +59,8 @@ public: rtl::Reference<LogicalFontInstance> CreateFontInstance(const vcl::font::FontSelectPattern& rFSD) const override; + hb_blob_t* GetHbTable(hb_tag_t nTag) const override; + private: typedef enum { Font, FontDB } FontIdType; diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index 29739adf33eb..9fc3e6b2d74c 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -75,6 +75,8 @@ public: rtl::Reference<LogicalFontInstance> CreateFontInstance(const vcl::font::FontSelectPattern&) const override; + virtual hb_blob_t* GetHbTable(hb_tag_t nTag) const override; + private: const sal_IntPtr mnFontId; mutable FontCharMapRef mxCharMap; @@ -104,7 +106,7 @@ public: private: explicit CoreTextStyle(const vcl::font::PhysicalFontFace&, const vcl::font::FontSelectPattern&); - hb_font_t* ImplInitHbFont() override; + virtual void ImplInitHbFont(hb_font_t*) override; bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override; void SetFontVariationsOnHBFont(hb_font_t*) const; diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx index 525bd35dc6f2..c3ca90591f59 100644 --- a/vcl/inc/unx/freetype_glyphcache.hxx +++ b/vcl/inc/unx/freetype_glyphcache.hxx @@ -106,6 +106,9 @@ public: FontCharMapRef GetFontCharMap() const override { return mpFreetypeFontInfo->GetFontCharMap(); } inline bool GetFontCapabilities(vcl::FontCapabilities&) const override; + + virtual hb_face_t* GetHbFace() const override; + virtual hb_blob_t* GetHbTable(hb_tag_t nTag) const override; }; bool FreetypeFontFace::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities) const @@ -119,7 +122,7 @@ class SAL_DLLPUBLIC_RTTI FreetypeFontInstance final : public LogicalFontInstance std::unique_ptr<FreetypeFont> mxFreetypeFont; - virtual hb_font_t* ImplInitHbFont() override; + virtual void ImplInitHbFont(hb_font_t*) override; virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override; explicit FreetypeFontInstance(const vcl::font::PhysicalFontFace& rPFF, const vcl::font::FontSelectPattern& rFSP); diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index 7833f988bd18..cddd59774b43 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -79,6 +79,8 @@ public: FontCharMapRef GetFontCharMap() const override; bool GetFontCapabilities(vcl::FontCapabilities&) const override; + virtual hb_blob_t* GetHbTable(hb_tag_t nTag) const override; + private: sal_IntPtr mnId; @@ -91,9 +93,10 @@ private: BYTE mnPitchAndFamily; bool mbAliasSymbolsHigh; bool mbAliasSymbolsLow; + mutable HDC mhDC; - void ReadCmapTable( HDC ) const; - void GetFontCapabilities( HDC hDC ) const; + void ReadCmapTable() const; + void GetFontCapabilities() const; }; /** Class that creates (and destroys) a compatible Device Context. diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx index 5f56fe6b0c5e..702bf7bf0b2a 100644 --- a/vcl/inc/win/winlayout.hxx +++ b/vcl/inc/win/winlayout.hxx @@ -57,7 +57,7 @@ public: private: explicit WinFontInstance(const WinFontFace&, const vcl::font::FontSelectPattern&); - hb_font_t* ImplInitHbFont() override; + virtual void ImplInitHbFont(hb_font_t*) override; bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override; WinSalGraphics *m_pGraphics; diff --git a/vcl/qt5/QtFont.cxx b/vcl/qt5/QtFont.cxx index 07bf9f541f0b..384f56774ffd 100644 --- a/vcl/qt5/QtFont.cxx +++ b/vcl/qt5/QtFont.cxx @@ -131,27 +131,6 @@ QtFont::QtFont(const vcl::font::PhysicalFontFace& rPFF, const vcl::font::FontSel applyStyle(*this, rFSP.GetItalic()); } -static hb_blob_t* getFontTable(hb_face_t*, hb_tag_t nTableTag, void* pUserData) -{ - char pTagName[5]; - LogicalFontInstance::DecodeOpenTypeTag(nTableTag, pTagName); - - QtFont* pFont = static_cast<QtFont*>(pUserData); - QRawFont aRawFont(QRawFont::fromFont(*pFont)); - QByteArray aTable = aRawFont.fontTable(pTagName); - const sal_uInt32 nLength = aTable.size(); - - hb_blob_t* pBlob = nullptr; - if (nLength > 0) - pBlob = hb_blob_create(aTable.data(), nLength, HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr); - return pBlob; -} - -hb_font_t* QtFont::ImplInitHbFont() -{ - return InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); -} - bool QtFont::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rB2DPolyPoly, bool) const { rB2DPolyPoly.clear(); diff --git a/vcl/qt5/QtFontFace.cxx b/vcl/qt5/QtFontFace.cxx index e97bee11d078..60e42422d454 100644 --- a/vcl/qt5/QtFontFace.cxx +++ b/vcl/qt5/QtFontFace.cxx @@ -253,4 +253,20 @@ bool QtFontFace::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities) c return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange; } +hb_blob_t* QtFontFace::GetHbTable(hb_tag_t nTag) const +{ + char pTagName[5] = { '\0' }; + hb_tag_to_string(nTag, pTagName); + + QFont aFont = CreateFont(); + QRawFont aRawFont(QRawFont::fromFont(aFont)); + QByteArray aTable = aRawFont.fontTable(pTagName); + const sal_uInt32 nLength = aTable.size(); + + hb_blob_t* pBlob = nullptr; + if (nLength > 0) + pBlob = hb_blob_create(aTable.data(), nLength, HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr); + return pBlob; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx index e5db219c3f8d..5e3e014c3cd4 100644 --- a/vcl/quartz/ctfonts.cxx +++ b/vcl/quartz/ctfonts.cxx @@ -232,16 +232,15 @@ bool CoreTextStyle::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rR return true; } -static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +hb_blob_t* CoreTextFontFace::GetHbTable(hb_tag_t nTag) const { sal_uLong nLength = 0; unsigned char* pBuffer = nullptr; - CoreTextFontFace* pFont = static_cast<CoreTextFontFace*>(pUserData); - nLength = pFont->GetFontTable(nTableTag, nullptr); + nLength = GetFontTable(nTag, nullptr); if (nLength > 0) { pBuffer = new unsigned char[nLength]; - pFont->GetFontTable(nTableTag, pBuffer); + GetFontTable(nTag, pBuffer); } hb_blob_t* pBlob = nullptr; @@ -293,13 +292,9 @@ void CoreTextStyle::SetFontVariationsOnHBFont(hb_font_t* pHbFont) const hb_font_set_variations(pHbFont, aHBVariations.data(), aHBVariations.size()); } -hb_font_t* CoreTextStyle::ImplInitHbFont() +void CoreTextStyle::ImplInitHbFont(hb_font_t* pHbFont) { - hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, GetFontFace(), nullptr); - hb_font_t* pHBFont = InitHbFont(pHbFace); - SetFontVariationsOnHBFont(pHBFont); - - return pHBFont; + SetFontVariationsOnHBFont(pHbFont); } rtl::Reference<LogicalFontInstance> CoreTextFontFace::CreateFontInstance(const vcl::font::FontSelectPattern& rFSD) const diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx index aef9054fdcc1..9969304e512a 100644 --- a/vcl/source/font/PhysicalFontFace.cxx +++ b/vcl/source/font/PhysicalFontFace.cxx @@ -36,6 +36,7 @@ namespace vcl::font PhysicalFontFace::PhysicalFontFace( const FontAttributes& rDFA ) : FontAttributes( rDFA ) + , mpHbFace(nullptr) { // StarSymbol is a unicode font, but it still deserves the symbol flag if( !IsSymbolFont() ) @@ -43,6 +44,12 @@ PhysicalFontFace::PhysicalFontFace( const FontAttributes& rDFA ) SetSymbolFlag( true ); } +PhysicalFontFace::~PhysicalFontFace() +{ + if (mpHbFace) + hb_face_destroy(mpHbFace); +} + sal_Int32 PhysicalFontFace::CompareIgnoreSize( const PhysicalFontFace& rOther ) const { // compare their width, weight, italic, style name and family name @@ -201,6 +208,18 @@ bool PhysicalFontFace::IsBetterMatch( const FontSelectPattern& rFSP, FontMatchSt return true; } + +static hb_blob_t* getTable(hb_face_t*, hb_tag_t nTag, void* pUserData) +{ + return static_cast<const PhysicalFontFace*>(pUserData)->GetHbTable(nTag); +} + +hb_face_t* PhysicalFontFace::GetHbFace() const +{ + if (mpHbFace == nullptr) + mpHbFace = hb_face_create_for_tables(getTable, const_cast<PhysicalFontFace*>(this), nullptr); + return mpHbFace; +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx index 44c2c8cc757d..6b9f9b16ed26 100644 --- a/vcl/source/font/fontinstance.cxx +++ b/vcl/source/font/fontinstance.cxx @@ -51,15 +51,15 @@ LogicalFontInstance::~LogicalFontInstance() hb_font_destroy(m_pHbFont); } -hb_font_t* LogicalFontInstance::InitHbFont(hb_face_t* pHbFace) +hb_font_t* LogicalFontInstance::InitHbFont() { + hb_face_t* pHbFace = GetFontFace()->GetHbFace(); assert(pHbFace); hb_font_t* pHbFont = hb_font_create(pHbFace); unsigned int nUPEM = hb_face_get_upem(pHbFace); hb_font_set_scale(pHbFont, nUPEM, nUPEM); hb_ot_font_set_funcs(pHbFont); - // hb_font_t keeps a reference to hb_face_t, so destroy this one. - hb_face_destroy(pHbFace); + ImplInitHbFont(pHbFont); return pHbFont; } diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 3b45eadd9658..5945a4813326 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -374,6 +374,24 @@ rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const v return new FreetypeFontInstance(*this, rFSD); } +hb_face_t* FreetypeFontFace::GetHbFace() const +{ + if (!mpHbFace) + { + auto* pFileName = mpFreetypeFontInfo->GetFontFileName().getStr(); + auto nIndex = mpFreetypeFontInfo->GetFontFaceIndex(); + hb_blob_t* pHbBlob = hb_blob_create_from_file(pFileName); + mpHbFace = hb_face_create(pHbBlob, nIndex); + hb_blob_destroy(pHbBlob); + } + return mpHbFace; +} + +hb_blob_t* FreetypeFontFace::GetHbTable(hb_tag_t nTag) const +{ + return hb_face_reference_table(mpHbFace, nTag); +} + // FreetypeFont FreetypeFont::FreetypeFont(FreetypeFontInstance& rFontInstance, std::shared_ptr<FreetypeFontInfo> xFI) diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx index 896585a87a27..b285bcc04c63 100644 --- a/vcl/unx/generic/glyphs/glyphcache.cxx +++ b/vcl/unx/generic/glyphs/glyphcache.cxx @@ -75,30 +75,10 @@ FreetypeFontInstance::~FreetypeFontInstance() { } -static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +void FreetypeFontInstance::ImplInitHbFont(hb_font_t* pHbFont) { - char pTagName[5]; - LogicalFontInstance::DecodeOpenTypeTag( nTableTag, pTagName ); - - sal_uLong nLength = 0; - FreetypeFontInstance* pFontInstance = static_cast<FreetypeFontInstance*>( pUserData ); - FreetypeFont& rFont = pFontInstance->GetFreetypeFont(); - const char* pBuffer = reinterpret_cast<const char*>( - rFont.GetTable(pTagName, &nLength) ); - - hb_blob_t* pBlob = nullptr; - if (pBuffer != nullptr) - pBlob = hb_blob_create(pBuffer, nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr); - - return pBlob; -} - -hb_font_t* FreetypeFontInstance::ImplInitHbFont() -{ - hb_font_t* pRet = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); assert(mxFreetypeFont); - mxFreetypeFont->SetFontVariationsOnHBFont(pRet); - return pRet; + mxFreetypeFont->SetFontVariationsOnHBFont(pHbFont); } bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, bool bVertical) const diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 3a2eb226114a..2135c7a02860 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -634,7 +634,8 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS, meWinCharSet( eWinCharSet ), mnPitchAndFamily( nPitchAndFamily ), mbAliasSymbolsHigh( false ), - mbAliasSymbolsLow( false ) + mbAliasSymbolsLow( false ), + mhDC( nullptr ) { if( eWinCharSet == SYMBOL_CHARSET ) { @@ -677,16 +678,93 @@ rtl::Reference<LogicalFontInstance> WinFontFace::CreateFontInstance(const vcl::f return new WinFontInstance(*this, rFSD); } +namespace +{ +struct BlobReference +{ + hb_blob_t* mpBlob; + BlobReference(hb_blob_t* pBlob) + : mpBlob(pBlob) + { + hb_blob_reference(mpBlob); + } + BlobReference(BlobReference&& other) noexcept + : mpBlob(other.mpBlob) + { + other.mpBlob = nullptr; + } + BlobReference& operator=(BlobReference&& other) + { + std::swap(mpBlob, other.mpBlob); + return *this; + } + BlobReference(const BlobReference& other) = delete; + BlobReference& operator=(BlobReference& other) = delete; + ~BlobReference() { hb_blob_destroy(mpBlob); } +}; +} + +using BlobCacheKey = std::pair<sal_IntPtr, hb_tag_t>; + +namespace +{ +struct BlobCacheKeyHash +{ + std::size_t operator()(BlobCacheKey const& rKey) const + { + std::size_t seed = 0; + o3tl::hash_combine(seed, rKey.first); + o3tl::hash_combine(seed, rKey.second); + return seed; + } +}; +} + +hb_blob_t* WinFontFace::GetHbTable(hb_tag_t nTag) const +{ + static o3tl::lru_map<BlobCacheKey, BlobReference, BlobCacheKeyHash> gCache(50); + BlobCacheKey aCacheKey{ GetFontId(), nTag }; + auto it = gCache.find(aCacheKey); + if (it != gCache.end()) + { + hb_blob_reference(it->second.mpBlob); + return it->second.mpBlob; + } + + assert(mhDC); + + sal_uLong nLength = 0; + unsigned char* pBuffer = nullptr; + + nLength = ::GetFontData(mhDC, 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); + } + + hb_blob_t* pBlob = nullptr; + + if (pBuffer) + pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, + pBuffer, [](void* data) { delete[] static_cast<unsigned char*>(data); }); + + gCache.insert({ aCacheKey, BlobReference(pBlob) }); + return pBlob; +} + 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( hDC ); - GetFontCapabilities( hDC ); + ReadCmapTable(); + GetFontCapabilities(); } FontCharMapRef WinFontFace::GetFontCharMap() const @@ -700,7 +778,7 @@ bool WinFontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange; } -void WinFontFace::ReadCmapTable( HDC hDC ) const +void WinFontFace::ReadCmapTable() const { if( mxUnicodeMap.is() ) return; @@ -708,7 +786,7 @@ void WinFontFace::ReadCmapTable( HDC hDC ) const 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( hDC, nCmapTag ); + const RawFontData aRawFontData( mhDC, nCmapTag ); // parse the CMAP table if available if( aRawFontData.get() ) { CmapResult aResult; @@ -727,7 +805,7 @@ void WinFontFace::ReadCmapTable( HDC hDC ) const } } -void WinFontFace::GetFontCapabilities( HDC hDC ) const +void WinFontFace::GetFontCapabilities() const { // read this only once per font if( mbFontCapabilitiesRead ) @@ -737,12 +815,12 @@ void WinFontFace::GetFontCapabilities( HDC hDC ) const // OS/2 table const DWORD OS2Tag = CalcTag( "OS/2" ); - DWORD nLength = ::GetFontData( hDC, OS2Tag, 0, nullptr, 0 ); + DWORD nLength = ::GetFontData( mhDC, OS2Tag, 0, nullptr, 0 ); if( (nLength != GDI_ERROR) && nLength ) { std::vector<unsigned char> aTable( nLength ); unsigned char* pTable = aTable.data(); - ::GetFontData( hDC, OS2Tag, 0, pTable, nLength ); + ::GetFontData( mhDC, OS2Tag, 0, pTable, nLength ); vcl::getTTCoverage(maFontCapabilities.oUnicodeRange, maFontCapabilities.oCodePageRange, pTable, nLength); } } diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index 66e9ac3e3597..b9134312bac1 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -46,7 +46,6 @@ #include <rtl/character.hxx> -#include <o3tl/hash_combine.hxx> #include <algorithm> #include <shlwapi.h> @@ -167,98 +166,9 @@ float WinFontInstance::getHScale() const return nWidth / nHeight; } -namespace -{ -struct BlobReference -{ - hb_blob_t* mpBlob; - BlobReference(hb_blob_t* pBlob) - : mpBlob(pBlob) - { - hb_blob_reference(mpBlob); - } - BlobReference(BlobReference&& other) noexcept - : mpBlob(other.mpBlob) - { - other.mpBlob = nullptr; - } - BlobReference& operator=(BlobReference&& other) - { - std::swap(mpBlob, other.mpBlob); - return *this; - } - BlobReference(const BlobReference& other) = delete; - BlobReference& operator=(BlobReference& other) = delete; - ~BlobReference() { hb_blob_destroy(mpBlob); } -}; -} - -using BlobCacheKey = std::pair<rtl::Reference<vcl::font::PhysicalFontFace>, hb_tag_t>; - -namespace -{ -struct BlobCacheKeyHash -{ - std::size_t operator()(BlobCacheKey const& rKey) const - { - std::size_t seed = 0; - o3tl::hash_combine(seed, rKey.first.get()); - o3tl::hash_combine(seed, rKey.second); - return seed; - } -}; -} - -static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) -{ - static o3tl::lru_map<BlobCacheKey, BlobReference, BlobCacheKeyHash> gCache(50); - - WinFontInstance* pFont = static_cast<WinFontInstance*>(pUserData); - - BlobCacheKey cacheKey{ rtl::Reference<vcl::font::PhysicalFontFace>(pFont->GetFontFace()), - nTableTag }; - auto it = gCache.find(cacheKey); - if (it != gCache.end()) - { - hb_blob_reference(it->second.mpBlob); - return it->second.mpBlob; - } - - HDC hDC = pFont->GetGraphics()->getHDC(); - HFONT hFont = pFont->GetHFONT(); - assert(hDC); - assert(hFont); - - sal_uLong nLength = 0; - unsigned char* pBuffer = nullptr; - - HGDIOBJ hOrigFont = SelectObject(hDC, hFont); - nLength = ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, nullptr, 0); - if (nLength > 0 && nLength != GDI_ERROR) - { - pBuffer = new unsigned char[nLength]; - ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, pBuffer, nLength); - } - SelectObject(hDC, hOrigFont); - - if (!pBuffer) - { // Cache also failures. - gCache.insert({ cacheKey, BlobReference(nullptr) }); - return nullptr; - } - - hb_blob_t* pBlob - = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, - pBuffer, [](void* data) { delete[] static_cast<unsigned char*>(data); }); - gCache.insert({ cacheKey, BlobReference(pBlob) }); - return pBlob; -} - -hb_font_t* WinFontInstance::ImplInitHbFont() +void WinFontInstance::ImplInitHbFont(hb_font_t* pHbFont) { assert(m_pGraphics); - hb_font_t* pHbFont = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); - // Calculate the AverageWidthFactor, see LogicalFontInstance::GetScale(). if (GetFontSelectPattern().mnWidth) { @@ -282,8 +192,6 @@ hb_font_t* WinFontInstance::ImplInitHbFont() SetAverageWidthFactor(nUPEM / aFontMetric.tmAveCharWidth); } - - return pHbFont; } void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics) |