vcl/inc/impfontcharmap.hxx           |    1 
 vcl/inc/sft.hxx                      |    3 +-
 vcl/source/font/PhysicalFontFace.cxx |   37 ++++++++++++++++++++++++++++++-----
 vcl/source/font/fontcharmap.cxx      |   26 ++++++++++++++++++++++++
 vcl/source/fontsubset/sft.cxx        |    8 ++-----
 5 files changed, 64 insertions(+), 11 deletions(-)

New commits:
commit 8597aed8a8576ad0f6efe139ff03556217b01b31
Author:     Khaled Hosny <kha...@aliftype.com>
AuthorDate: Thu Sep 8 02:05:14 2022 +0200
Commit:     خالد حسني <kha...@aliftype.com>
CommitDate: Thu Sep 8 16:32:01 2022 +0200

    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: خالد حسني <kha...@aliftype.com>

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);

Reply via email to