diff options
author | Khaled Hosny <khaled@aliftype.com> | 2022-09-08 02:05:14 +0200 |
---|---|---|
committer | خالد حسني <khaled@aliftype.com> | 2022-09-08 16:32:01 +0200 |
commit | 8597aed8a8576ad0f6efe139ff03556217b01b31 (patch) | |
tree | 867f9b4831f0f03120e83864cb6347188d609fdd | |
parent | 05b3d7ea4673654e809be816bee0fa67fbf0308a (diff) |
vcl: Get FontCharMap from HarfBuzz
Implement PhysicalFontFace::GetFontCharMap() on top
hb_face_collect_unicodes() so that it is the same charmap as what
shaping code will actually use.
Change-Id: I486e9d296cec5bd897e4f628d14a2f19e63b70b5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139623
Tested-by: Jenkins
Reviewed-by: خالد حسني <khaled@aliftype.com>
-rw-r--r-- | vcl/inc/impfontcharmap.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/sft.hxx | 3 | ||||
-rw-r--r-- | vcl/source/font/PhysicalFontFace.cxx | 37 | ||||
-rw-r--r-- | vcl/source/font/fontcharmap.cxx | 26 | ||||
-rw-r--r-- | vcl/source/fontsubset/sft.cxx | 8 |
5 files changed, 64 insertions, 11 deletions
diff --git a/vcl/inc/impfontcharmap.hxx b/vcl/inc/impfontcharmap.hxx index 8a8428d7e34e..8a0b0c413d56 100644 --- a/vcl/inc/impfontcharmap.hxx +++ b/vcl/inc/impfontcharmap.hxx @@ -50,6 +50,7 @@ private: const bool m_bSymbolic; }; +bool VCL_DLLPUBLIC HasSymbolCmap(const char* pRawData, int nRawLength); bool VCL_DLLPUBLIC ParseCMAP( const unsigned char* pRawData, int nRawLength, CmapResult& ); #endif // INCLUDED_VCL_INC_IMPFONTCHARMAP_HXX diff --git a/vcl/inc/sft.hxx b/vcl/inc/sft.hxx index fb43e51a174a..75af2af8044e 100644 --- a/vcl/inc/sft.hxx +++ b/vcl/inc/sft.hxx @@ -727,6 +727,7 @@ class VCL_DLLPUBLIC AbstractTrueTypeFont sal_uInt32 m_nUnitsPerEm; std::vector<sal_uInt32> m_aGlyphOffsets; FontCharMapRef m_xCharMap; + bool m_bIsSymbolFont; protected: SFErrCodes indexGlyphData(); @@ -741,7 +742,7 @@ public: sal_uInt32 horzMetricCount() const { return m_nHorzMetrics; } sal_uInt32 vertMetricCount() const { return m_nVertMetrics; } sal_uInt32 unitsPerEm() const { return m_nUnitsPerEm; } - const FontCharMapRef & GetCharMap() const { return m_xCharMap; } + bool IsSymbolFont() const { return m_bIsSymbolFont; } virtual bool hasTable(sal_uInt32 ord) const = 0; virtual const sal_uInt8* table(sal_uInt32 ord, sal_uInt32& size) const = 0; diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx index 5d90283fe1f4..1133b0d6a131 100644 --- a/vcl/source/font/PhysicalFontFace.cxx +++ b/vcl/source/font/PhysicalFontFace.cxx @@ -230,18 +230,45 @@ FontCharMapRef PhysicalFontFace::GetFontCharMap() const if (mxCharMap.is()) return mxCharMap; + // Check if this font is using symbol cmap subtable, most likely redundant + // since HarfBuzz handles mapping symbol fonts for us. + bool bSymbol = false; hb_blob_t* pBlob = GetHbTable(HB_TAG('c', 'm', 'a', 'p')); if (pBlob) { unsigned int nSize = 0; - auto* pData = reinterpret_cast<const unsigned char*>(hb_blob_get_data(pBlob, &nSize)); - - CmapResult aCmapResult(IsSymbolFont()); - if (ParseCMAP(pData, nSize, aCmapResult)) - mxCharMap = new FontCharMap(aCmapResult); + auto* pData = hb_blob_get_data(pBlob, &nSize); + bSymbol = HasSymbolCmap(pData, nSize); hb_blob_destroy(pBlob); } + hb_face_t* pHbFace = GetHbFace(); + hb_set_t* pUnicodes = hb_set_create(); + hb_face_collect_unicodes(pHbFace, pUnicodes); + + if (hb_set_get_population(pUnicodes)) + { + // Convert HarfBuzz set to CmapResult ranges. + int nRangeCount = 0; + hb_codepoint_t nFirst, nLast = HB_SET_VALUE_INVALID; + while (hb_set_next_range(pUnicodes, &nFirst, &nLast)) + nRangeCount++; + + nLast = HB_SET_VALUE_INVALID; + auto* pRangeCodes(new sal_UCS4[nRangeCount * 2]); + auto* pCP = pRangeCodes; + while (hb_set_next_range(pUnicodes, &nFirst, &nLast)) + { + *(pCP++) = nFirst; + *(pCP++) = nLast + 1; + } + + CmapResult aCmapResult(bSymbol, pRangeCodes, nRangeCount); + mxCharMap = new FontCharMap(aCmapResult); + } + + hb_set_destroy(pUnicodes); + if (!mxCharMap.is()) mxCharMap = FontCharMap::GetDefaultMap(IsSymbolFont()); diff --git a/vcl/source/font/fontcharmap.cxx b/vcl/source/font/fontcharmap.cxx index cb42e3b9620c..24f1903f7165 100644 --- a/vcl/source/font/fontcharmap.cxx +++ b/vcl/source/font/fontcharmap.cxx @@ -83,6 +83,32 @@ bool ImplFontCharMap::isDefaultMap() const return bIsDefault; } +static unsigned GetUShort(const char* p) { return((p[0]<<8) | p[1]);} + +bool HasSymbolCmap(const char* pCmap, int nLength) +{ + // parse the table header and check for validity + if( !pCmap || (nLength < 24) ) + return false; + + if( GetUShort( pCmap ) != 0x0000 ) // simple check for CMAP corruption + return false; + + int nSubTables = GetUShort(pCmap + 2); + if( (nSubTables <= 0) || (nSubTables > (nLength - 24) / 8) ) + return false; + + for (const char* p = pCmap + 4; --nSubTables >= 0; p += 8) + { + int nPlatform = GetUShort(p); + int nEncoding = GetUShort(p + 2); + if (nPlatform == 3 && nEncoding == 0) + return true; + } + + return false; +} + static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8) | p[1]);} diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx index a164757a886d..41918cb12e6f 100644 --- a/vcl/source/fontsubset/sft.cxx +++ b/vcl/source/fontsubset/sft.cxx @@ -1200,6 +1200,7 @@ AbstractTrueTypeFont::AbstractTrueTypeFont(const char* pFileName, const FontChar , m_nVertMetrics(0) , m_nUnitsPerEm(0) , m_xCharMap(xCharMap) + , m_bIsSymbolFont(false) { if (pFileName) m_sFileName = pFileName; @@ -1297,11 +1298,8 @@ SFErrCodes AbstractTrueTypeFont::indexGlyphData() if (!m_xCharMap.is()) { - CmapResult aCmapResult; table = this->table(O_cmap, table_size); - if (!ParseCMAP(table, table_size, aCmapResult)) - return SFErrCodes::TtFormat; - m_xCharMap = new FontCharMap(aCmapResult); + m_bIsSymbolFont = HasSymbolCmap(reinterpret_cast<const char*>(table), table_size); } return SFErrCodes::Ok; @@ -2170,7 +2168,7 @@ void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) info->subfamily = ttf->subfamily; info->usubfamily = ttf->usubfamily; info->psname = ttf->psname; - info->symbolEncoded = ttf->GetCharMap()->isSymbolic(); + info->symbolEncoded = ttf->IsSymbolFont(); sal_uInt32 table_size; const sal_uInt8* table = ttf->table(O_OS2, table_size); |