-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
- \r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../../include/fxge/fx_ge.h"\r
-#include "../../../include/fxge/fx_freetype.h"\r
-#include "text_int.h"\r
-#define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1])\r
-#define GET_TT_LONG(w) (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])\r
-CFX_SubstFont::CFX_SubstFont()\r
-{\r
- m_ExtHandle = NULL;\r
- m_Charset = 0;\r
- m_SubstFlags = 0;\r
- m_Weight = 0;\r
- m_ItalicAngle = 0;\r
- m_bSubstOfCJK = FALSE;\r
- m_WeightCJK = 0;\r
- m_bItlicCJK = FALSE;\r
-}\r
-CTTFontDesc::~CTTFontDesc()\r
-{\r
- if (m_Type == 1) {\r
- if (m_SingleFace.m_pFace) {\r
- FXFT_Done_Face(m_SingleFace.m_pFace);\r
- }\r
- } else if (m_Type == 2) {\r
- for (int i = 0; i < 16; i ++)\r
- if (m_TTCFace.m_pFaces[i]) {\r
- FXFT_Done_Face(m_TTCFace.m_pFaces[i]);\r
- }\r
- }\r
- if (m_pFontData) {\r
- FX_Free(m_pFontData);\r
- }\r
-}\r
-FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face)\r
-{\r
- if (m_Type == 1) {\r
- if (m_SingleFace.m_pFace != face) {\r
- return FALSE;\r
- }\r
- } else if (m_Type == 2) {\r
- int i;\r
- for (i = 0; i < 16; i ++)\r
- if (m_TTCFace.m_pFaces[i] == face) {\r
- break;\r
- }\r
- if (i == 16) {\r
- return FALSE;\r
- }\r
- }\r
- m_RefCount --;\r
- if (m_RefCount) {\r
- return FALSE;\r
- }\r
- delete this;\r
- return TRUE;\r
-}\r
-CFX_FontMgr::CFX_FontMgr()\r
-{\r
- m_pBuiltinMapper = FX_NEW CFX_FontMapper;\r
- if (!m_pBuiltinMapper) {\r
- return;\r
- }\r
- m_pBuiltinMapper->m_pFontMgr = this;\r
- m_pExtMapper = NULL;\r
- m_FTLibrary = NULL;\r
- FXSYS_memset32(m_ExternalFonts, 0, sizeof m_ExternalFonts);\r
-}\r
-CFX_FontMgr::~CFX_FontMgr()\r
-{\r
- if (m_pBuiltinMapper) {\r
- delete m_pBuiltinMapper;\r
- }\r
- FreeCache();\r
- if (m_FTLibrary) {\r
- FXFT_Done_FreeType(m_FTLibrary);\r
- }\r
-}\r
-void CFX_FontMgr::InitFTLibrary()\r
-{\r
- if (m_FTLibrary == NULL) {\r
- FXFT_Init_FreeType(&m_FTLibrary);\r
- }\r
-}\r
-void CFX_FontMgr::FreeCache()\r
-{\r
- FX_POSITION pos = m_FaceMap.GetStartPosition();\r
- while(pos) {\r
- CFX_ByteString Key;\r
- CTTFontDesc* face;\r
- m_FaceMap.GetNextAssoc(pos, Key, (void*&)face);\r
- delete face;\r
- }\r
- m_FaceMap.RemoveAll();\r
-}\r
-void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo)\r
-{\r
- m_pBuiltinMapper->SetSystemFontInfo(pFontInfo);\r
-}\r
-FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, FX_BOOL bTrueType,\r
- FX_DWORD flags, int weight, int italic_angle, int CharsetCP, CFX_SubstFont* pSubstFont)\r
-{\r
- if (m_FTLibrary == NULL) {\r
- FXFT_Init_FreeType(&m_FTLibrary);\r
- }\r
- if (m_pExtMapper) {\r
- FXFT_Face face = m_pExtMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,\r
- CharsetCP, pSubstFont);\r
- if (face) {\r
- return face;\r
- }\r
- }\r
- return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,\r
- CharsetCP, pSubstFont);\r
-}\r
-FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name,\r
- int weight, FX_BOOL bItalic, FX_LPBYTE& pFontData)\r
-{\r
- CFX_ByteString key(face_name);\r
- key += ',';\r
- key += CFX_ByteString::FormatInteger(weight);\r
- key += bItalic ? 'I' : 'N';\r
- CTTFontDesc* pFontDesc = NULL;\r
- m_FaceMap.Lookup(key, (void*&)pFontDesc);\r
- if(pFontDesc) {\r
- pFontData = pFontDesc->m_pFontData;\r
- pFontDesc->m_RefCount ++;\r
- return pFontDesc->m_SingleFace.m_pFace;\r
- }\r
- return NULL;\r
-}\r
-FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name,\r
- int weight, FX_BOOL bItalic, FX_LPBYTE pData, FX_DWORD size, int face_index)\r
-{\r
- CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc;\r
- if (!pFontDesc) {\r
- return NULL;\r
- }\r
- pFontDesc->m_Type = 1;\r
- pFontDesc->m_SingleFace.m_pFace = NULL;\r
- pFontDesc->m_SingleFace.m_bBold = weight;\r
- pFontDesc->m_SingleFace.m_bItalic = bItalic;\r
- pFontDesc->m_pFontData = pData;\r
- pFontDesc->m_RefCount = 1;\r
- FXFT_Library library;\r
- if (m_FTLibrary == NULL) {\r
- FXFT_Init_FreeType(&m_FTLibrary);\r
- }\r
- library = m_FTLibrary;\r
- int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &pFontDesc->m_SingleFace.m_pFace);\r
- if (ret) {\r
- delete pFontDesc;\r
- return NULL;\r
- }\r
- ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64);\r
- if (ret) {\r
- delete pFontDesc;\r
- return NULL;\r
- }\r
- CFX_ByteString key(face_name);\r
- key += ',';\r
- key += CFX_ByteString::FormatInteger(weight);\r
- key += bItalic ? 'I' : 'N';\r
- m_FaceMap.SetAt(key, pFontDesc);\r
- return pFontDesc->m_SingleFace.m_pFace;\r
-}\r
-const FX_LPCSTR g_Base14FontNames[14] = {\r
- "Courier",\r
- "Courier-Bold",\r
- "Courier-BoldOblique",\r
- "Courier-Oblique",\r
- "Helvetica",\r
- "Helvetica-Bold",\r
- "Helvetica-BoldOblique",\r
- "Helvetica-Oblique",\r
- "Times-Roman",\r
- "Times-Bold",\r
- "Times-BoldItalic",\r
- "Times-Italic",\r
- "Symbol",\r
- "ZapfDingbats",\r
-};\r
-const struct _AltFontName {\r
- const FX_CHAR* m_pName;\r
- int m_Index;\r
-}\r
-g_AltFontNames[] = {\r
- {"Arial", 4},\r
- {"Arial,Bold", 5},\r
- {"Arial,BoldItalic", 6},\r
- {"Arial,Italic", 7},\r
- {"Arial-Bold", 5},\r
- {"Arial-BoldItalic", 6},\r
- {"Arial-BoldItalicMT", 6},\r
- {"Arial-BoldMT", 5},\r
- {"Arial-Italic", 7},\r
- {"Arial-ItalicMT", 7},\r
- {"ArialBold", 5},\r
- {"ArialBoldItalic", 6},\r
- {"ArialItalic", 7},\r
- {"ArialMT", 4},\r
- {"ArialMT,Bold", 5},\r
- {"ArialMT,BoldItalic", 6},\r
- {"ArialMT,Italic", 7},\r
- {"ArialRoundedMTBold", 5},\r
- {"Courier", 0},\r
- {"Courier,Bold", 1},\r
- {"Courier,BoldItalic", 2},\r
- {"Courier,Italic", 3},\r
- {"Courier-Bold", 1},\r
- {"Courier-BoldOblique", 2},\r
- {"Courier-Oblique", 3},\r
- {"CourierBold", 1},\r
- {"CourierBoldItalic", 2},\r
- {"CourierItalic", 3},\r
- {"CourierNew", 0},\r
- {"CourierNew,Bold", 1},\r
- {"CourierNew,BoldItalic", 2},\r
- {"CourierNew,Italic", 3},\r
- {"CourierNew-Bold", 1},\r
- {"CourierNew-BoldItalic", 2},\r
- {"CourierNew-Italic", 3},\r
- {"CourierNewBold", 1},\r
- {"CourierNewBoldItalic", 2},\r
- {"CourierNewItalic", 3},\r
- {"CourierNewPS-BoldItalicMT", 2},\r
- {"CourierNewPS-BoldMT", 1},\r
- {"CourierNewPS-ItalicMT", 3},\r
- {"CourierNewPSMT", 0},\r
- {"CourierStd", 0},\r
- {"CourierStd-Bold", 1},\r
- {"CourierStd-BoldOblique", 2},\r
- {"CourierStd-Oblique", 3},\r
- {"Helvetica", 4},\r
- {"Helvetica,Bold", 5},\r
- {"Helvetica,BoldItalic", 6},\r
- {"Helvetica,Italic", 7},\r
- {"Helvetica-Bold", 5},\r
- {"Helvetica-BoldItalic", 6},\r
- {"Helvetica-BoldOblique", 6},\r
- {"Helvetica-Italic", 7},\r
- {"Helvetica-Oblique", 7},\r
- {"HelveticaBold", 5},\r
- {"HelveticaBoldItalic", 6},\r
- {"HelveticaItalic", 7},\r
- {"Symbol", 12},\r
- {"SymbolMT", 12},\r
- {"Times-Bold", 9},\r
- {"Times-BoldItalic", 10},\r
- {"Times-Italic", 11},\r
- {"Times-Roman", 8},\r
- {"TimesBold", 9},\r
- {"TimesBoldItalic", 10},\r
- {"TimesItalic", 11},\r
- {"TimesNewRoman", 8},\r
- {"TimesNewRoman,Bold", 9},\r
- {"TimesNewRoman,BoldItalic", 10},\r
- {"TimesNewRoman,Italic", 11},\r
- {"TimesNewRoman-Bold", 9},\r
- {"TimesNewRoman-BoldItalic", 10},\r
- {"TimesNewRoman-Italic", 11},\r
- {"TimesNewRomanBold", 9},\r
- {"TimesNewRomanBoldItalic", 10},\r
- {"TimesNewRomanItalic", 11},\r
- {"TimesNewRomanPS", 8},\r
- {"TimesNewRomanPS-Bold", 9},\r
- {"TimesNewRomanPS-BoldItalic", 10},\r
- {"TimesNewRomanPS-BoldItalicMT", 10},\r
- {"TimesNewRomanPS-BoldMT", 9},\r
- {"TimesNewRomanPS-Italic", 11},\r
- {"TimesNewRomanPS-ItalicMT", 11},\r
- {"TimesNewRomanPSMT", 8},\r
- {"TimesNewRomanPSMT,Bold", 9},\r
- {"TimesNewRomanPSMT,BoldItalic", 10},\r
- {"TimesNewRomanPSMT,Italic", 11},\r
- {"ZapfDingbats", 13},\r
-};\r
-extern "C" {\r
- static int compareString(const void* key, const void* element)\r
- {\r
- return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontName*)element)->m_pName);\r
- }\r
-}\r
-int _PDF_GetStandardFontName(CFX_ByteString& name)\r
-{\r
- _AltFontName* found = (_AltFontName*)FXSYS_bsearch((FX_LPCSTR)name, g_AltFontNames,\r
- sizeof g_AltFontNames / sizeof (_AltFontName), sizeof (_AltFontName), compareString);\r
- if (found == NULL) {\r
- return -1;\r
- }\r
- name = g_Base14FontNames[found->m_Index];\r
- return found->m_Index;\r
-}\r
-int GetTTCIndex(FX_LPCBYTE pFontData, FX_DWORD ttc_size, FX_DWORD font_offset)\r
-{\r
- int face_index = 0;\r
- FX_LPCBYTE p = pFontData + 8;\r
- FX_DWORD nfont = GET_TT_LONG(p);\r
- FX_DWORD index;\r
- for (index = 0; index < nfont; index ++) {\r
- p = pFontData + 12 + index * 4;\r
- if (GET_TT_LONG(p) == font_offset) {\r
- break;\r
- }\r
- }\r
- if(index >= nfont) {\r
- face_index = 0;\r
- } else {\r
- face_index = index;\r
- }\r
- return face_index;\r
-}\r
-FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, FX_DWORD checksum,\r
- int font_offset, FX_LPBYTE& pFontData)\r
-{\r
- CFX_ByteString key;\r
- key.Format("%d:%d", ttc_size, checksum);\r
- CTTFontDesc* pFontDesc = NULL;\r
- m_FaceMap.Lookup(key, (void*&)pFontDesc);\r
- if (pFontDesc == NULL) {\r
- return NULL;\r
- }\r
- pFontData = pFontDesc->m_pFontData;\r
- pFontDesc->m_RefCount ++;\r
- int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);\r
- if (pFontDesc->m_TTCFace.m_pFaces[face_index] == NULL) {\r
- pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);\r
- }\r
- return pFontDesc->m_TTCFace.m_pFaces[face_index];\r
-}\r
-FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, FX_DWORD checksum,\r
- FX_LPBYTE pData, FX_DWORD size, int font_offset)\r
-{\r
- CFX_ByteString key;\r
- key.Format("%d:%d", ttc_size, checksum);\r
- CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc;\r
- if (!pFontDesc) {\r
- return NULL;\r
- }\r
- pFontDesc->m_Type = 2;\r
- pFontDesc->m_pFontData = pData;\r
- for (int i = 0; i < 16; i ++) {\r
- pFontDesc->m_TTCFace.m_pFaces[i] = NULL;\r
- }\r
- pFontDesc->m_RefCount ++;\r
- key.Format("%d:%d", ttc_size, checksum);\r
- m_FaceMap.SetAt(key, pFontDesc);\r
- int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);\r
- pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);\r
- return pFontDesc->m_TTCFace.m_pFaces[face_index];\r
-}\r
-FXFT_Face CFX_FontMgr::GetFixedFace(FX_LPCBYTE pData, FX_DWORD size, int face_index)\r
-{\r
- FXFT_Library library;\r
- if (m_FTLibrary == NULL) {\r
- FXFT_Init_FreeType(&m_FTLibrary);\r
- }\r
- library = m_FTLibrary;\r
- FXFT_Face face = NULL;\r
- int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face);\r
- if (ret) {\r
- return NULL;\r
- }\r
- ret = FXFT_Set_Pixel_Sizes(face, 64, 64);\r
- if (ret) {\r
- return NULL;\r
- }\r
- return face;\r
-}\r
-FXFT_Face CFX_FontMgr::GetFileFace(FX_LPCSTR filename, int face_index)\r
-{\r
- FXFT_Library library;\r
- if (m_FTLibrary == NULL) {\r
- FXFT_Init_FreeType(&m_FTLibrary);\r
- }\r
- library = m_FTLibrary;\r
- FXFT_Face face = NULL;\r
- int ret = FXFT_New_Face(library, filename, face_index, &face);\r
- if (ret) {\r
- return NULL;\r
- }\r
- ret = FXFT_Set_Pixel_Sizes(face, 64, 64);\r
- if (ret) {\r
- return NULL;\r
- }\r
- return face;\r
-}\r
-void CFX_FontMgr::ReleaseFace(FXFT_Face face)\r
-{\r
- if (face == NULL) {\r
- return;\r
- }\r
- FX_POSITION pos = m_FaceMap.GetStartPosition();\r
- while(pos) {\r
- CFX_ByteString Key;\r
- CTTFontDesc* ttface;\r
- m_FaceMap.GetNextAssoc(pos, Key, (void*&)ttface);\r
- if (ttface->ReleaseFace(face)) {\r
- m_FaceMap.RemoveKey(Key);\r
- }\r
- }\r
-}\r
-extern "C" {\r
- extern const unsigned char g_FoxitFixedItalicFontData [18746];\r
- extern const unsigned char g_FoxitFixedFontData [17597];\r
- extern const unsigned char g_FoxitSansItalicFontData [16339];\r
- extern const unsigned char g_FoxitSansFontData [15025];\r
- extern const unsigned char g_FoxitSerifItalicFontData [21227];\r
- extern const unsigned char g_FoxitSerifFontData [19469];\r
- extern const unsigned char g_FoxitFixedBoldItalicFontData [19151];\r
- extern const unsigned char g_FoxitFixedBoldFontData [18055];\r
- extern const unsigned char g_FoxitSansBoldItalicFontData [16418];\r
- extern const unsigned char g_FoxitSansBoldFontData [16344];\r
- extern const unsigned char g_FoxitSerifBoldItalicFontData [20733];\r
- extern const unsigned char g_FoxitSerifBoldFontData [19395];\r
- extern const unsigned char g_FoxitSymbolFontData[16729];\r
- extern const unsigned char g_FoxitDingbatsFontData[29513];\r
- extern const unsigned char g_FoxitSerifMMFontData[113417];\r
- extern const unsigned char g_FoxitSansMMFontData[66919];\r
-};\r
-const FoxitFonts g_FoxitFonts[14] = {\r
- {g_FoxitFixedFontData, 17597},\r
- {g_FoxitFixedBoldFontData, 18055},\r
- {g_FoxitFixedBoldItalicFontData, 19151},\r
- {g_FoxitFixedItalicFontData, 18746},\r
- {g_FoxitSansFontData, 15025},\r
- {g_FoxitSansBoldFontData, 16344},\r
- {g_FoxitSansBoldItalicFontData, 16418},\r
- {g_FoxitSansItalicFontData, 16339},\r
- {g_FoxitSerifFontData, 19469},\r
- {g_FoxitSerifBoldFontData, 19395},\r
- {g_FoxitSerifBoldItalicFontData, 20733},\r
- {g_FoxitSerifItalicFontData, 21227},\r
- {g_FoxitSymbolFontData, 16729},\r
- {g_FoxitDingbatsFontData, 29513},\r
-};\r
-void _FPDFAPI_GetInternalFontData(int id, FX_LPCBYTE& data, FX_DWORD& size)\r
-{\r
- CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id);\r
-}\r
-FX_BOOL CFX_FontMgr::GetStandardFont(FX_LPCBYTE& pFontData, FX_DWORD& size, int index)\r
-{\r
- if (index > 15 || index < 0) {\r
- return FALSE;\r
- }\r
- {\r
- if (index >= 14) {\r
- if (index == 14) {\r
- pFontData = g_FoxitSerifMMFontData;\r
- size = 113417;\r
- } else {\r
- pFontData = g_FoxitSansMMFontData;\r
- size = 66919;\r
- }\r
- } else {\r
- pFontData = g_FoxitFonts[index].m_pFontData;\r
- size = g_FoxitFonts[index].m_dwSize;\r
- }\r
- }\r
- return TRUE;\r
-}\r
-CFX_FontMapper::CFX_FontMapper()\r
-{\r
- FXSYS_memset32(m_FoxitFaces, 0, sizeof m_FoxitFaces);\r
- m_MMFaces[0] = m_MMFaces[1] = NULL;\r
- m_pFontInfo = NULL;\r
- m_bListLoaded = FALSE;\r
- m_pFontEnumerator = NULL;\r
-}\r
-CFX_FontMapper::~CFX_FontMapper()\r
-{\r
- for (int i = 0; i < 14; i ++)\r
- if (m_FoxitFaces[i]) {\r
- FXFT_Done_Face(m_FoxitFaces[i]);\r
- }\r
- if (m_MMFaces[0]) {\r
- FXFT_Done_Face(m_MMFaces[0]);\r
- }\r
- if (m_MMFaces[1]) {\r
- FXFT_Done_Face(m_MMFaces[1]);\r
- }\r
- if (m_pFontInfo) {\r
- m_pFontInfo->Release();\r
- }\r
-}\r
-void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo)\r
-{\r
- if (pFontInfo == NULL) {\r
- return;\r
- }\r
- if (m_pFontInfo) {\r
- m_pFontInfo->Release();\r
- }\r
- m_pFontInfo = pFontInfo;\r
-}\r
-static CFX_ByteString _TT_NormalizeName(FX_LPCSTR family)\r
-{\r
- CFX_ByteString norm(family, -1);\r
- norm.Remove(' ');\r
- norm.Remove('-');\r
- norm.Remove(',');\r
- int pos = norm.Find('+');\r
- if (pos > 0) {\r
- norm = norm.Left(pos);\r
- }\r
- norm.MakeLower();\r
- return norm;\r
-}\r
-CFX_ByteString _FPDF_GetNameFromTT(FX_LPCBYTE name_table, FX_DWORD name_id)\r
-{\r
- FX_LPCBYTE ptr = name_table + 2;\r
- int name_count = GET_TT_SHORT(ptr);\r
- int string_offset = GET_TT_SHORT(ptr + 2);\r
- FX_LPCBYTE string_ptr = name_table + string_offset;\r
- ptr += 4;\r
- for (int i = 0; i < name_count; i ++) {\r
- if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 && GET_TT_SHORT(ptr + 2) == 0) {\r
- return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10), GET_TT_SHORT(ptr + 8));\r
- }\r
- ptr += 12;\r
- }\r
- return CFX_ByteString();\r
-}\r
-static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile, FX_DWORD size)\r
-{\r
- CFX_ByteString buffer;\r
- if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) {\r
- return CFX_ByteString();\r
- }\r
- buffer.ReleaseBuffer(size);\r
- return buffer;\r
-}\r
-static CFX_ByteString _FPDF_ReadStringFromStreamFile(IFX_FileStream* pFile, FX_DWORD size)\r
-{\r
- CFX_ByteString buffer;\r
- if (!pFile->ReadBlock(buffer.GetBuffer(size), size)) {\r
- return CFX_ByteString();\r
- }\r
- buffer.ReleaseBuffer(size);\r
- return buffer;\r
-}\r
-CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag)\r
-{\r
- for (FX_DWORD i = 0; i < nTables; i ++) {\r
- FX_LPCBYTE p = pTables + i * 16;\r
- if (GET_TT_LONG(p) == tag) {\r
- FX_DWORD offset = GET_TT_LONG(p + 8);\r
- FX_DWORD size = GET_TT_LONG(p + 12);\r
- FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);\r
- return _FPDF_ReadStringFromFile(pFile, size);\r
- }\r
- }\r
- return CFX_ByteString();\r
-}\r
-CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag)\r
-{\r
- for (FX_DWORD i = 0; i < nTables; i ++) {\r
- FX_LPCBYTE p = pTables + i * 16;\r
- if (GET_TT_LONG(p) == tag) {\r
- FX_DWORD offset = GET_TT_LONG(p + 8);\r
- FX_DWORD size = GET_TT_LONG(p + 12);\r
- CFX_ByteString buffer;\r
- if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) {\r
- return CFX_ByteString();\r
- }\r
- buffer.ReleaseBuffer(size);\r
- return buffer;\r
- }\r
- }\r
- return CFX_ByteString();\r
-}\r
-CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont)\r
-{\r
- if (m_pFontInfo == NULL) {\r
- CFX_ByteString();\r
- }\r
- CFX_ByteString result;\r
- FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0);\r
- if (size) {\r
- FX_LPBYTE buffer = FX_Alloc(FX_BYTE, size);\r
- if (!buffer) {\r
- return result;\r
- }\r
- m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);\r
- result = _FPDF_GetNameFromTT(buffer, 6);\r
- FX_Free(buffer);\r
- }\r
- return result;\r
-}\r
-void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset)\r
-{\r
- if (m_pFontInfo == NULL) {\r
- return;\r
- }\r
- if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {\r
- m_CharsetArray.Add((FX_DWORD)charset);\r
- m_FaceArray.Add(name);\r
- }\r
- if (name == m_LastFamily) {\r
- return;\r
- }\r
- FX_LPCBYTE ptr = name;\r
- FX_BOOL bLocalized = FALSE;\r
- for (int i = 0; i < name.GetLength(); i ++)\r
- if (ptr[i] > 0x80) {\r
- bLocalized = TRUE;\r
- break;\r
- }\r
- if (bLocalized) {\r
- void* hFont = m_pFontInfo->GetFont(name);\r
- if (hFont == NULL) {\r
- FX_BOOL bExact;\r
- hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, bExact);\r
- if (hFont == NULL) {\r
- return;\r
- }\r
- }\r
- CFX_ByteString new_name = GetPSNameFromTT(hFont);\r
- if (!new_name.IsEmpty()) {\r
- new_name.Insert(0, ' ');\r
- m_InstalledTTFonts.Add(new_name);\r
- }\r
- m_pFontInfo->DeleteFont(hFont);\r
- }\r
- m_InstalledTTFonts.Add(name);\r
- m_LastFamily = name;\r
-}\r
-void CFX_FontMapper::LoadInstalledFonts()\r
-{\r
- if (m_pFontInfo == NULL) {\r
- return;\r
- }\r
- if (m_bListLoaded) {\r
- return;\r
- }\r
- if (m_bListLoaded) {\r
- return;\r
- }\r
- m_pFontInfo->EnumFontList(this);\r
- m_bListLoaded = TRUE;\r
-}\r
-CFX_ByteString CFX_FontMapper::MatchInstalledFonts(const CFX_ByteString& norm_name)\r
-{\r
- LoadInstalledFonts();\r
- int i;\r
- for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i --) {\r
- CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);\r
- if (norm1 == norm_name) {\r
- break;\r
- }\r
- }\r
- if (i < 0) {\r
- return CFX_ByteString();\r
- }\r
- CFX_ByteString match = m_InstalledTTFonts[i];\r
- if (match[0] == ' ') {\r
- match = m_InstalledTTFonts[i + 1];\r
- }\r
- return match;\r
-}\r
-typedef struct _CHARSET_MAP_ {\r
- FX_BYTE charset;\r
- FX_WORD codepage;\r
-} CHARSET_MAP;\r
-static const CHARSET_MAP g_Codepage2CharsetTable[] = {\r
- { 1 , 0 },\r
- { 2 , 42 },\r
- { 254, 437 },\r
- { 255, 850 },\r
- { 222, 874 },\r
- { 128, 932 },\r
- { 134, 936 },\r
- { 129, 949 },\r
- { 136, 950 },\r
- { 238, 1250 },\r
- { 204, 1251 },\r
- { 0, 1252 },\r
- { 161, 1253 },\r
- { 162, 1254 },\r
- { 177, 1255 },\r
- { 178, 1256 },\r
- { 186, 1257 },\r
- { 163, 1258 },\r
- { 130, 1361 },\r
- { 77, 10000 },\r
- { 78, 10001 },\r
- { 79, 10003 },\r
- { 80, 10008 },\r
- { 81, 10002 },\r
- { 83, 10005 },\r
- { 84, 10004 },\r
- { 85, 10006 },\r
- { 86, 10081 },\r
- { 87, 10021 },\r
- { 88, 10029 },\r
- { 89, 10007 },\r
-};\r
-FX_BYTE _GetCharsetFromCodePage(FX_WORD codepage)\r
-{\r
- FX_INT32 iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;\r
- FXSYS_assert(iEnd >= 0);\r
- FX_INT32 iStart = 0, iMid;\r
- do {\r
- iMid = (iStart + iEnd) / 2;\r
- const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid];\r
- if (codepage == cp.codepage) {\r
- return cp.charset;\r
- } else if (codepage < cp.codepage) {\r
- iEnd = iMid - 1;\r
- } else {\r
- iStart = iMid + 1;\r
- }\r
- } while (iStart <= iEnd);\r
- return 1;\r
-}\r
-FX_DWORD _GetCodePageRangeFromCharset(int charset)\r
-{\r
- if (charset == FXFONT_EASTEUROPE_CHARSET) {\r
- return 1 << 1;\r
- }\r
- if (charset == FXFONT_GREEK_CHARSET) {\r
- return 1 << 3;\r
- }\r
- if (charset == FXFONT_TURKISH_CHARSET) {\r
- return 1 << 4;\r
- }\r
- if (charset == FXFONT_HEBREW_CHARSET) {\r
- return 1 << 5;\r
- }\r
- if (charset == FXFONT_ARABIC_CHARSET) {\r
- return 1 << 6;\r
- }\r
- if (charset == FXFONT_BALTIC_CHARSET) {\r
- return 1 << 7;\r
- }\r
- if (charset == FXFONT_THAI_CHARSET) {\r
- return 1 << 16;\r
- }\r
- if (charset == FXFONT_SHIFTJIS_CHARSET) {\r
- return 1 << 17;\r
- }\r
- if (charset == FXFONT_GB2312_CHARSET) {\r
- return 1 << 18;\r
- }\r
- if (charset == FXFONT_CHINESEBIG5_CHARSET) {\r
- return 1 << 20;\r
- }\r
- if (charset == FXFONT_HANGEUL_CHARSET) {\r
- return 1 << 19;\r
- }\r
- if (charset == FXFONT_SYMBOL_CHARSET) {\r
- return 1 << 31;\r
- }\r
- return 1 << 21;\r
-}\r
-static int CP2CharSet(int cp)\r
-{\r
- if(cp == 932) {\r
- return FXFONT_SHIFTJIS_CHARSET;\r
- } else if(cp == 936) {\r
- return FXFONT_GB2312_CHARSET;\r
- } else if(cp == 949) {\r
- return FXFONT_HANGEUL_CHARSET;\r
- } else if(cp == 950) {\r
- return FXFONT_CHINESEBIG5_CHARSET;\r
- }\r
- return FXFONT_DEFAULT_CHARSET;\r
-}\r
-FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int picthfamily)\r
-{\r
- if (iBaseFont < 12) {\r
- if (m_FoxitFaces[iBaseFont]) {\r
- return m_FoxitFaces[iBaseFont];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size = 0;\r
- if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {\r
- m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_FoxitFaces[iBaseFont];\r
- }\r
- }\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;\r
- pSubstFont->m_ItalicAngle = italic_angle;\r
- if (weight) {\r
- pSubstFont->m_Weight = weight;\r
- }\r
- if (picthfamily & FXFONT_FF_ROMAN) {\r
- pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;\r
- pSubstFont->m_Family = "Chrome Serif";\r
- if (m_MMFaces[1]) {\r
- return m_MMFaces[1];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size;\r
- m_pFontMgr->GetStandardFont(pFontData, size, 14);\r
- m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_MMFaces[1];\r
- }\r
- pSubstFont->m_Family = "Chrome Sans";\r
- if (m_MMFaces[0]) {\r
- return m_MMFaces[0];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size = 0;\r
- m_pFontMgr->GetStandardFont(pFontData, size, 15);\r
- m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_MMFaces[0];\r
-}\r
-const struct _AltFontFamily {\r
- FX_LPCSTR m_pFontName;\r
- FX_LPCSTR m_pFontFamily;\r
-}\r
-g_AltFontFamilies[] = {\r
- {"AGaramondPro", "Adobe Garamond Pro"},\r
- {"BankGothicBT-Medium", "BankGothic Md BT"},\r
- {"ForteMT", "Forte"},\r
-};\r
-extern "C" {\r
- static int compareFontFamilyString(const void* key, const void* element)\r
- {\r
- CFX_ByteString str_key((FX_LPCSTR)key);\r
- if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {\r
- return 0;\r
- }\r
- return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontFamily*)element)->m_pFontName);\r
- }\r
-}\r
-#define FX_FONT_STYLE_None 0x00\r
-#define FX_FONT_STYLE_Bold 0x01\r
-#define FX_FONT_STYLE_Italic 0x02\r
-#define FX_FONT_STYLE_BoldBold 0x04\r
-static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle)\r
-{\r
- if (fontName.Find("Script") >= 0) {\r
- if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {\r
- fontName = "ScriptMTBold";\r
- } else if (fontName.Find("Palace") >= 0) {\r
- fontName = "PalaceScriptMT";\r
- } else if (fontName.Find("French") >= 0) {\r
- fontName = "FrenchScriptMT";\r
- } else if (fontName.Find("FreeStyle") >= 0) {\r
- fontName = "FreeStyleScript";\r
- }\r
- return fontName;\r
- }\r
- _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch((FX_LPCSTR)fontName, g_AltFontFamilies,\r
- sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString);\r
- if (found == NULL) {\r
- return fontName;\r
- }\r
- return found->m_pFontFamily;\r
-};\r
-typedef struct _FX_FontStyle {\r
- FX_LPCSTR style;\r
- FX_INT32 len;\r
-} FX_FontStyle;\r
-const FX_FontStyle g_FontStyles[] = {\r
- "Bold", 4,\r
- "Italic", 6,\r
- "BoldItalic", 10,\r
- "Reg", 3,\r
- "Regular", 7,\r
-};\r
-CFX_ByteString ParseStyle(FX_LPCSTR pStyle, int iLen, int iIndex)\r
-{\r
- CFX_ByteTextBuf buf;\r
- if (!iLen || iLen <= iIndex) {\r
- return buf.GetByteString();\r
- }\r
- while (iIndex < iLen) {\r
- if (pStyle[iIndex] == ',') {\r
- break;\r
- }\r
- buf.AppendChar(pStyle[iIndex]);\r
- ++iIndex;\r
- }\r
- return buf.GetByteString();\r
-}\r
-FX_INT32 GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert)\r
-{\r
- FX_INT32 iLen = bsStyle.GetLength();\r
- if (!iLen) {\r
- return -1;\r
- }\r
- int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);\r
- const FX_FontStyle *pStyle = NULL;\r
- for (int i = iSize - 1; i >= 0; --i) {\r
- pStyle = g_FontStyles + i;\r
- if (!pStyle || pStyle->len > iLen) {\r
- continue;\r
- }\r
- if (!bRevert) {\r
- if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {\r
- return i;\r
- }\r
- } else {\r
- if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {\r
- return i;\r
- }\r
- }\r
- }\r
- return -1;\r
-}\r
-FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int &PitchFamily)\r
-{\r
- if (name == FX_BSTRC("MyriadPro")) {\r
- PitchFamily &= ~FXFONT_FF_ROMAN;\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, FX_BOOL bTrueType, FX_DWORD flags,\r
- int weight, int italic_angle, int WindowCP, CFX_SubstFont* pSubstFont)\r
-{\r
- if (!(flags & FXFONT_USEEXTERNATTR)) {\r
- weight = FXFONT_FW_NORMAL;\r
- italic_angle = 0;\r
- }\r
- CFX_ByteString SubstName = name;\r
- SubstName.Remove(0x20);\r
- if (bTrueType) {\r
- if (name[0] == '@') {\r
- SubstName = name.Mid(1);\r
- }\r
- }\r
- _PDF_GetStandardFontName(SubstName);\r
- if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {\r
- pSubstFont->m_Family = "Chrome Symbol";\r
- pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- if (m_FoxitFaces[12]) {\r
- return m_FoxitFaces[12];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size = 0;\r
- m_pFontMgr->GetStandardFont(pFontData, size, 12);\r
- m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_FoxitFaces[12];\r
- }\r
- if (SubstName == FX_BSTRC("ZapfDingbats")) {\r
- pSubstFont->m_Family = "Chrome Dingbats";\r
- pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- if (m_FoxitFaces[13]) {\r
- return m_FoxitFaces[13];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size = 0;\r
- m_pFontMgr->GetStandardFont(pFontData, size, 13);\r
- m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_FoxitFaces[13];\r
- }\r
- int iBaseFont = 0;\r
- CFX_ByteString family, style;\r
- FX_BOOL bHasComma = FALSE;\r
- FX_BOOL bHasHypen = FALSE;\r
- int find = SubstName.Find(FX_BSTRC(","), 0);\r
- if (find >= 0) {\r
- family = SubstName.Left(find);\r
- _PDF_GetStandardFontName(family);\r
- style = SubstName.Mid(find + 1);\r
- bHasComma = TRUE;\r
- } else {\r
- family = SubstName;\r
- }\r
- for (; iBaseFont < 12; iBaseFont ++)\r
- if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {\r
- break;\r
- }\r
- int PitchFamily = 0;\r
- FX_BOOL bItalic = FALSE;\r
- FX_DWORD nStyle = 0;\r
- FX_BOOL bStyleAvail = FALSE;\r
- FX_BOOL bFamilyStyleIsWhole = FALSE;\r
- FX_BOOL bNextF = FALSE;\r
- if (iBaseFont < 12) {\r
- family = g_Base14FontNames[iBaseFont];\r
- if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {\r
- nStyle |= FX_FONT_STYLE_Bold;\r
- }\r
- if ((iBaseFont % 4) / 2) {\r
- nStyle |= FX_FONT_STYLE_Italic;\r
- }\r
- if (iBaseFont < 4) {\r
- PitchFamily |= FXFONT_FF_FIXEDPITCH;\r
- }\r
- if (iBaseFont >= 8) {\r
- PitchFamily |= FXFONT_FF_ROMAN;\r
- }\r
- } else {\r
- if (!bHasComma) {\r
- find = family.ReverseFind('-');\r
- if (find >= 0) {\r
- style = family.Mid(find + 1);\r
- family = family.Left(find);\r
- bHasHypen = TRUE;\r
- }\r
- }\r
- if (!bHasHypen) {\r
- int nLen = family.GetLength();\r
- FX_INT32 nRet = GetStyleType(family, TRUE);\r
- if (nRet > -1) {\r
- family = family.Left(nLen - g_FontStyles[nRet].len);\r
- if (nRet == 0) {\r
- nStyle |= FX_FONT_STYLE_Bold;\r
- }\r
- if (nRet == 1) {\r
- nStyle |= FX_FONT_STYLE_Italic;\r
- }\r
- if (nRet == 2) {\r
- nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);\r
- }\r
- }\r
- }\r
- if (flags & FXFONT_SERIF) {\r
- PitchFamily |= FXFONT_FF_ROMAN;\r
- }\r
- if (flags & FXFONT_SCRIPT) {\r
- PitchFamily |= FXFONT_FF_SCRIPT;\r
- }\r
- if (flags & FXFONT_FIXED_PITCH) {\r
- PitchFamily |= FXFONT_FF_FIXEDPITCH;\r
- }\r
- }\r
- if (!style.IsEmpty()) {\r
- int nLen = style.GetLength();\r
- FX_LPCSTR pStyle = style;\r
- int i = 0;\r
- FX_BOOL bFirstItem = TRUE;\r
- CFX_ByteString buf;\r
- while (i < nLen) {\r
- buf = ParseStyle(pStyle, nLen, i);\r
- FX_INT32 nRet = GetStyleType(buf, FALSE);\r
- if ((i && !bStyleAvail) || (!i && nRet < 0)) {\r
- family = SubstName;\r
- iBaseFont = 12;\r
- break;\r
- } else if (nRet >= 0) {\r
- bStyleAvail = TRUE;\r
- }\r
- if (nRet == 0) {\r
- if (nStyle & FX_FONT_STYLE_Bold) {\r
- nStyle |= FX_FONT_STYLE_BoldBold;\r
- } else {\r
- nStyle |= FX_FONT_STYLE_Bold;\r
- }\r
- bFirstItem = FALSE;\r
- }\r
- if (nRet == 1) {\r
- if (bFirstItem) {\r
- nStyle |= FX_FONT_STYLE_Italic;\r
- } else {\r
- family = SubstName;\r
- iBaseFont = 12;\r
- }\r
- break;\r
- }\r
- if (nRet == 2) {\r
- nStyle |= FX_FONT_STYLE_Italic;\r
- if (nStyle & FX_FONT_STYLE_Bold) {\r
- nStyle |= FX_FONT_STYLE_BoldBold;\r
- } else {\r
- nStyle |= FX_FONT_STYLE_Bold;\r
- }\r
- bFirstItem = FALSE;\r
- }\r
- i += buf.GetLength() + 1;\r
- }\r
- }\r
- weight = weight ? weight : FXFONT_FW_NORMAL;\r
- int old_weight = weight;\r
- if (nStyle) {\r
- weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);\r
- }\r
- if (nStyle & FX_FONT_STYLE_Italic) {\r
- bItalic = TRUE;\r
- }\r
- FX_BOOL bCJK = FALSE;\r
- FX_BOOL bExact = FALSE;\r
- int Charset = FXFONT_ANSI_CHARSET;\r
- if (WindowCP) {\r
- Charset = _GetCharsetFromCodePage(WindowCP);\r
- } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {\r
- Charset = FXFONT_SYMBOL_CHARSET;\r
- }\r
- if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||\r
- Charset == FXFONT_HANGEUL_CHARSET || Charset == FXFONT_CHINESEBIG5_CHARSET) {\r
- bCJK = TRUE;\r
- }\r
- if (m_pFontInfo == NULL) {\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);\r
- }\r
- family = _GetFontFamily(family, nStyle);\r
- CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));\r
- if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {\r
- match = MatchInstalledFonts(_TT_NormalizeName(SubstName));\r
- }\r
- if (match.IsEmpty() && iBaseFont >= 12) {\r
- if (!bCJK) {\r
- if (!CheckSupportThirdPartFont(family, PitchFamily)) {\r
- if (italic_angle != 0) {\r
- bItalic = TRUE;\r
- } else {\r
- bItalic = FALSE;\r
- }\r
- weight = old_weight;\r
- }\r
- } else {\r
- pSubstFont->m_bSubstOfCJK = TRUE;\r
- if (nStyle) {\r
- pSubstFont->m_WeightCJK = weight;\r
- } else {\r
- pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;\r
- }\r
- if (nStyle & FX_FONT_STYLE_Italic) {\r
- pSubstFont->m_bItlicCJK = TRUE;\r
- }\r
- }\r
- } else {\r
- italic_angle = 0;\r
- weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);\r
- }\r
- if (!match.IsEmpty() || iBaseFont < 12) {\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;\r
- if (!match.IsEmpty()) {\r
- family = match;\r
- }\r
- if (iBaseFont < 12) {\r
- if (nStyle && !(iBaseFont % 4)) {\r
- if ((nStyle & 0x3) == 1) {\r
- iBaseFont += 1;\r
- }\r
- if ((nStyle & 0x3) == 2) {\r
- iBaseFont += 3;\r
- }\r
- if ((nStyle & 0x3) == 3) {\r
- iBaseFont += 2;\r
- }\r
- }\r
- if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {\r
- if (m_FoxitFaces[iBaseFont]) {\r
- return m_FoxitFaces[iBaseFont];\r
- }\r
- m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,\r
- m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);\r
- if (m_FoxitFaces[iBaseFont]) {\r
- return m_FoxitFaces[iBaseFont];\r
- }\r
- } else {\r
- family = g_Base14FontNames[iBaseFont];\r
- }\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- }\r
- } else {\r
- if (flags & FXFONT_ITALIC) {\r
- bItalic = TRUE;\r
- }\r
- }\r
- bExact = !match.IsEmpty();\r
- void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, bExact);\r
- if (bExact) {\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;\r
- }\r
- if (hFont == NULL) {\r
- if (bCJK) {\r
- if (italic_angle != 0) {\r
- bItalic = TRUE;\r
- } else {\r
- bItalic = FALSE;\r
- }\r
- weight = old_weight;\r
- }\r
- if (!match.IsEmpty()) {\r
- hFont = m_pFontInfo->GetFont(match);\r
- if (hFont == NULL) {\r
- return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);\r
- }\r
- } else {\r
- if (Charset == FXFONT_SYMBOL_CHARSET) {\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_\r
- if (SubstName == FX_BSTRC("Symbol")) {\r
- pSubstFont->m_Family = "Chrome Symbol";\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;\r
- if (m_FoxitFaces[12]) {\r
- return m_FoxitFaces[12];\r
- }\r
- FX_LPCBYTE pFontData = NULL;\r
- FX_DWORD size = 0;\r
- m_pFontMgr->GetStandardFont(pFontData, size, 12);\r
- m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);\r
- return m_FoxitFaces[12];\r
- } else {\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;\r
- return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);\r
- }\r
-#else\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;\r
- return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);\r
-#endif\r
- }\r
- if (Charset == FXFONT_ANSI_CHARSET) {\r
- pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;\r
- return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);\r
- }\r
- int index = m_CharsetArray.Find(Charset);\r
- if (index < 0) {\r
- return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);\r
- } else {\r
- hFont = m_pFontInfo->GetFont(m_FaceArray[index]);\r
- }\r
- }\r
- }\r
- pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);\r
- if (hFont == NULL) {\r
- return NULL;\r
- }\r
- m_pFontInfo->GetFaceName(hFont, SubstName);\r
- if (Charset == FXFONT_DEFAULT_CHARSET) {\r
- m_pFontInfo->GetFontCharset(hFont, Charset);\r
- }\r
- FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);\r
- FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);\r
- if(font_size == 0 && ttc_size == 0) {\r
- m_pFontInfo->DeleteFont(hFont);\r
- return NULL;\r
- }\r
- FXFT_Face face = NULL;\r
- if (ttc_size) {\r
- FX_BYTE temp[1024];\r
- m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);\r
- FX_DWORD checksum = 0;\r
- for (int i = 0; i < 256; i ++) {\r
- checksum += ((FX_DWORD*)temp)[i];\r
- }\r
- FX_LPBYTE pFontData;\r
- face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData);\r
- if (face == NULL) {\r
- pFontData = FX_Alloc(FX_BYTE, ttc_size);\r
- if (pFontData) {\r
- m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);\r
- face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size,\r
- ttc_size - font_size);\r
- }\r
- }\r
- } else {\r
- FX_LPBYTE pFontData;\r
- face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);\r
- if (face == NULL) {\r
- pFontData = FX_Alloc(FX_BYTE, font_size);\r
- if (!pFontData) {\r
- m_pFontInfo->DeleteFont(hFont);\r
- return NULL;\r
- }\r
- m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);\r
- face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, font_size, m_pFontInfo->GetFaceIndex(hFont));\r
- }\r
- }\r
- if (face == NULL) {\r
- m_pFontInfo->DeleteFont(hFont);\r
- return NULL;\r
- }\r
- pSubstFont->m_Family = SubstName;\r
- pSubstFont->m_Charset = Charset;\r
- FX_BOOL bNeedUpdateWeight = FALSE;\r
- if (FXFT_Is_Face_Bold(face)) {\r
- if (weight == FXFONT_FW_BOLD) {\r
- bNeedUpdateWeight = FALSE;\r
- } else {\r
- bNeedUpdateWeight = TRUE;\r
- }\r
- } else {\r
- if (weight == FXFONT_FW_NORMAL) {\r
- bNeedUpdateWeight = FALSE;\r
- } else {\r
- bNeedUpdateWeight = TRUE;\r
- }\r
- }\r
- if (bNeedUpdateWeight) {\r
- pSubstFont->m_Weight = weight;\r
- }\r
- if (bItalic && !FXFT_Is_Face_Italic(face)) {\r
- if (italic_angle == 0) {\r
- italic_angle = -12;\r
- } else if (FXSYS_abs(italic_angle) < 5) {\r
- italic_angle = 0;\r
- }\r
- pSubstFont->m_ItalicAngle = italic_angle;\r
- }\r
- m_pFontInfo->DeleteFont(hFont);\r
- return face;\r
-}\r
-extern "C" {\r
- unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,\r
- unsigned char* buffer, unsigned long count);\r
- void _FTStreamClose(FXFT_Stream stream);\r
-};\r
-CFontFileFaceInfo::CFontFileFaceInfo()\r
-{\r
- m_pFile = NULL;\r
- m_Face = NULL;\r
- m_Charsets = 0;\r
- m_FileSize = 0;\r
- m_FontOffset = 0;\r
- m_Weight = 0;\r
- m_bItalic = FALSE;\r
- m_PitchFamily = 0;\r
-}\r
-CFontFileFaceInfo::~CFontFileFaceInfo()\r
-{\r
- if (m_Face) {\r
- FXFT_Done_Face(m_Face);\r
- }\r
- m_Face = NULL;\r
-}\r
-extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream);\r
-#if defined(_FPDFAPI_MINI_) || _FX_OS_ == _FX_ANDROID_\r
-IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault()\r
-{\r
- return NULL;\r
-}\r
-#endif\r
-#if !defined(_FPDFAPI_MINI_)\r
-CFX_FolderFontInfo::CFX_FolderFontInfo()\r
-{\r
-}\r
-CFX_FolderFontInfo::~CFX_FolderFontInfo()\r
-{\r
- FX_POSITION pos = m_FontList.GetStartPosition();\r
- while (pos) {\r
- CFX_ByteString key;\r
- FX_LPVOID value;\r
- m_FontList.GetNextAssoc(pos, key, value);\r
- delete (CFontFaceInfo*)value;\r
- }\r
-}\r
-void CFX_FolderFontInfo::AddPath(FX_BSTR path)\r
-{\r
- m_PathList.Add(path);\r
-}\r
-void CFX_FolderFontInfo::Release()\r
-{\r
- delete this;\r
-}\r
-FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper)\r
-{\r
- m_pMapper = pMapper;\r
- for (int i = 0; i < m_PathList.GetSize(); i ++) {\r
- ScanPath(m_PathList[i]);\r
- }\r
- return TRUE;\r
-}\r
-void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path)\r
-{\r
- void* handle = FX_OpenFolder(path);\r
- if (handle == NULL) {\r
- return;\r
- }\r
- CFX_ByteString filename;\r
- FX_BOOL bFolder;\r
- while (FX_GetNextFile(handle, filename, bFolder)) {\r
- if (bFolder) {\r
- if (filename == "." || filename == "..") {\r
- continue;\r
- }\r
- } else {\r
- CFX_ByteString ext = filename.Right(4);\r
- ext.MakeUpper();\r
- if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {\r
- continue;\r
- }\r
- }\r
- CFX_ByteString fullpath = path;\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
- fullpath += "\\";\r
-#else\r
- fullpath += "/";\r
-#endif\r
- fullpath += filename;\r
- if (bFolder) {\r
- ScanPath(fullpath);\r
- } else {\r
- ScanFile(fullpath);\r
- }\r
- }\r
- FX_CloseFolder(handle);\r
-}\r
-void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path)\r
-{\r
- FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");\r
- if (pFile == NULL) {\r
- return;\r
- }\r
- FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);\r
- FX_DWORD filesize = FXSYS_ftell(pFile);\r
- FX_BYTE buffer[16];\r
- FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);\r
- size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);\r
- if (GET_TT_LONG(buffer) == 0x74746366) {\r
- FX_DWORD nFaces = GET_TT_LONG(buffer + 8);\r
- FX_LPBYTE offsets = FX_Alloc(FX_BYTE, nFaces * 4);\r
- if (!offsets) {\r
- FXSYS_fclose(pFile);\r
- return;\r
- }\r
- readCnt = FXSYS_fread(offsets, nFaces * 4, 1, pFile);\r
- for (FX_DWORD i = 0; i < nFaces; i ++) {\r
- FX_LPBYTE p = offsets + i * 4;\r
- ReportFace(path, pFile, filesize, GET_TT_LONG(p));\r
- }\r
- FX_Free(offsets);\r
- } else {\r
- ReportFace(path, pFile, filesize, 0);\r
- }\r
- FXSYS_fclose(pFile);\r
-}\r
-void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, FXSYS_FILE* pFile, FX_DWORD filesize, FX_DWORD offset)\r
-{\r
- FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);\r
- char buffer[16];\r
- if (!FXSYS_fread(buffer, 12, 1, pFile)) {\r
- return;\r
- }\r
- FX_DWORD nTables = GET_TT_SHORT(buffer + 4);\r
- CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);\r
- CFX_ByteString names = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);\r
- CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);\r
- CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);\r
- if (style != "Regular") {\r
- facename += " " + style;\r
- }\r
- FX_LPVOID p;\r
- if (m_FontList.Lookup(facename, p)) {\r
- return;\r
- }\r
- CFontFaceInfo* pInfo = FX_NEW CFontFaceInfo;\r
- if (!pInfo) {\r
- return;\r
- }\r
- pInfo->m_FilePath = path;\r
- pInfo->m_FaceName = facename;\r
- pInfo->m_FontTables = tables;\r
- pInfo->m_FontOffset = offset;\r
- pInfo->m_FileSize = filesize;\r
- pInfo->m_Charsets = 0;\r
- CFX_ByteString os2 = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);\r
- if (os2.GetLength() >= 86) {\r
- FX_LPCBYTE p = (FX_LPCBYTE)os2 + 78;\r
- FX_DWORD codepages = GET_TT_LONG(p);\r
- if (codepages & (1 << 17)) {\r
- m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;\r
- }\r
- if (codepages & (1 << 18)) {\r
- m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_GB;\r
- }\r
- if (codepages & (1 << 20)) {\r
- m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_BIG5;\r
- }\r
- if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {\r
- m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;\r
- }\r
- if (codepages & (1 << 31)) {\r
- m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;\r
- }\r
- }\r
- m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);\r
- pInfo->m_Charsets |= CHARSET_FLAG_ANSI;\r
- pInfo->m_Styles = 0;\r
- if (style.Find(FX_BSTRC("Bold")) > -1) {\r
- pInfo->m_Styles |= FXFONT_BOLD;\r
- }\r
- if (style.Find(FX_BSTRC("Italic")) > -1 || style.Find(FX_BSTRC("Oblique")) > -1) {\r
- pInfo->m_Styles |= FXFONT_ITALIC;\r
- }\r
- if (facename.Find(FX_BSTRC("Serif")) > -1) {\r
- pInfo->m_Styles |= FXFONT_SERIF;\r
- }\r
- m_FontList.SetAt(facename, pInfo);\r
-}\r
-void* CFX_FolderFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL& bExact)\r
-{\r
- return NULL;\r
-}\r
-void* CFX_FolderFontInfo::GetFont(FX_LPCSTR face)\r
-{\r
- FX_LPVOID p;\r
- if (!m_FontList.Lookup(face, p)) {\r
- return NULL;\r
- }\r
- return p;\r
-}\r
-FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, FX_LPBYTE buffer, FX_DWORD size)\r
-{\r
- if (hFont == NULL) {\r
- return 0;\r
- }\r
- CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;\r
- FXSYS_FILE* pFile = NULL;\r
- if (size > 0) {\r
- pFile = FXSYS_fopen(pFont->m_FilePath, "rb");\r
- if (pFile == NULL) {\r
- return 0;\r
- }\r
- }\r
- FX_DWORD datasize = 0;\r
- FX_DWORD offset;\r
- if (table == 0) {\r
- datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;\r
- offset = 0;\r
- } else if (table == 0x74746366) {\r
- datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;\r
- offset = 0;\r
- } else {\r
- FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;\r
- for (FX_DWORD i = 0; i < nTables; i ++) {\r
- FX_LPCBYTE p = (FX_LPCBYTE)pFont->m_FontTables + i * 16;\r
- if (GET_TT_LONG(p) == table) {\r
- offset = GET_TT_LONG(p + 8);\r
- datasize = GET_TT_LONG(p + 12);\r
- }\r
- }\r
- }\r
- if (datasize && size >= datasize && pFile) {\r
- FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);\r
- size_t readCnt = FXSYS_fread(buffer, datasize, 1, pFile);\r
- }\r
- if (pFile) {\r
- FXSYS_fclose(pFile);\r
- }\r
- return datasize;\r
-}\r
-void CFX_FolderFontInfo::DeleteFont(void* hFont)\r
-{\r
-}\r
-FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name)\r
-{\r
- if (hFont == NULL) {\r
- return FALSE;\r
- }\r
- CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;\r
- name = pFont->m_FaceName;\r
- return TRUE;\r
-}\r
-FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset)\r
-{\r
- return FALSE;\r
-}\r
-#endif\r
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include <limits>
+
+#include "../../../include/fxge/fx_ge.h"
+#include "../../../include/fxge/fx_freetype.h"
+#include "../fontdata/chromefontdata/chromefontdata.h"
+#include "text_int.h"
+
+#define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1])
+#define GET_TT_LONG(w) \
+ (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
+
+namespace {
+
+CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name,
+ int weight,
+ FX_BOOL bItalic) {
+ CFX_ByteString key(face_name);
+ key += ',';
+ key += CFX_ByteString::FormatInteger(weight);
+ key += bItalic ? 'I' : 'N';
+ return key;
+}
+
+CFX_ByteString KeyNameFromSize(int ttc_size, FX_DWORD checksum) {
+ CFX_ByteString key;
+ key.Format("%d:%d", ttc_size, checksum);
+ return key;
+}
+
+} // namespace
+
+CFX_SubstFont::CFX_SubstFont() {
+ m_ExtHandle = NULL;
+ m_Charset = 0;
+ m_SubstFlags = 0;
+ m_Weight = 0;
+ m_ItalicAngle = 0;
+ m_bSubstOfCJK = FALSE;
+ m_WeightCJK = 0;
+ m_bItlicCJK = FALSE;
+}
+CTTFontDesc::~CTTFontDesc() {
+ if (m_Type == 1) {
+ if (m_SingleFace.m_pFace) {
+ FXFT_Done_Face(m_SingleFace.m_pFace);
+ }
+ } else if (m_Type == 2) {
+ for (int i = 0; i < 16; i++)
+ if (m_TTCFace.m_pFaces[i]) {
+ FXFT_Done_Face(m_TTCFace.m_pFaces[i]);
+ }
+ }
+ FX_Free(m_pFontData);
+}
+FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face) {
+ if (m_Type == 1) {
+ if (m_SingleFace.m_pFace != face) {
+ return FALSE;
+ }
+ } else if (m_Type == 2) {
+ int i;
+ for (i = 0; i < 16; i++)
+ if (m_TTCFace.m_pFaces[i] == face) {
+ break;
+ }
+ if (i == 16) {
+ return FALSE;
+ }
+ }
+ m_RefCount--;
+ if (m_RefCount) {
+ return FALSE;
+ }
+ delete this;
+ return TRUE;
+}
+CFX_FontMgr::CFX_FontMgr() : m_FTLibrary(nullptr) {
+ m_pBuiltinMapper = new CFX_FontMapper(this);
+ FXSYS_memset(m_ExternalFonts, 0, sizeof m_ExternalFonts);
+}
+CFX_FontMgr::~CFX_FontMgr() {
+ delete m_pBuiltinMapper;
+ FreeCache();
+ if (m_FTLibrary) {
+ FXFT_Done_FreeType(m_FTLibrary);
+ }
+}
+void CFX_FontMgr::InitFTLibrary() {
+ if (m_FTLibrary == NULL) {
+ FXFT_Init_FreeType(&m_FTLibrary);
+ }
+}
+void CFX_FontMgr::FreeCache() {
+ for (const auto& pair : m_FaceMap) {
+ delete pair.second;
+ }
+ m_FaceMap.clear();
+}
+void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) {
+ m_pBuiltinMapper->SetSystemFontInfo(pFontInfo);
+}
+FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name,
+ FX_BOOL bTrueType,
+ FX_DWORD flags,
+ int weight,
+ int italic_angle,
+ int CharsetCP,
+ CFX_SubstFont* pSubstFont) {
+ if (!m_FTLibrary) {
+ FXFT_Init_FreeType(&m_FTLibrary);
+ }
+ return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight,
+ italic_angle, CharsetCP, pSubstFont);
+}
+FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name,
+ int weight,
+ FX_BOOL bItalic,
+ uint8_t*& pFontData) {
+ auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic));
+ if (it == m_FaceMap.end())
+ return nullptr;
+
+ CTTFontDesc* pFontDesc = it->second;
+ pFontData = pFontDesc->m_pFontData;
+ pFontDesc->m_RefCount++;
+ return pFontDesc->m_SingleFace.m_pFace;
+}
+FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name,
+ int weight,
+ FX_BOOL bItalic,
+ uint8_t* pData,
+ FX_DWORD size,
+ int face_index) {
+ CTTFontDesc* pFontDesc = new CTTFontDesc;
+ pFontDesc->m_Type = 1;
+ pFontDesc->m_SingleFace.m_pFace = NULL;
+ pFontDesc->m_SingleFace.m_bBold = weight;
+ pFontDesc->m_SingleFace.m_bItalic = bItalic;
+ pFontDesc->m_pFontData = pData;
+ pFontDesc->m_RefCount = 1;
+ FXFT_Library library;
+ if (m_FTLibrary == NULL) {
+ FXFT_Init_FreeType(&m_FTLibrary);
+ }
+ library = m_FTLibrary;
+ int ret = FXFT_New_Memory_Face(library, pData, size, face_index,
+ &pFontDesc->m_SingleFace.m_pFace);
+ if (ret) {
+ delete pFontDesc;
+ return NULL;
+ }
+ ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64);
+ if (ret) {
+ delete pFontDesc;
+ return NULL;
+ }
+ m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc;
+ return pFontDesc->m_SingleFace.m_pFace;
+}
+const FX_CHAR* const g_Base14FontNames[14] = {
+ "Courier",
+ "Courier-Bold",
+ "Courier-BoldOblique",
+ "Courier-Oblique",
+ "Helvetica",
+ "Helvetica-Bold",
+ "Helvetica-BoldOblique",
+ "Helvetica-Oblique",
+ "Times-Roman",
+ "Times-Bold",
+ "Times-BoldItalic",
+ "Times-Italic",
+ "Symbol",
+ "ZapfDingbats",
+};
+const struct AltFontName {
+ const FX_CHAR* m_pName;
+ int m_Index;
+} g_AltFontNames[] = {
+ {"Arial", 4},
+ {"Arial,Bold", 5},
+ {"Arial,BoldItalic", 6},
+ {"Arial,Italic", 7},
+ {"Arial-Bold", 5},
+ {"Arial-BoldItalic", 6},
+ {"Arial-BoldItalicMT", 6},
+ {"Arial-BoldMT", 5},
+ {"Arial-Italic", 7},
+ {"Arial-ItalicMT", 7},
+ {"ArialBold", 5},
+ {"ArialBoldItalic", 6},
+ {"ArialItalic", 7},
+ {"ArialMT", 4},
+ {"ArialMT,Bold", 5},
+ {"ArialMT,BoldItalic", 6},
+ {"ArialMT,Italic", 7},
+ {"ArialRoundedMTBold", 5},
+ {"Courier", 0},
+ {"Courier,Bold", 1},
+ {"Courier,BoldItalic", 2},
+ {"Courier,Italic", 3},
+ {"Courier-Bold", 1},
+ {"Courier-BoldOblique", 2},
+ {"Courier-Oblique", 3},
+ {"CourierBold", 1},
+ {"CourierBoldItalic", 2},
+ {"CourierItalic", 3},
+ {"CourierNew", 0},
+ {"CourierNew,Bold", 1},
+ {"CourierNew,BoldItalic", 2},
+ {"CourierNew,Italic", 3},
+ {"CourierNew-Bold", 1},
+ {"CourierNew-BoldItalic", 2},
+ {"CourierNew-Italic", 3},
+ {"CourierNewBold", 1},
+ {"CourierNewBoldItalic", 2},
+ {"CourierNewItalic", 3},
+ {"CourierNewPS-BoldItalicMT", 2},
+ {"CourierNewPS-BoldMT", 1},
+ {"CourierNewPS-ItalicMT", 3},
+ {"CourierNewPSMT", 0},
+ {"CourierStd", 0},
+ {"CourierStd-Bold", 1},
+ {"CourierStd-BoldOblique", 2},
+ {"CourierStd-Oblique", 3},
+ {"Helvetica", 4},
+ {"Helvetica,Bold", 5},
+ {"Helvetica,BoldItalic", 6},
+ {"Helvetica,Italic", 7},
+ {"Helvetica-Bold", 5},
+ {"Helvetica-BoldItalic", 6},
+ {"Helvetica-BoldOblique", 6},
+ {"Helvetica-Italic", 7},
+ {"Helvetica-Oblique", 7},
+ {"HelveticaBold", 5},
+ {"HelveticaBoldItalic", 6},
+ {"HelveticaItalic", 7},
+ {"Symbol", 12},
+ {"SymbolMT", 12},
+ {"Times-Bold", 9},
+ {"Times-BoldItalic", 10},
+ {"Times-Italic", 11},
+ {"Times-Roman", 8},
+ {"TimesBold", 9},
+ {"TimesBoldItalic", 10},
+ {"TimesItalic", 11},
+ {"TimesNewRoman", 8},
+ {"TimesNewRoman,Bold", 9},
+ {"TimesNewRoman,BoldItalic", 10},
+ {"TimesNewRoman,Italic", 11},
+ {"TimesNewRoman-Bold", 9},
+ {"TimesNewRoman-BoldItalic", 10},
+ {"TimesNewRoman-Italic", 11},
+ {"TimesNewRomanBold", 9},
+ {"TimesNewRomanBoldItalic", 10},
+ {"TimesNewRomanItalic", 11},
+ {"TimesNewRomanPS", 8},
+ {"TimesNewRomanPS-Bold", 9},
+ {"TimesNewRomanPS-BoldItalic", 10},
+ {"TimesNewRomanPS-BoldItalicMT", 10},
+ {"TimesNewRomanPS-BoldMT", 9},
+ {"TimesNewRomanPS-Italic", 11},
+ {"TimesNewRomanPS-ItalicMT", 11},
+ {"TimesNewRomanPSMT", 8},
+ {"TimesNewRomanPSMT,Bold", 9},
+ {"TimesNewRomanPSMT,BoldItalic", 10},
+ {"TimesNewRomanPSMT,Italic", 11},
+ {"ZapfDingbats", 13},
+};
+extern "C" {
+static int compareString(const void* key, const void* element) {
+ return FXSYS_stricmp((const FX_CHAR*)key, ((AltFontName*)element)->m_pName);
+}
+}
+
+int GetTTCIndex(const uint8_t* pFontData,
+ FX_DWORD ttc_size,
+ FX_DWORD font_offset) {
+ int face_index = 0;
+ const uint8_t* p = pFontData + 8;
+ FX_DWORD nfont = GET_TT_LONG(p);
+ FX_DWORD index;
+ for (index = 0; index < nfont; index++) {
+ p = pFontData + 12 + index * 4;
+ if (GET_TT_LONG(p) == font_offset) {
+ break;
+ }
+ }
+ if (index >= nfont) {
+ face_index = 0;
+ } else {
+ face_index = index;
+ }
+ return face_index;
+}
+FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size,
+ FX_DWORD checksum,
+ int font_offset,
+ uint8_t*& pFontData) {
+ auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum));
+ if (it == m_FaceMap.end())
+ return nullptr;
+
+ CTTFontDesc* pFontDesc = it->second;
+ pFontData = pFontDesc->m_pFontData;
+ pFontDesc->m_RefCount++;
+ int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
+ if (!pFontDesc->m_TTCFace.m_pFaces[face_index]) {
+ pFontDesc->m_TTCFace.m_pFaces[face_index] =
+ GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
+ }
+ return pFontDesc->m_TTCFace.m_pFaces[face_index];
+}
+FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size,
+ FX_DWORD checksum,
+ uint8_t* pData,
+ FX_DWORD size,
+ int font_offset) {
+ CTTFontDesc* pFontDesc = new CTTFontDesc;
+ pFontDesc->m_Type = 2;
+ pFontDesc->m_pFontData = pData;
+ for (int i = 0; i < 16; i++) {
+ pFontDesc->m_TTCFace.m_pFaces[i] = NULL;
+ }
+ pFontDesc->m_RefCount++;
+ m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc;
+ int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
+ pFontDesc->m_TTCFace.m_pFaces[face_index] =
+ GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
+ return pFontDesc->m_TTCFace.m_pFaces[face_index];
+}
+FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData,
+ FX_DWORD size,
+ int face_index) {
+ FXFT_Library library;
+ if (m_FTLibrary == NULL) {
+ FXFT_Init_FreeType(&m_FTLibrary);
+ }
+ library = m_FTLibrary;
+ FXFT_Face face = NULL;
+ int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face);
+ if (ret) {
+ return NULL;
+ }
+ ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
+ if (ret) {
+ return NULL;
+ }
+ return face;
+}
+FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) {
+ FXFT_Library library;
+ if (m_FTLibrary == NULL) {
+ FXFT_Init_FreeType(&m_FTLibrary);
+ }
+ library = m_FTLibrary;
+ FXFT_Face face = NULL;
+ int ret = FXFT_New_Face(library, filename, face_index, &face);
+ if (ret) {
+ return NULL;
+ }
+ ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
+ if (ret) {
+ return NULL;
+ }
+ return face;
+}
+void CFX_FontMgr::ReleaseFace(FXFT_Face face) {
+ if (!face) {
+ return;
+ }
+ auto it = m_FaceMap.begin();
+ while (it != m_FaceMap.end()) {
+ auto temp = it++;
+ if (temp->second->ReleaseFace(face)) {
+ m_FaceMap.erase(temp);
+ }
+ }
+}
+const FoxitFonts g_FoxitFonts[14] = {
+ {g_FoxitFixedFontData, 17597},
+ {g_FoxitFixedBoldFontData, 18055},
+ {g_FoxitFixedBoldItalicFontData, 19151},
+ {g_FoxitFixedItalicFontData, 18746},
+ {g_FoxitSansFontData, 15025},
+ {g_FoxitSansBoldFontData, 16344},
+ {g_FoxitSansBoldItalicFontData, 16418},
+ {g_FoxitSansItalicFontData, 16339},
+ {g_FoxitSerifFontData, 19469},
+ {g_FoxitSerifBoldFontData, 19395},
+ {g_FoxitSerifBoldItalicFontData, 20733},
+ {g_FoxitSerifItalicFontData, 21227},
+ {g_FoxitSymbolFontData, 16729},
+ {g_FoxitDingbatsFontData, 29513},
+};
+FX_BOOL CFX_FontMgr::GetStandardFont(const uint8_t*& pFontData,
+ FX_DWORD& size,
+ int index) {
+ if (index > 15 || index < 0) {
+ return FALSE;
+ }
+ {
+ if (index >= 14) {
+ if (index == 14) {
+ pFontData = g_FoxitSerifMMFontData;
+ size = 113417;
+ } else {
+ pFontData = g_FoxitSansMMFontData;
+ size = 66919;
+ }
+ } else {
+ pFontData = g_FoxitFonts[index].m_pFontData;
+ size = g_FoxitFonts[index].m_dwSize;
+ }
+ }
+ return TRUE;
+}
+CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr)
+ : m_bListLoaded(FALSE),
+ m_pFontInfo(nullptr),
+ m_pFontEnumerator(nullptr),
+ m_pFontMgr(mgr) {
+ m_MMFaces[0] = nullptr;
+ m_MMFaces[1] = nullptr;
+ FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces));
+}
+CFX_FontMapper::~CFX_FontMapper() {
+ for (int i = 0; i < 14; i++)
+ if (m_FoxitFaces[i]) {
+ FXFT_Done_Face(m_FoxitFaces[i]);
+ }
+ if (m_MMFaces[0]) {
+ FXFT_Done_Face(m_MMFaces[0]);
+ }
+ if (m_MMFaces[1]) {
+ FXFT_Done_Face(m_MMFaces[1]);
+ }
+ if (m_pFontInfo) {
+ m_pFontInfo->Release();
+ }
+}
+void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) {
+ if (pFontInfo == NULL) {
+ return;
+ }
+ if (m_pFontInfo) {
+ m_pFontInfo->Release();
+ }
+ m_pFontInfo = pFontInfo;
+}
+static CFX_ByteString _TT_NormalizeName(const FX_CHAR* family) {
+ CFX_ByteString norm(family);
+ norm.Remove(' ');
+ norm.Remove('-');
+ norm.Remove(',');
+ int pos = norm.Find('+');
+ if (pos > 0) {
+ norm = norm.Left(pos);
+ }
+ norm.MakeLower();
+ return norm;
+}
+CFX_ByteString GetNameFromTT(const uint8_t* name_table, FX_DWORD name_id) {
+ const uint8_t* ptr = name_table + 2;
+ int name_count = GET_TT_SHORT(ptr);
+ int string_offset = GET_TT_SHORT(ptr + 2);
+ const uint8_t* string_ptr = name_table + string_offset;
+ ptr += 4;
+ for (int i = 0; i < name_count; i++) {
+ if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 &&
+ GET_TT_SHORT(ptr + 2) == 0) {
+ return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10),
+ GET_TT_SHORT(ptr + 8));
+ }
+ ptr += 12;
+ }
+ return CFX_ByteString();
+}
+static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile,
+ FX_DWORD size) {
+ CFX_ByteString buffer;
+ if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) {
+ return CFX_ByteString();
+ }
+ buffer.ReleaseBuffer(size);
+ return buffer;
+}
+CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile,
+ const uint8_t* pTables,
+ FX_DWORD nTables,
+ FX_DWORD tag) {
+ for (FX_DWORD i = 0; i < nTables; i++) {
+ const uint8_t* p = pTables + i * 16;
+ if (GET_TT_LONG(p) == tag) {
+ FX_DWORD offset = GET_TT_LONG(p + 8);
+ FX_DWORD size = GET_TT_LONG(p + 12);
+ FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
+ return _FPDF_ReadStringFromFile(pFile, size);
+ }
+ }
+ return CFX_ByteString();
+}
+CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile,
+ const uint8_t* pTables,
+ FX_DWORD nTables,
+ FX_DWORD tag) {
+ for (FX_DWORD i = 0; i < nTables; i++) {
+ const uint8_t* p = pTables + i * 16;
+ if (GET_TT_LONG(p) == tag) {
+ FX_DWORD offset = GET_TT_LONG(p + 8);
+ FX_DWORD size = GET_TT_LONG(p + 12);
+ CFX_ByteString buffer;
+ if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) {
+ return CFX_ByteString();
+ }
+ buffer.ReleaseBuffer(size);
+ return buffer;
+ }
+ }
+ return CFX_ByteString();
+}
+CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) {
+ if (m_pFontInfo == NULL) {
+ return CFX_ByteString();
+ }
+ CFX_ByteString result;
+ FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0);
+ if (size) {
+ uint8_t* buffer = FX_Alloc(uint8_t, size);
+ m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);
+ result = GetNameFromTT(buffer, 6);
+ FX_Free(buffer);
+ }
+ return result;
+}
+void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) {
+ if (m_pFontInfo == NULL) {
+ return;
+ }
+ if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {
+ m_CharsetArray.Add((FX_DWORD)charset);
+ m_FaceArray.Add(name);
+ }
+ if (name == m_LastFamily) {
+ return;
+ }
+ const uint8_t* ptr = name;
+ FX_BOOL bLocalized = FALSE;
+ for (int i = 0; i < name.GetLength(); i++)
+ if (ptr[i] > 0x80) {
+ bLocalized = TRUE;
+ break;
+ }
+ if (bLocalized) {
+ void* hFont = m_pFontInfo->GetFont(name);
+ if (hFont == NULL) {
+ int iExact;
+ hFont =
+ m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact);
+ if (hFont == NULL) {
+ return;
+ }
+ }
+ CFX_ByteString new_name = GetPSNameFromTT(hFont);
+ if (!new_name.IsEmpty()) {
+ new_name.Insert(0, ' ');
+ m_InstalledTTFonts.Add(new_name);
+ }
+ m_pFontInfo->DeleteFont(hFont);
+ }
+ m_InstalledTTFonts.Add(name);
+ m_LastFamily = name;
+}
+void CFX_FontMapper::LoadInstalledFonts() {
+ if (m_pFontInfo == NULL) {
+ return;
+ }
+ if (m_bListLoaded) {
+ return;
+ }
+ if (m_bListLoaded) {
+ return;
+ }
+ m_pFontInfo->EnumFontList(this);
+ m_bListLoaded = TRUE;
+}
+CFX_ByteString CFX_FontMapper::MatchInstalledFonts(
+ const CFX_ByteString& norm_name) {
+ LoadInstalledFonts();
+ int i;
+ for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i--) {
+ CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);
+ if (norm1 == norm_name) {
+ break;
+ }
+ }
+ if (i < 0) {
+ return CFX_ByteString();
+ }
+ CFX_ByteString match = m_InstalledTTFonts[i];
+ if (match[0] == ' ') {
+ match = m_InstalledTTFonts[i + 1];
+ }
+ return match;
+}
+typedef struct _CHARSET_MAP_ {
+ uint8_t charset;
+ FX_WORD codepage;
+} CHARSET_MAP;
+static const CHARSET_MAP g_Codepage2CharsetTable[] = {
+ {1, 0}, {2, 42}, {254, 437}, {255, 850}, {222, 874},
+ {128, 932}, {134, 936}, {129, 949}, {136, 950}, {238, 1250},
+ {204, 1251}, {0, 1252}, {161, 1253}, {162, 1254}, {177, 1255},
+ {178, 1256}, {186, 1257}, {163, 1258}, {130, 1361}, {77, 10000},
+ {78, 10001}, {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005},
+ {84, 10004}, {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029},
+ {89, 10007},
+};
+uint8_t _GetCharsetFromCodePage(FX_WORD codepage) {
+ int32_t iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ int32_t iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const CHARSET_MAP& cp = g_Codepage2CharsetTable[iMid];
+ if (codepage == cp.codepage) {
+ return cp.charset;
+ }
+ if (codepage < cp.codepage) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 1;
+}
+FX_DWORD _GetCodePageRangeFromCharset(int charset) {
+ if (charset == FXFONT_EASTEUROPE_CHARSET) {
+ return 1 << 1;
+ }
+ if (charset == FXFONT_GREEK_CHARSET) {
+ return 1 << 3;
+ }
+ if (charset == FXFONT_TURKISH_CHARSET) {
+ return 1 << 4;
+ }
+ if (charset == FXFONT_HEBREW_CHARSET) {
+ return 1 << 5;
+ }
+ if (charset == FXFONT_ARABIC_CHARSET) {
+ return 1 << 6;
+ }
+ if (charset == FXFONT_BALTIC_CHARSET) {
+ return 1 << 7;
+ }
+ if (charset == FXFONT_THAI_CHARSET) {
+ return 1 << 16;
+ }
+ if (charset == FXFONT_SHIFTJIS_CHARSET) {
+ return 1 << 17;
+ }
+ if (charset == FXFONT_GB2312_CHARSET) {
+ return 1 << 18;
+ }
+ if (charset == FXFONT_CHINESEBIG5_CHARSET) {
+ return 1 << 20;
+ }
+ if (charset == FXFONT_HANGEUL_CHARSET) {
+ return 1 << 19;
+ }
+ if (charset == FXFONT_SYMBOL_CHARSET) {
+ return 1 << 31;
+ }
+ return 1 << 21;
+}
+FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont,
+ int iBaseFont,
+ int italic_angle,
+ int weight,
+ int picthfamily) {
+ if (iBaseFont < 12) {
+ if (m_FoxitFaces[iBaseFont]) {
+ return m_FoxitFaces[iBaseFont];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size = 0;
+ if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
+ m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_FoxitFaces[iBaseFont];
+ }
+ }
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
+ pSubstFont->m_ItalicAngle = italic_angle;
+ if (weight) {
+ pSubstFont->m_Weight = weight;
+ }
+ if (picthfamily & FXFONT_FF_ROMAN) {
+ pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
+ pSubstFont->m_Family = "Chrome Serif";
+ if (m_MMFaces[1]) {
+ return m_MMFaces[1];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size;
+ m_pFontMgr->GetStandardFont(pFontData, size, 14);
+ m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_MMFaces[1];
+ }
+ pSubstFont->m_Family = "Chrome Sans";
+ if (m_MMFaces[0]) {
+ return m_MMFaces[0];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size = 0;
+ m_pFontMgr->GetStandardFont(pFontData, size, 15);
+ m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_MMFaces[0];
+}
+const struct _AltFontFamily {
+ const FX_CHAR* m_pFontName;
+ const FX_CHAR* m_pFontFamily;
+} g_AltFontFamilies[] = {
+ {"AGaramondPro", "Adobe Garamond Pro"},
+ {"BankGothicBT-Medium", "BankGothic Md BT"},
+ {"ForteMT", "Forte"},
+};
+extern "C" {
+static int compareFontFamilyString(const void* key, const void* element) {
+ CFX_ByteString str_key((const FX_CHAR*)key);
+ if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
+ return 0;
+ }
+ return FXSYS_stricmp((const FX_CHAR*)key,
+ ((_AltFontFamily*)element)->m_pFontName);
+}
+}
+#define FX_FONT_STYLE_None 0x00
+#define FX_FONT_STYLE_Bold 0x01
+#define FX_FONT_STYLE_Italic 0x02
+#define FX_FONT_STYLE_BoldBold 0x04
+static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle) {
+ if (fontName.Find("Script") >= 0) {
+ if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
+ fontName = "ScriptMTBold";
+ } else if (fontName.Find("Palace") >= 0) {
+ fontName = "PalaceScriptMT";
+ } else if (fontName.Find("French") >= 0) {
+ fontName = "FrenchScriptMT";
+ } else if (fontName.Find("FreeStyle") >= 0) {
+ fontName = "FreeStyleScript";
+ }
+ return fontName;
+ }
+ _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(
+ fontName.c_str(), g_AltFontFamilies,
+ sizeof g_AltFontFamilies / sizeof(_AltFontFamily), sizeof(_AltFontFamily),
+ compareFontFamilyString);
+ if (found == NULL) {
+ return fontName;
+ }
+ return found->m_pFontFamily;
+};
+typedef struct _FX_FontStyle {
+ const FX_CHAR* style;
+ int32_t len;
+} FX_FontStyle;
+const FX_FontStyle g_FontStyles[] = {
+ {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7},
+};
+CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) {
+ CFX_ByteTextBuf buf;
+ if (!iLen || iLen <= iIndex) {
+ return buf.GetByteString();
+ }
+ while (iIndex < iLen) {
+ if (pStyle[iIndex] == ',') {
+ break;
+ }
+ buf.AppendChar(pStyle[iIndex]);
+ ++iIndex;
+ }
+ return buf.GetByteString();
+}
+int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) {
+ int32_t iLen = bsStyle.GetLength();
+ if (!iLen) {
+ return -1;
+ }
+ int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
+ const FX_FontStyle* pStyle = NULL;
+ for (int i = iSize - 1; i >= 0; --i) {
+ pStyle = g_FontStyles + i;
+ if (!pStyle || pStyle->len > iLen) {
+ continue;
+ }
+ if (!bRevert) {
+ if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
+ return i;
+ }
+ } else {
+ if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) {
+ if (name == FX_BSTRC("MyriadPro")) {
+ PitchFamily &= ~FXFONT_FF_ROMAN;
+ return TRUE;
+ }
+ return FALSE;
+}
+FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name,
+ FX_BOOL bTrueType,
+ FX_DWORD flags,
+ int weight,
+ int italic_angle,
+ int WindowCP,
+ CFX_SubstFont* pSubstFont) {
+ if (!(flags & FXFONT_USEEXTERNATTR)) {
+ weight = FXFONT_FW_NORMAL;
+ italic_angle = 0;
+ }
+ CFX_ByteString SubstName = name;
+ SubstName.Remove(0x20);
+ if (bTrueType) {
+ if (name[0] == '@') {
+ SubstName = name.Mid(1);
+ }
+ }
+ PDF_GetStandardFontName(&SubstName);
+ if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
+ pSubstFont->m_Family = "Chrome Symbol";
+ pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ if (m_FoxitFaces[12]) {
+ return m_FoxitFaces[12];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size = 0;
+ m_pFontMgr->GetStandardFont(pFontData, size, 12);
+ m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_FoxitFaces[12];
+ }
+ if (SubstName == FX_BSTRC("ZapfDingbats")) {
+ pSubstFont->m_Family = "Chrome Dingbats";
+ pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ if (m_FoxitFaces[13]) {
+ return m_FoxitFaces[13];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size = 0;
+ m_pFontMgr->GetStandardFont(pFontData, size, 13);
+ m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_FoxitFaces[13];
+ }
+ int iBaseFont = 0;
+ CFX_ByteString family, style;
+ FX_BOOL bHasComma = FALSE;
+ FX_BOOL bHasHypen = FALSE;
+ int find = SubstName.Find(FX_BSTRC(","), 0);
+ if (find >= 0) {
+ family = SubstName.Left(find);
+ PDF_GetStandardFontName(&family);
+ style = SubstName.Mid(find + 1);
+ bHasComma = TRUE;
+ } else {
+ family = SubstName;
+ }
+ for (; iBaseFont < 12; iBaseFont++)
+ if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
+ break;
+ }
+ int PitchFamily = 0;
+ FX_BOOL bItalic = FALSE;
+ FX_DWORD nStyle = 0;
+ FX_BOOL bStyleAvail = FALSE;
+ if (iBaseFont < 12) {
+ family = g_Base14FontNames[iBaseFont];
+ if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
+ nStyle |= FX_FONT_STYLE_Bold;
+ }
+ if ((iBaseFont % 4) / 2) {
+ nStyle |= FX_FONT_STYLE_Italic;
+ }
+ if (iBaseFont < 4) {
+ PitchFamily |= FXFONT_FF_FIXEDPITCH;
+ }
+ if (iBaseFont >= 8) {
+ PitchFamily |= FXFONT_FF_ROMAN;
+ }
+ } else {
+ if (!bHasComma) {
+ find = family.ReverseFind('-');
+ if (find >= 0) {
+ style = family.Mid(find + 1);
+ family = family.Left(find);
+ bHasHypen = TRUE;
+ }
+ }
+ if (!bHasHypen) {
+ int nLen = family.GetLength();
+ int32_t nRet = GetStyleType(family, TRUE);
+ if (nRet > -1) {
+ family = family.Left(nLen - g_FontStyles[nRet].len);
+ if (nRet == 0) {
+ nStyle |= FX_FONT_STYLE_Bold;
+ }
+ if (nRet == 1) {
+ nStyle |= FX_FONT_STYLE_Italic;
+ }
+ if (nRet == 2) {
+ nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
+ }
+ }
+ }
+ if (flags & FXFONT_SERIF) {
+ PitchFamily |= FXFONT_FF_ROMAN;
+ }
+ if (flags & FXFONT_SCRIPT) {
+ PitchFamily |= FXFONT_FF_SCRIPT;
+ }
+ if (flags & FXFONT_FIXED_PITCH) {
+ PitchFamily |= FXFONT_FF_FIXEDPITCH;
+ }
+ }
+ if (!style.IsEmpty()) {
+ int nLen = style.GetLength();
+ const FX_CHAR* pStyle = style;
+ int i = 0;
+ FX_BOOL bFirstItem = TRUE;
+ CFX_ByteString buf;
+ while (i < nLen) {
+ buf = ParseStyle(pStyle, nLen, i);
+ int32_t nRet = GetStyleType(buf, FALSE);
+ if ((i && !bStyleAvail) || (!i && nRet < 0)) {
+ family = SubstName;
+ iBaseFont = 12;
+ break;
+ } else if (nRet >= 0) {
+ bStyleAvail = TRUE;
+ }
+ if (nRet == 0) {
+ if (nStyle & FX_FONT_STYLE_Bold) {
+ nStyle |= FX_FONT_STYLE_BoldBold;
+ } else {
+ nStyle |= FX_FONT_STYLE_Bold;
+ }
+ bFirstItem = FALSE;
+ }
+ if (nRet == 1) {
+ if (bFirstItem) {
+ nStyle |= FX_FONT_STYLE_Italic;
+ } else {
+ family = SubstName;
+ iBaseFont = 12;
+ }
+ break;
+ }
+ if (nRet == 2) {
+ nStyle |= FX_FONT_STYLE_Italic;
+ if (nStyle & FX_FONT_STYLE_Bold) {
+ nStyle |= FX_FONT_STYLE_BoldBold;
+ } else {
+ nStyle |= FX_FONT_STYLE_Bold;
+ }
+ bFirstItem = FALSE;
+ }
+ i += buf.GetLength() + 1;
+ }
+ }
+ weight = weight ? weight : FXFONT_FW_NORMAL;
+ int old_weight = weight;
+ if (nStyle) {
+ weight =
+ nStyle & FX_FONT_STYLE_BoldBold
+ ? 900
+ : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
+ }
+ if (nStyle & FX_FONT_STYLE_Italic) {
+ bItalic = TRUE;
+ }
+ FX_BOOL bCJK = FALSE;
+ int iExact = 0;
+ int Charset = FXFONT_ANSI_CHARSET;
+ if (WindowCP) {
+ Charset = _GetCharsetFromCodePage(WindowCP);
+ } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
+ Charset = FXFONT_SYMBOL_CHARSET;
+ }
+ if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
+ Charset == FXFONT_HANGEUL_CHARSET ||
+ Charset == FXFONT_CHINESEBIG5_CHARSET) {
+ bCJK = TRUE;
+ }
+ if (m_pFontInfo == NULL) {
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
+ PitchFamily);
+ }
+ family = _GetFontFamily(family, nStyle);
+ CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
+ if (match.IsEmpty() && family != SubstName &&
+ (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
+ match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
+ }
+ if (match.IsEmpty() && iBaseFont >= 12) {
+ if (!bCJK) {
+ if (!CheckSupportThirdPartFont(family, PitchFamily)) {
+ if (italic_angle != 0) {
+ bItalic = TRUE;
+ } else {
+ bItalic = FALSE;
+ }
+ weight = old_weight;
+ }
+ } else {
+ pSubstFont->m_bSubstOfCJK = TRUE;
+ if (nStyle) {
+ pSubstFont->m_WeightCJK = weight;
+ } else {
+ pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
+ }
+ if (nStyle & FX_FONT_STYLE_Italic) {
+ pSubstFont->m_bItlicCJK = TRUE;
+ }
+ }
+ } else {
+ italic_angle = 0;
+ weight =
+ nStyle & FX_FONT_STYLE_BoldBold
+ ? 900
+ : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
+ }
+ if (!match.IsEmpty() || iBaseFont < 12) {
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
+ if (!match.IsEmpty()) {
+ family = match;
+ }
+ if (iBaseFont < 12) {
+ if (nStyle && !(iBaseFont % 4)) {
+ if ((nStyle & 0x3) == 1) {
+ iBaseFont += 1;
+ }
+ if ((nStyle & 0x3) == 2) {
+ iBaseFont += 3;
+ }
+ if ((nStyle & 0x3) == 3) {
+ iBaseFont += 2;
+ }
+ }
+ if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
+ if (m_FoxitFaces[iBaseFont]) {
+ return m_FoxitFaces[iBaseFont];
+ }
+ m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(
+ m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
+ m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
+ if (m_FoxitFaces[iBaseFont]) {
+ return m_FoxitFaces[iBaseFont];
+ }
+ } else {
+ family = g_Base14FontNames[iBaseFont];
+ }
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ }
+ } else {
+ if (flags & FXFONT_ITALIC) {
+ bItalic = TRUE;
+ }
+ }
+ iExact = !match.IsEmpty();
+ void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily,
+ family, iExact);
+ if (iExact) {
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
+ }
+ if (hFont == NULL) {
+ if (bCJK) {
+ if (italic_angle != 0) {
+ bItalic = TRUE;
+ } else {
+ bItalic = FALSE;
+ }
+ weight = old_weight;
+ }
+ if (!match.IsEmpty()) {
+ hFont = m_pFontInfo->GetFont(match);
+ if (hFont == NULL) {
+ return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
+ PitchFamily);
+ }
+ } else {
+ if (Charset == FXFONT_SYMBOL_CHARSET) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
+ _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
+ if (SubstName == FX_BSTRC("Symbol")) {
+ pSubstFont->m_Family = "Chrome Symbol";
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
+ if (m_FoxitFaces[12]) {
+ return m_FoxitFaces[12];
+ }
+ const uint8_t* pFontData = NULL;
+ FX_DWORD size = 0;
+ m_pFontMgr->GetStandardFont(pFontData, size, 12);
+ m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
+ return m_FoxitFaces[12];
+ }
+#endif
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
+ return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC,
+ weight, italic_angle, 0, pSubstFont);
+ }
+ if (Charset == FXFONT_ANSI_CHARSET) {
+ pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
+ return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
+ PitchFamily);
+ }
+ int index = m_CharsetArray.Find(Charset);
+ if (index < 0) {
+ return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
+ PitchFamily);
+ }
+ hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
+ }
+ }
+ pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
+ if (hFont == NULL) {
+ return NULL;
+ }
+ m_pFontInfo->GetFaceName(hFont, SubstName);
+ if (Charset == FXFONT_DEFAULT_CHARSET) {
+ m_pFontInfo->GetFontCharset(hFont, Charset);
+ }
+ FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
+ FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
+ if (font_size == 0 && ttc_size == 0) {
+ m_pFontInfo->DeleteFont(hFont);
+ return NULL;
+ }
+ FXFT_Face face = NULL;
+ if (ttc_size) {
+ uint8_t temp[1024];
+ m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
+ FX_DWORD checksum = 0;
+ for (int i = 0; i < 256; i++) {
+ checksum += ((FX_DWORD*)temp)[i];
+ }
+ uint8_t* pFontData;
+ face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum,
+ ttc_size - font_size, pFontData);
+ if (face == NULL) {
+ pFontData = FX_Alloc(uint8_t, ttc_size);
+ m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
+ face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData,
+ ttc_size, ttc_size - font_size);
+ }
+ } else {
+ uint8_t* pFontData;
+ face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
+ if (face == NULL) {
+ pFontData = FX_Alloc(uint8_t, font_size);
+ m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
+ face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData,
+ font_size,
+ m_pFontInfo->GetFaceIndex(hFont));
+ }
+ }
+ if (face == NULL) {
+ m_pFontInfo->DeleteFont(hFont);
+ return NULL;
+ }
+ pSubstFont->m_Family = SubstName;
+ pSubstFont->m_Charset = Charset;
+ FX_BOOL bNeedUpdateWeight = FALSE;
+ if (FXFT_Is_Face_Bold(face)) {
+ if (weight == FXFONT_FW_BOLD) {
+ bNeedUpdateWeight = FALSE;
+ } else {
+ bNeedUpdateWeight = TRUE;
+ }
+ } else {
+ if (weight == FXFONT_FW_NORMAL) {
+ bNeedUpdateWeight = FALSE;
+ } else {
+ bNeedUpdateWeight = TRUE;
+ }
+ }
+ if (bNeedUpdateWeight) {
+ pSubstFont->m_Weight = weight;
+ }
+ if (bItalic && !FXFT_Is_Face_Italic(face)) {
+ if (italic_angle == 0) {
+ italic_angle = -12;
+ } else if (FXSYS_abs(italic_angle) < 5) {
+ italic_angle = 0;
+ }
+ pSubstFont->m_ItalicAngle = italic_angle;
+ }
+ m_pFontInfo->DeleteFont(hFont);
+ return face;
+}
+extern "C" {
+unsigned long _FTStreamRead(FXFT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count);
+void _FTStreamClose(FXFT_Stream stream);
+};
+CFontFileFaceInfo::CFontFileFaceInfo() {
+ m_pFile = NULL;
+ m_Face = NULL;
+ m_Charsets = 0;
+ m_FileSize = 0;
+ m_FontOffset = 0;
+ m_Weight = 0;
+ m_bItalic = FALSE;
+ m_PitchFamily = 0;
+}
+CFontFileFaceInfo::~CFontFileFaceInfo() {
+ if (m_Face) {
+ FXFT_Done_Face(m_Face);
+ }
+ m_Face = NULL;
+}
+#if _FX_OS_ == _FX_ANDROID_
+IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
+ return NULL;
+}
+#endif
+CFX_FolderFontInfo::CFX_FolderFontInfo() {}
+CFX_FolderFontInfo::~CFX_FolderFontInfo() {
+ for (const auto& pair : m_FontList) {
+ delete pair.second;
+ }
+}
+void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) {
+ m_PathList.Add(path);
+}
+void CFX_FolderFontInfo::Release() {
+ delete this;
+}
+FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) {
+ m_pMapper = pMapper;
+ for (int i = 0; i < m_PathList.GetSize(); i++) {
+ ScanPath(m_PathList[i]);
+ }
+ return TRUE;
+}
+void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path) {
+ void* handle = FX_OpenFolder(path);
+ if (handle == NULL) {
+ return;
+ }
+ CFX_ByteString filename;
+ FX_BOOL bFolder;
+ while (FX_GetNextFile(handle, filename, bFolder)) {
+ if (bFolder) {
+ if (filename == "." || filename == "..") {
+ continue;
+ }
+ } else {
+ CFX_ByteString ext = filename.Right(4);
+ ext.MakeUpper();
+ if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
+ continue;
+ }
+ }
+ CFX_ByteString fullpath = path;
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ fullpath += "\\";
+#else
+ fullpath += "/";
+#endif
+ fullpath += filename;
+ if (bFolder) {
+ ScanPath(fullpath);
+ } else {
+ ScanFile(fullpath);
+ }
+ }
+ FX_CloseFolder(handle);
+}
+void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path) {
+ FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
+ if (pFile == NULL) {
+ return;
+ }
+ FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
+ FX_DWORD filesize = FXSYS_ftell(pFile);
+ uint8_t buffer[16];
+ FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
+ size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
+ if (readCnt != 1) {
+ FXSYS_fclose(pFile);
+ return;
+ }
+
+ if (GET_TT_LONG(buffer) == 0x74746366) {
+ FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
+ if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) {
+ FXSYS_fclose(pFile);
+ return;
+ }
+ FX_DWORD face_bytes = nFaces * 4;
+ uint8_t* offsets = FX_Alloc(uint8_t, face_bytes);
+ readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile);
+ if (readCnt != face_bytes) {
+ FX_Free(offsets);
+ FXSYS_fclose(pFile);
+ return;
+ }
+ for (FX_DWORD i = 0; i < nFaces; i++) {
+ uint8_t* p = offsets + i * 4;
+ ReportFace(path, pFile, filesize, GET_TT_LONG(p));
+ }
+ FX_Free(offsets);
+ } else {
+ ReportFace(path, pFile, filesize, 0);
+ }
+ FXSYS_fclose(pFile);
+}
+void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path,
+ FXSYS_FILE* pFile,
+ FX_DWORD filesize,
+ FX_DWORD offset) {
+ FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
+ char buffer[16];
+ if (!FXSYS_fread(buffer, 12, 1, pFile)) {
+ return;
+ }
+ FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
+ CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
+ if (tables.IsEmpty()) {
+ return;
+ }
+ CFX_ByteString names =
+ _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
+ CFX_ByteString facename = GetNameFromTT(names, 1);
+ CFX_ByteString style = GetNameFromTT(names, 2);
+ if (style != "Regular") {
+ facename += " " + style;
+ }
+ if (m_FontList.find(facename) != m_FontList.end()) {
+ return;
+ }
+ CFX_FontFaceInfo* pInfo =
+ new CFX_FontFaceInfo(path, facename, tables, offset, filesize);
+ CFX_ByteString os2 =
+ _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
+ if (os2.GetLength() >= 86) {
+ const uint8_t* p = (const uint8_t*)os2 + 78;
+ FX_DWORD codepages = GET_TT_LONG(p);
+ if (codepages & (1 << 17)) {
+ m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
+ }
+ if (codepages & (1 << 18)) {
+ m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_GB;
+ }
+ if (codepages & (1 << 20)) {
+ m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
+ }
+ if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
+ m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
+ }
+ if (codepages & (1 << 31)) {
+ m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
+ }
+ }
+ m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
+ pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
+ pInfo->m_Styles = 0;
+ if (style.Find(FX_BSTRC("Bold")) > -1) {
+ pInfo->m_Styles |= FXFONT_BOLD;
+ }
+ if (style.Find(FX_BSTRC("Italic")) > -1 ||
+ style.Find(FX_BSTRC("Oblique")) > -1) {
+ pInfo->m_Styles |= FXFONT_ITALIC;
+ }
+ if (facename.Find(FX_BSTRC("Serif")) > -1) {
+ pInfo->m_Styles |= FXFONT_SERIF;
+ }
+ m_FontList[facename] = pInfo;
+}
+static const struct {
+ const FX_CHAR* m_pName;
+ const FX_CHAR* m_pSubstName;
+} Base14Substs[] = {
+ {"Courier", "Courier New"},
+ {"Courier-Bold", "Courier New Bold"},
+ {"Courier-BoldOblique", "Courier New Bold Italic"},
+ {"Courier-Oblique", "Courier New Italic"},
+ {"Helvetica", "Arial"},
+ {"Helvetica-Bold", "Arial Bold"},
+ {"Helvetica-BoldOblique", "Arial Bold Italic"},
+ {"Helvetica-Oblique", "Arial Italic"},
+ {"Times-Roman", "Times New Roman"},
+ {"Times-Bold", "Times New Roman Bold"},
+ {"Times-BoldItalic", "Times New Roman Bold Italic"},
+ {"Times-Italic", "Times New Roman Italic"},
+};
+void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) {
+ for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs);
+ iBaseFont++) {
+ if (face == Base14Substs[iBaseFont].m_pName) {
+ return GetFont(Base14Substs[iBaseFont].m_pSubstName);
+ }
+ }
+ return nullptr;
+}
+static FX_DWORD _GetCharset(int charset) {
+ switch (charset) {
+ case FXFONT_SHIFTJIS_CHARSET:
+ return CHARSET_FLAG_SHIFTJIS;
+ case FXFONT_GB2312_CHARSET:
+ return CHARSET_FLAG_GB;
+ case FXFONT_CHINESEBIG5_CHARSET:
+ return CHARSET_FLAG_BIG5;
+ case FXFONT_HANGEUL_CHARSET:
+ return CHARSET_FLAG_KOREAN;
+ case FXFONT_SYMBOL_CHARSET:
+ return CHARSET_FLAG_SYMBOL;
+ case FXFONT_ANSI_CHARSET:
+ return CHARSET_FLAG_ANSI;
+ default:
+ break;
+ }
+ return 0;
+}
+static int32_t _GetSimilarValue(int weight,
+ FX_BOOL bItalic,
+ int pitch_family,
+ FX_DWORD style) {
+ int32_t iSimilarValue = 0;
+ if ((style & FXFONT_BOLD) == (weight > 400)) {
+ iSimilarValue += 16;
+ }
+ if ((style & FXFONT_ITALIC) == bItalic) {
+ iSimilarValue += 16;
+ }
+ if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) {
+ iSimilarValue += 16;
+ }
+ if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) {
+ iSimilarValue += 8;
+ }
+ if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) {
+ iSimilarValue += 8;
+ }
+ return iSimilarValue;
+}
+void* CFX_FolderFontInfo::FindFont(int weight,
+ FX_BOOL bItalic,
+ int charset,
+ int pitch_family,
+ const FX_CHAR* family,
+ FX_BOOL bMatchName) {
+ CFX_FontFaceInfo* pFind = nullptr;
+ if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
+ return GetFont("Courier New");
+ }
+ FX_DWORD charset_flag = _GetCharset(charset);
+ int32_t iBestSimilar = 0;
+ for (const auto& it : m_FontList) {
+ const CFX_ByteString& bsName = it.first;
+ CFX_FontFaceInfo* pFont = it.second;
+ if (!(pFont->m_Charsets & charset_flag) &&
+ charset != FXFONT_DEFAULT_CHARSET) {
+ continue;
+ }
+ int32_t index = bsName.Find(family);
+ if (bMatchName && index < 0) {
+ continue;
+ }
+ int32_t iSimilarValue =
+ _GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
+ if (iSimilarValue > iBestSimilar) {
+ iBestSimilar = iSimilarValue;
+ pFind = pFont;
+ }
+ }
+ return pFind;
+}
+void* CFX_FolderFontInfo::MapFont(int weight,
+ FX_BOOL bItalic,
+ int charset,
+ int pitch_family,
+ const FX_CHAR* family,
+ int& iExact) {
+ return NULL;
+}
+void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) {
+ auto it = m_FontList.find(face);
+ return it != m_FontList.end() ? it->second : nullptr;
+}
+FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont,
+ FX_DWORD table,
+ uint8_t* buffer,
+ FX_DWORD size) {
+ if (hFont == NULL) {
+ return 0;
+ }
+ CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
+ FXSYS_FILE* pFile = NULL;
+ if (size > 0) {
+ pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
+ if (pFile == NULL) {
+ return 0;
+ }
+ }
+ FX_DWORD datasize = 0;
+ FX_DWORD offset = 0;
+ if (table == 0) {
+ datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
+ } else if (table == 0x74746366) {
+ datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
+ } else {
+ FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
+ for (FX_DWORD i = 0; i < nTables; i++) {
+ const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16;
+ if (GET_TT_LONG(p) == table) {
+ offset = GET_TT_LONG(p + 8);
+ datasize = GET_TT_LONG(p + 12);
+ }
+ }
+ }
+ if (datasize && size >= datasize && pFile) {
+ FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
+ FXSYS_fread(buffer, datasize, 1, pFile);
+ }
+ if (pFile) {
+ FXSYS_fclose(pFile);
+ }
+ return datasize;
+}
+void CFX_FolderFontInfo::DeleteFont(void* hFont) {}
+FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) {
+ if (hFont == NULL) {
+ return FALSE;
+ }
+ CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
+ name = pFont->m_FaceName;
+ return TRUE;
+}
+FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) {
+ return FALSE;
+}
+
+int PDF_GetStandardFontName(CFX_ByteString* name) {
+ AltFontName* found = static_cast<AltFontName*>(
+ FXSYS_bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames),
+ sizeof(AltFontName), compareString));
+ if (!found)
+ return -1;
+
+ *name = g_Base14FontNames[found->m_Index];
+ return found->m_Index;
+}