Extern in .cpp files is a code smell.
[pdfium.git] / core / src / fxge / ge / fx_ge_fontmap.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <limits>
8
9 #include "../../../include/fxge/fx_ge.h"
10 #include "../../../include/fxge/fx_freetype.h"
11 #include "../fontdata/chromefontdata/chromefontdata.h"
12 #include "text_int.h"
13
14 #define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1])
15 #define GET_TT_LONG(w) \
16   (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
17
18 namespace {
19
20 CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name,
21                                int weight,
22                                FX_BOOL bItalic) {
23   CFX_ByteString key(face_name);
24   key += ',';
25   key += CFX_ByteString::FormatInteger(weight);
26   key += bItalic ? 'I' : 'N';
27   return key;
28 }
29
30 CFX_ByteString KeyNameFromSize(int ttc_size, FX_DWORD checksum) {
31   CFX_ByteString key;
32   key.Format("%d:%d", ttc_size, checksum);
33   return key;
34 }
35
36 }  // namespace
37
38 CFX_SubstFont::CFX_SubstFont() {
39   m_ExtHandle = NULL;
40   m_Charset = 0;
41   m_SubstFlags = 0;
42   m_Weight = 0;
43   m_ItalicAngle = 0;
44   m_bSubstOfCJK = FALSE;
45   m_WeightCJK = 0;
46   m_bItlicCJK = FALSE;
47 }
48 CTTFontDesc::~CTTFontDesc() {
49   if (m_Type == 1) {
50     if (m_SingleFace.m_pFace) {
51       FXFT_Done_Face(m_SingleFace.m_pFace);
52     }
53   } else if (m_Type == 2) {
54     for (int i = 0; i < 16; i++)
55       if (m_TTCFace.m_pFaces[i]) {
56         FXFT_Done_Face(m_TTCFace.m_pFaces[i]);
57       }
58   }
59   FX_Free(m_pFontData);
60 }
61 FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face) {
62   if (m_Type == 1) {
63     if (m_SingleFace.m_pFace != face) {
64       return FALSE;
65     }
66   } else if (m_Type == 2) {
67     int i;
68     for (i = 0; i < 16; i++)
69       if (m_TTCFace.m_pFaces[i] == face) {
70         break;
71       }
72     if (i == 16) {
73       return FALSE;
74     }
75   }
76   m_RefCount--;
77   if (m_RefCount) {
78     return FALSE;
79   }
80   delete this;
81   return TRUE;
82 }
83 CFX_FontMgr::CFX_FontMgr() : m_FTLibrary(nullptr) {
84   m_pBuiltinMapper = new CFX_FontMapper(this);
85   FXSYS_memset(m_ExternalFonts, 0, sizeof m_ExternalFonts);
86 }
87 CFX_FontMgr::~CFX_FontMgr() {
88   delete m_pBuiltinMapper;
89   FreeCache();
90   if (m_FTLibrary) {
91     FXFT_Done_FreeType(m_FTLibrary);
92   }
93 }
94 void CFX_FontMgr::InitFTLibrary() {
95   if (m_FTLibrary == NULL) {
96     FXFT_Init_FreeType(&m_FTLibrary);
97   }
98 }
99 void CFX_FontMgr::FreeCache() {
100   for (const auto& pair : m_FaceMap) {
101     delete pair.second;
102   }
103   m_FaceMap.clear();
104 }
105 void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) {
106   m_pBuiltinMapper->SetSystemFontInfo(pFontInfo);
107 }
108 FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name,
109                                      FX_BOOL bTrueType,
110                                      FX_DWORD flags,
111                                      int weight,
112                                      int italic_angle,
113                                      int CharsetCP,
114                                      CFX_SubstFont* pSubstFont) {
115   if (!m_FTLibrary) {
116     FXFT_Init_FreeType(&m_FTLibrary);
117   }
118   return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight,
119                                          italic_angle, CharsetCP, pSubstFont);
120 }
121 FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name,
122                                      int weight,
123                                      FX_BOOL bItalic,
124                                      uint8_t*& pFontData) {
125   auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic));
126   if (it == m_FaceMap.end())
127     return nullptr;
128
129   CTTFontDesc* pFontDesc = it->second;
130   pFontData = pFontDesc->m_pFontData;
131   pFontDesc->m_RefCount++;
132   return pFontDesc->m_SingleFace.m_pFace;
133 }
134 FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name,
135                                      int weight,
136                                      FX_BOOL bItalic,
137                                      uint8_t* pData,
138                                      FX_DWORD size,
139                                      int face_index) {
140   CTTFontDesc* pFontDesc = new CTTFontDesc;
141   pFontDesc->m_Type = 1;
142   pFontDesc->m_SingleFace.m_pFace = NULL;
143   pFontDesc->m_SingleFace.m_bBold = weight;
144   pFontDesc->m_SingleFace.m_bItalic = bItalic;
145   pFontDesc->m_pFontData = pData;
146   pFontDesc->m_RefCount = 1;
147   FXFT_Library library;
148   if (m_FTLibrary == NULL) {
149     FXFT_Init_FreeType(&m_FTLibrary);
150   }
151   library = m_FTLibrary;
152   int ret = FXFT_New_Memory_Face(library, pData, size, face_index,
153                                  &pFontDesc->m_SingleFace.m_pFace);
154   if (ret) {
155     delete pFontDesc;
156     return NULL;
157   }
158   ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64);
159   if (ret) {
160     delete pFontDesc;
161     return NULL;
162   }
163   m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc;
164   return pFontDesc->m_SingleFace.m_pFace;
165 }
166 const FX_CHAR* const g_Base14FontNames[14] = {
167     "Courier",
168     "Courier-Bold",
169     "Courier-BoldOblique",
170     "Courier-Oblique",
171     "Helvetica",
172     "Helvetica-Bold",
173     "Helvetica-BoldOblique",
174     "Helvetica-Oblique",
175     "Times-Roman",
176     "Times-Bold",
177     "Times-BoldItalic",
178     "Times-Italic",
179     "Symbol",
180     "ZapfDingbats",
181 };
182 const struct _AltFontName {
183   const FX_CHAR* m_pName;
184   int m_Index;
185 } g_AltFontNames[] = {
186     {"Arial", 4},
187     {"Arial,Bold", 5},
188     {"Arial,BoldItalic", 6},
189     {"Arial,Italic", 7},
190     {"Arial-Bold", 5},
191     {"Arial-BoldItalic", 6},
192     {"Arial-BoldItalicMT", 6},
193     {"Arial-BoldMT", 5},
194     {"Arial-Italic", 7},
195     {"Arial-ItalicMT", 7},
196     {"ArialBold", 5},
197     {"ArialBoldItalic", 6},
198     {"ArialItalic", 7},
199     {"ArialMT", 4},
200     {"ArialMT,Bold", 5},
201     {"ArialMT,BoldItalic", 6},
202     {"ArialMT,Italic", 7},
203     {"ArialRoundedMTBold", 5},
204     {"Courier", 0},
205     {"Courier,Bold", 1},
206     {"Courier,BoldItalic", 2},
207     {"Courier,Italic", 3},
208     {"Courier-Bold", 1},
209     {"Courier-BoldOblique", 2},
210     {"Courier-Oblique", 3},
211     {"CourierBold", 1},
212     {"CourierBoldItalic", 2},
213     {"CourierItalic", 3},
214     {"CourierNew", 0},
215     {"CourierNew,Bold", 1},
216     {"CourierNew,BoldItalic", 2},
217     {"CourierNew,Italic", 3},
218     {"CourierNew-Bold", 1},
219     {"CourierNew-BoldItalic", 2},
220     {"CourierNew-Italic", 3},
221     {"CourierNewBold", 1},
222     {"CourierNewBoldItalic", 2},
223     {"CourierNewItalic", 3},
224     {"CourierNewPS-BoldItalicMT", 2},
225     {"CourierNewPS-BoldMT", 1},
226     {"CourierNewPS-ItalicMT", 3},
227     {"CourierNewPSMT", 0},
228     {"CourierStd", 0},
229     {"CourierStd-Bold", 1},
230     {"CourierStd-BoldOblique", 2},
231     {"CourierStd-Oblique", 3},
232     {"Helvetica", 4},
233     {"Helvetica,Bold", 5},
234     {"Helvetica,BoldItalic", 6},
235     {"Helvetica,Italic", 7},
236     {"Helvetica-Bold", 5},
237     {"Helvetica-BoldItalic", 6},
238     {"Helvetica-BoldOblique", 6},
239     {"Helvetica-Italic", 7},
240     {"Helvetica-Oblique", 7},
241     {"HelveticaBold", 5},
242     {"HelveticaBoldItalic", 6},
243     {"HelveticaItalic", 7},
244     {"Symbol", 12},
245     {"SymbolMT", 12},
246     {"Times-Bold", 9},
247     {"Times-BoldItalic", 10},
248     {"Times-Italic", 11},
249     {"Times-Roman", 8},
250     {"TimesBold", 9},
251     {"TimesBoldItalic", 10},
252     {"TimesItalic", 11},
253     {"TimesNewRoman", 8},
254     {"TimesNewRoman,Bold", 9},
255     {"TimesNewRoman,BoldItalic", 10},
256     {"TimesNewRoman,Italic", 11},
257     {"TimesNewRoman-Bold", 9},
258     {"TimesNewRoman-BoldItalic", 10},
259     {"TimesNewRoman-Italic", 11},
260     {"TimesNewRomanBold", 9},
261     {"TimesNewRomanBoldItalic", 10},
262     {"TimesNewRomanItalic", 11},
263     {"TimesNewRomanPS", 8},
264     {"TimesNewRomanPS-Bold", 9},
265     {"TimesNewRomanPS-BoldItalic", 10},
266     {"TimesNewRomanPS-BoldItalicMT", 10},
267     {"TimesNewRomanPS-BoldMT", 9},
268     {"TimesNewRomanPS-Italic", 11},
269     {"TimesNewRomanPS-ItalicMT", 11},
270     {"TimesNewRomanPSMT", 8},
271     {"TimesNewRomanPSMT,Bold", 9},
272     {"TimesNewRomanPSMT,BoldItalic", 10},
273     {"TimesNewRomanPSMT,Italic", 11},
274     {"ZapfDingbats", 13},
275 };
276 extern "C" {
277 static int compareString(const void* key, const void* element) {
278   return FXSYS_stricmp((const FX_CHAR*)key, ((_AltFontName*)element)->m_pName);
279 }
280 }
281 int _PDF_GetStandardFontName(CFX_ByteString& name) {
282   _AltFontName* found =
283       (_AltFontName*)FXSYS_bsearch(name.c_str(), g_AltFontNames,
284                                    sizeof g_AltFontNames / sizeof(_AltFontName),
285                                    sizeof(_AltFontName), compareString);
286   if (found == NULL) {
287     return -1;
288   }
289   name = g_Base14FontNames[found->m_Index];
290   return found->m_Index;
291 }
292 int GetTTCIndex(const uint8_t* pFontData,
293                 FX_DWORD ttc_size,
294                 FX_DWORD font_offset) {
295   int face_index = 0;
296   const uint8_t* p = pFontData + 8;
297   FX_DWORD nfont = GET_TT_LONG(p);
298   FX_DWORD index;
299   for (index = 0; index < nfont; index++) {
300     p = pFontData + 12 + index * 4;
301     if (GET_TT_LONG(p) == font_offset) {
302       break;
303     }
304   }
305   if (index >= nfont) {
306     face_index = 0;
307   } else {
308     face_index = index;
309   }
310   return face_index;
311 }
312 FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size,
313                                         FX_DWORD checksum,
314                                         int font_offset,
315                                         uint8_t*& pFontData) {
316   auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum));
317   if (it == m_FaceMap.end())
318     return nullptr;
319
320   CTTFontDesc* pFontDesc = it->second;
321   pFontData = pFontDesc->m_pFontData;
322   pFontDesc->m_RefCount++;
323   int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
324   if (!pFontDesc->m_TTCFace.m_pFaces[face_index]) {
325     pFontDesc->m_TTCFace.m_pFaces[face_index] =
326         GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
327   }
328   return pFontDesc->m_TTCFace.m_pFaces[face_index];
329 }
330 FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size,
331                                         FX_DWORD checksum,
332                                         uint8_t* pData,
333                                         FX_DWORD size,
334                                         int font_offset) {
335   CTTFontDesc* pFontDesc = new CTTFontDesc;
336   pFontDesc->m_Type = 2;
337   pFontDesc->m_pFontData = pData;
338   for (int i = 0; i < 16; i++) {
339     pFontDesc->m_TTCFace.m_pFaces[i] = NULL;
340   }
341   pFontDesc->m_RefCount++;
342   m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc;
343   int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
344   pFontDesc->m_TTCFace.m_pFaces[face_index] =
345       GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
346   return pFontDesc->m_TTCFace.m_pFaces[face_index];
347 }
348 FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData,
349                                     FX_DWORD size,
350                                     int face_index) {
351   FXFT_Library library;
352   if (m_FTLibrary == NULL) {
353     FXFT_Init_FreeType(&m_FTLibrary);
354   }
355   library = m_FTLibrary;
356   FXFT_Face face = NULL;
357   int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face);
358   if (ret) {
359     return NULL;
360   }
361   ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
362   if (ret) {
363     return NULL;
364   }
365   return face;
366 }
367 FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) {
368   FXFT_Library library;
369   if (m_FTLibrary == NULL) {
370     FXFT_Init_FreeType(&m_FTLibrary);
371   }
372   library = m_FTLibrary;
373   FXFT_Face face = NULL;
374   int ret = FXFT_New_Face(library, filename, face_index, &face);
375   if (ret) {
376     return NULL;
377   }
378   ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
379   if (ret) {
380     return NULL;
381   }
382   return face;
383 }
384 void CFX_FontMgr::ReleaseFace(FXFT_Face face) {
385   if (!face) {
386     return;
387   }
388   auto it = m_FaceMap.begin();
389   while (it != m_FaceMap.end()) {
390     auto temp = it++;
391     if (temp->second->ReleaseFace(face)) {
392       m_FaceMap.erase(temp);
393     }
394   }
395 }
396 const FoxitFonts g_FoxitFonts[14] = {
397     {g_FoxitFixedFontData, 17597},
398     {g_FoxitFixedBoldFontData, 18055},
399     {g_FoxitFixedBoldItalicFontData, 19151},
400     {g_FoxitFixedItalicFontData, 18746},
401     {g_FoxitSansFontData, 15025},
402     {g_FoxitSansBoldFontData, 16344},
403     {g_FoxitSansBoldItalicFontData, 16418},
404     {g_FoxitSansItalicFontData, 16339},
405     {g_FoxitSerifFontData, 19469},
406     {g_FoxitSerifBoldFontData, 19395},
407     {g_FoxitSerifBoldItalicFontData, 20733},
408     {g_FoxitSerifItalicFontData, 21227},
409     {g_FoxitSymbolFontData, 16729},
410     {g_FoxitDingbatsFontData, 29513},
411 };
412 void _FPDFAPI_GetInternalFontData(int id,
413                                   const uint8_t*& data,
414                                   FX_DWORD& size) {
415   CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id);
416 }
417 FX_BOOL CFX_FontMgr::GetStandardFont(const uint8_t*& pFontData,
418                                      FX_DWORD& size,
419                                      int index) {
420   if (index > 15 || index < 0) {
421     return FALSE;
422   }
423   {
424     if (index >= 14) {
425       if (index == 14) {
426         pFontData = g_FoxitSerifMMFontData;
427         size = 113417;
428       } else {
429         pFontData = g_FoxitSansMMFontData;
430         size = 66919;
431       }
432     } else {
433       pFontData = g_FoxitFonts[index].m_pFontData;
434       size = g_FoxitFonts[index].m_dwSize;
435     }
436   }
437   return TRUE;
438 }
439 CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr)
440     : m_bListLoaded(FALSE),
441       m_pFontInfo(nullptr),
442       m_pFontEnumerator(nullptr),
443       m_pFontMgr(mgr) {
444   m_MMFaces[0] = nullptr;
445   m_MMFaces[1] = nullptr;
446   FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces));
447 }
448 CFX_FontMapper::~CFX_FontMapper() {
449   for (int i = 0; i < 14; i++)
450     if (m_FoxitFaces[i]) {
451       FXFT_Done_Face(m_FoxitFaces[i]);
452     }
453   if (m_MMFaces[0]) {
454     FXFT_Done_Face(m_MMFaces[0]);
455   }
456   if (m_MMFaces[1]) {
457     FXFT_Done_Face(m_MMFaces[1]);
458   }
459   if (m_pFontInfo) {
460     m_pFontInfo->Release();
461   }
462 }
463 void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) {
464   if (pFontInfo == NULL) {
465     return;
466   }
467   if (m_pFontInfo) {
468     m_pFontInfo->Release();
469   }
470   m_pFontInfo = pFontInfo;
471 }
472 static CFX_ByteString _TT_NormalizeName(const FX_CHAR* family) {
473   CFX_ByteString norm(family, -1);
474   norm.Remove(' ');
475   norm.Remove('-');
476   norm.Remove(',');
477   int pos = norm.Find('+');
478   if (pos > 0) {
479     norm = norm.Left(pos);
480   }
481   norm.MakeLower();
482   return norm;
483 }
484 CFX_ByteString _FPDF_GetNameFromTT(const uint8_t* name_table,
485                                    FX_DWORD name_id) {
486   const uint8_t* ptr = name_table + 2;
487   int name_count = GET_TT_SHORT(ptr);
488   int string_offset = GET_TT_SHORT(ptr + 2);
489   const uint8_t* string_ptr = name_table + string_offset;
490   ptr += 4;
491   for (int i = 0; i < name_count; i++) {
492     if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 &&
493         GET_TT_SHORT(ptr + 2) == 0) {
494       return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10),
495                              GET_TT_SHORT(ptr + 8));
496     }
497     ptr += 12;
498   }
499   return CFX_ByteString();
500 }
501 static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile,
502                                                FX_DWORD size) {
503   CFX_ByteString buffer;
504   if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) {
505     return CFX_ByteString();
506   }
507   buffer.ReleaseBuffer(size);
508   return buffer;
509 }
510 CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile,
511                                      const uint8_t* pTables,
512                                      FX_DWORD nTables,
513                                      FX_DWORD tag) {
514   for (FX_DWORD i = 0; i < nTables; i++) {
515     const uint8_t* p = pTables + i * 16;
516     if (GET_TT_LONG(p) == tag) {
517       FX_DWORD offset = GET_TT_LONG(p + 8);
518       FX_DWORD size = GET_TT_LONG(p + 12);
519       FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
520       return _FPDF_ReadStringFromFile(pFile, size);
521     }
522   }
523   return CFX_ByteString();
524 }
525 CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile,
526                                                const uint8_t* pTables,
527                                                FX_DWORD nTables,
528                                                FX_DWORD tag) {
529   for (FX_DWORD i = 0; i < nTables; i++) {
530     const uint8_t* p = pTables + i * 16;
531     if (GET_TT_LONG(p) == tag) {
532       FX_DWORD offset = GET_TT_LONG(p + 8);
533       FX_DWORD size = GET_TT_LONG(p + 12);
534       CFX_ByteString buffer;
535       if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) {
536         return CFX_ByteString();
537       }
538       buffer.ReleaseBuffer(size);
539       return buffer;
540     }
541   }
542   return CFX_ByteString();
543 }
544 CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) {
545   if (m_pFontInfo == NULL) {
546     CFX_ByteString();
547   }
548   CFX_ByteString result;
549   FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0);
550   if (size) {
551     uint8_t* buffer = FX_Alloc(uint8_t, size);
552     m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);
553     result = _FPDF_GetNameFromTT(buffer, 6);
554     FX_Free(buffer);
555   }
556   return result;
557 }
558 void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) {
559   if (m_pFontInfo == NULL) {
560     return;
561   }
562   if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {
563     m_CharsetArray.Add((FX_DWORD)charset);
564     m_FaceArray.Add(name);
565   }
566   if (name == m_LastFamily) {
567     return;
568   }
569   const uint8_t* ptr = name;
570   FX_BOOL bLocalized = FALSE;
571   for (int i = 0; i < name.GetLength(); i++)
572     if (ptr[i] > 0x80) {
573       bLocalized = TRUE;
574       break;
575     }
576   if (bLocalized) {
577     void* hFont = m_pFontInfo->GetFont(name);
578     if (hFont == NULL) {
579       int iExact;
580       hFont =
581           m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact);
582       if (hFont == NULL) {
583         return;
584       }
585     }
586     CFX_ByteString new_name = GetPSNameFromTT(hFont);
587     if (!new_name.IsEmpty()) {
588       new_name.Insert(0, ' ');
589       m_InstalledTTFonts.Add(new_name);
590     }
591     m_pFontInfo->DeleteFont(hFont);
592   }
593   m_InstalledTTFonts.Add(name);
594   m_LastFamily = name;
595 }
596 void CFX_FontMapper::LoadInstalledFonts() {
597   if (m_pFontInfo == NULL) {
598     return;
599   }
600   if (m_bListLoaded) {
601     return;
602   }
603   if (m_bListLoaded) {
604     return;
605   }
606   m_pFontInfo->EnumFontList(this);
607   m_bListLoaded = TRUE;
608 }
609 CFX_ByteString CFX_FontMapper::MatchInstalledFonts(
610     const CFX_ByteString& norm_name) {
611   LoadInstalledFonts();
612   int i;
613   for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i--) {
614     CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);
615     if (norm1 == norm_name) {
616       break;
617     }
618   }
619   if (i < 0) {
620     return CFX_ByteString();
621   }
622   CFX_ByteString match = m_InstalledTTFonts[i];
623   if (match[0] == ' ') {
624     match = m_InstalledTTFonts[i + 1];
625   }
626   return match;
627 }
628 typedef struct _CHARSET_MAP_ {
629   uint8_t charset;
630   FX_WORD codepage;
631 } CHARSET_MAP;
632 static const CHARSET_MAP g_Codepage2CharsetTable[] = {
633     {1, 0},      {2, 42},     {254, 437},  {255, 850},  {222, 874},
634     {128, 932},  {134, 936},  {129, 949},  {136, 950},  {238, 1250},
635     {204, 1251}, {0, 1252},   {161, 1253}, {162, 1254}, {177, 1255},
636     {178, 1256}, {186, 1257}, {163, 1258}, {130, 1361}, {77, 10000},
637     {78, 10001}, {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005},
638     {84, 10004}, {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029},
639     {89, 10007},
640 };
641 uint8_t _GetCharsetFromCodePage(FX_WORD codepage) {
642   int32_t iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;
643   FXSYS_assert(iEnd >= 0);
644   int32_t iStart = 0, iMid;
645   do {
646     iMid = (iStart + iEnd) / 2;
647     const CHARSET_MAP& cp = g_Codepage2CharsetTable[iMid];
648     if (codepage == cp.codepage) {
649       return cp.charset;
650     }
651     if (codepage < cp.codepage) {
652       iEnd = iMid - 1;
653     } else {
654       iStart = iMid + 1;
655     }
656   } while (iStart <= iEnd);
657   return 1;
658 }
659 FX_DWORD _GetCodePageRangeFromCharset(int charset) {
660   if (charset == FXFONT_EASTEUROPE_CHARSET) {
661     return 1 << 1;
662   }
663   if (charset == FXFONT_GREEK_CHARSET) {
664     return 1 << 3;
665   }
666   if (charset == FXFONT_TURKISH_CHARSET) {
667     return 1 << 4;
668   }
669   if (charset == FXFONT_HEBREW_CHARSET) {
670     return 1 << 5;
671   }
672   if (charset == FXFONT_ARABIC_CHARSET) {
673     return 1 << 6;
674   }
675   if (charset == FXFONT_BALTIC_CHARSET) {
676     return 1 << 7;
677   }
678   if (charset == FXFONT_THAI_CHARSET) {
679     return 1 << 16;
680   }
681   if (charset == FXFONT_SHIFTJIS_CHARSET) {
682     return 1 << 17;
683   }
684   if (charset == FXFONT_GB2312_CHARSET) {
685     return 1 << 18;
686   }
687   if (charset == FXFONT_CHINESEBIG5_CHARSET) {
688     return 1 << 20;
689   }
690   if (charset == FXFONT_HANGEUL_CHARSET) {
691     return 1 << 19;
692   }
693   if (charset == FXFONT_SYMBOL_CHARSET) {
694     return 1 << 31;
695   }
696   return 1 << 21;
697 }
698 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont,
699                                            int iBaseFont,
700                                            int italic_angle,
701                                            int weight,
702                                            int picthfamily) {
703   if (iBaseFont < 12) {
704     if (m_FoxitFaces[iBaseFont]) {
705       return m_FoxitFaces[iBaseFont];
706     }
707     const uint8_t* pFontData = NULL;
708     FX_DWORD size = 0;
709     if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
710       m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
711       return m_FoxitFaces[iBaseFont];
712     }
713   }
714   pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
715   pSubstFont->m_ItalicAngle = italic_angle;
716   if (weight) {
717     pSubstFont->m_Weight = weight;
718   }
719   if (picthfamily & FXFONT_FF_ROMAN) {
720     pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
721     pSubstFont->m_Family = "Chrome Serif";
722     if (m_MMFaces[1]) {
723       return m_MMFaces[1];
724     }
725     const uint8_t* pFontData = NULL;
726     FX_DWORD size;
727     m_pFontMgr->GetStandardFont(pFontData, size, 14);
728     m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
729     return m_MMFaces[1];
730   }
731   pSubstFont->m_Family = "Chrome Sans";
732   if (m_MMFaces[0]) {
733     return m_MMFaces[0];
734   }
735   const uint8_t* pFontData = NULL;
736   FX_DWORD size = 0;
737   m_pFontMgr->GetStandardFont(pFontData, size, 15);
738   m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
739   return m_MMFaces[0];
740 }
741 const struct _AltFontFamily {
742   const FX_CHAR* m_pFontName;
743   const FX_CHAR* m_pFontFamily;
744 } g_AltFontFamilies[] = {
745     {"AGaramondPro", "Adobe Garamond Pro"},
746     {"BankGothicBT-Medium", "BankGothic Md BT"},
747     {"ForteMT", "Forte"},
748 };
749 extern "C" {
750 static int compareFontFamilyString(const void* key, const void* element) {
751   CFX_ByteString str_key((const FX_CHAR*)key);
752   if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
753     return 0;
754   }
755   return FXSYS_stricmp((const FX_CHAR*)key,
756                        ((_AltFontFamily*)element)->m_pFontName);
757 }
758 }
759 #define FX_FONT_STYLE_None 0x00
760 #define FX_FONT_STYLE_Bold 0x01
761 #define FX_FONT_STYLE_Italic 0x02
762 #define FX_FONT_STYLE_BoldBold 0x04
763 static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle) {
764   if (fontName.Find("Script") >= 0) {
765     if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
766       fontName = "ScriptMTBold";
767     } else if (fontName.Find("Palace") >= 0) {
768       fontName = "PalaceScriptMT";
769     } else if (fontName.Find("French") >= 0) {
770       fontName = "FrenchScriptMT";
771     } else if (fontName.Find("FreeStyle") >= 0) {
772       fontName = "FreeStyleScript";
773     }
774     return fontName;
775   }
776   _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(
777       fontName.c_str(), g_AltFontFamilies,
778       sizeof g_AltFontFamilies / sizeof(_AltFontFamily), sizeof(_AltFontFamily),
779       compareFontFamilyString);
780   if (found == NULL) {
781     return fontName;
782   }
783   return found->m_pFontFamily;
784 };
785 typedef struct _FX_FontStyle {
786   const FX_CHAR* style;
787   int32_t len;
788 } FX_FontStyle;
789 const FX_FontStyle g_FontStyles[] = {
790     {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7},
791 };
792 CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) {
793   CFX_ByteTextBuf buf;
794   if (!iLen || iLen <= iIndex) {
795     return buf.GetByteString();
796   }
797   while (iIndex < iLen) {
798     if (pStyle[iIndex] == ',') {
799       break;
800     }
801     buf.AppendChar(pStyle[iIndex]);
802     ++iIndex;
803   }
804   return buf.GetByteString();
805 }
806 int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) {
807   int32_t iLen = bsStyle.GetLength();
808   if (!iLen) {
809     return -1;
810   }
811   int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
812   const FX_FontStyle* pStyle = NULL;
813   for (int i = iSize - 1; i >= 0; --i) {
814     pStyle = g_FontStyles + i;
815     if (!pStyle || pStyle->len > iLen) {
816       continue;
817     }
818     if (!bRevert) {
819       if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
820         return i;
821       }
822     } else {
823       if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
824         return i;
825       }
826     }
827   }
828   return -1;
829 }
830 FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) {
831   if (name == FX_BSTRC("MyriadPro")) {
832     PitchFamily &= ~FXFONT_FF_ROMAN;
833     return TRUE;
834   }
835   return FALSE;
836 }
837 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name,
838                                         FX_BOOL bTrueType,
839                                         FX_DWORD flags,
840                                         int weight,
841                                         int italic_angle,
842                                         int WindowCP,
843                                         CFX_SubstFont* pSubstFont) {
844   if (!(flags & FXFONT_USEEXTERNATTR)) {
845     weight = FXFONT_FW_NORMAL;
846     italic_angle = 0;
847   }
848   CFX_ByteString SubstName = name;
849   SubstName.Remove(0x20);
850   if (bTrueType) {
851     if (name[0] == '@') {
852       SubstName = name.Mid(1);
853     }
854   }
855   _PDF_GetStandardFontName(SubstName);
856   if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
857     pSubstFont->m_Family = "Chrome Symbol";
858     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
859     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
860     if (m_FoxitFaces[12]) {
861       return m_FoxitFaces[12];
862     }
863     const uint8_t* pFontData = NULL;
864     FX_DWORD size = 0;
865     m_pFontMgr->GetStandardFont(pFontData, size, 12);
866     m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
867     return m_FoxitFaces[12];
868   }
869   if (SubstName == FX_BSTRC("ZapfDingbats")) {
870     pSubstFont->m_Family = "Chrome Dingbats";
871     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
872     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
873     if (m_FoxitFaces[13]) {
874       return m_FoxitFaces[13];
875     }
876     const uint8_t* pFontData = NULL;
877     FX_DWORD size = 0;
878     m_pFontMgr->GetStandardFont(pFontData, size, 13);
879     m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
880     return m_FoxitFaces[13];
881   }
882   int iBaseFont = 0;
883   CFX_ByteString family, style;
884   FX_BOOL bHasComma = FALSE;
885   FX_BOOL bHasHypen = FALSE;
886   int find = SubstName.Find(FX_BSTRC(","), 0);
887   if (find >= 0) {
888     family = SubstName.Left(find);
889     _PDF_GetStandardFontName(family);
890     style = SubstName.Mid(find + 1);
891     bHasComma = TRUE;
892   } else {
893     family = SubstName;
894   }
895   for (; iBaseFont < 12; iBaseFont++)
896     if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
897       break;
898     }
899   int PitchFamily = 0;
900   FX_BOOL bItalic = FALSE;
901   FX_DWORD nStyle = 0;
902   FX_BOOL bStyleAvail = FALSE;
903   if (iBaseFont < 12) {
904     family = g_Base14FontNames[iBaseFont];
905     if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
906       nStyle |= FX_FONT_STYLE_Bold;
907     }
908     if ((iBaseFont % 4) / 2) {
909       nStyle |= FX_FONT_STYLE_Italic;
910     }
911     if (iBaseFont < 4) {
912       PitchFamily |= FXFONT_FF_FIXEDPITCH;
913     }
914     if (iBaseFont >= 8) {
915       PitchFamily |= FXFONT_FF_ROMAN;
916     }
917   } else {
918     if (!bHasComma) {
919       find = family.ReverseFind('-');
920       if (find >= 0) {
921         style = family.Mid(find + 1);
922         family = family.Left(find);
923         bHasHypen = TRUE;
924       }
925     }
926     if (!bHasHypen) {
927       int nLen = family.GetLength();
928       int32_t nRet = GetStyleType(family, TRUE);
929       if (nRet > -1) {
930         family = family.Left(nLen - g_FontStyles[nRet].len);
931         if (nRet == 0) {
932           nStyle |= FX_FONT_STYLE_Bold;
933         }
934         if (nRet == 1) {
935           nStyle |= FX_FONT_STYLE_Italic;
936         }
937         if (nRet == 2) {
938           nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
939         }
940       }
941     }
942     if (flags & FXFONT_SERIF) {
943       PitchFamily |= FXFONT_FF_ROMAN;
944     }
945     if (flags & FXFONT_SCRIPT) {
946       PitchFamily |= FXFONT_FF_SCRIPT;
947     }
948     if (flags & FXFONT_FIXED_PITCH) {
949       PitchFamily |= FXFONT_FF_FIXEDPITCH;
950     }
951   }
952   if (!style.IsEmpty()) {
953     int nLen = style.GetLength();
954     const FX_CHAR* pStyle = style;
955     int i = 0;
956     FX_BOOL bFirstItem = TRUE;
957     CFX_ByteString buf;
958     while (i < nLen) {
959       buf = ParseStyle(pStyle, nLen, i);
960       int32_t nRet = GetStyleType(buf, FALSE);
961       if ((i && !bStyleAvail) || (!i && nRet < 0)) {
962         family = SubstName;
963         iBaseFont = 12;
964         break;
965       } else if (nRet >= 0) {
966         bStyleAvail = TRUE;
967       }
968       if (nRet == 0) {
969         if (nStyle & FX_FONT_STYLE_Bold) {
970           nStyle |= FX_FONT_STYLE_BoldBold;
971         } else {
972           nStyle |= FX_FONT_STYLE_Bold;
973         }
974         bFirstItem = FALSE;
975       }
976       if (nRet == 1) {
977         if (bFirstItem) {
978           nStyle |= FX_FONT_STYLE_Italic;
979         } else {
980           family = SubstName;
981           iBaseFont = 12;
982         }
983         break;
984       }
985       if (nRet == 2) {
986         nStyle |= FX_FONT_STYLE_Italic;
987         if (nStyle & FX_FONT_STYLE_Bold) {
988           nStyle |= FX_FONT_STYLE_BoldBold;
989         } else {
990           nStyle |= FX_FONT_STYLE_Bold;
991         }
992         bFirstItem = FALSE;
993       }
994       i += buf.GetLength() + 1;
995     }
996   }
997   weight = weight ? weight : FXFONT_FW_NORMAL;
998   int old_weight = weight;
999   if (nStyle) {
1000     weight =
1001         nStyle & FX_FONT_STYLE_BoldBold
1002             ? 900
1003             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1004   }
1005   if (nStyle & FX_FONT_STYLE_Italic) {
1006     bItalic = TRUE;
1007   }
1008   FX_BOOL bCJK = FALSE;
1009   int iExact = 0;
1010   int Charset = FXFONT_ANSI_CHARSET;
1011   if (WindowCP) {
1012     Charset = _GetCharsetFromCodePage(WindowCP);
1013   } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
1014     Charset = FXFONT_SYMBOL_CHARSET;
1015   }
1016   if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
1017       Charset == FXFONT_HANGEUL_CHARSET ||
1018       Charset == FXFONT_CHINESEBIG5_CHARSET) {
1019     bCJK = TRUE;
1020   }
1021   if (m_pFontInfo == NULL) {
1022     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1023     return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1024                             PitchFamily);
1025   }
1026   family = _GetFontFamily(family, nStyle);
1027   CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
1028   if (match.IsEmpty() && family != SubstName &&
1029       (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
1030     match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
1031   }
1032   if (match.IsEmpty() && iBaseFont >= 12) {
1033     if (!bCJK) {
1034       if (!CheckSupportThirdPartFont(family, PitchFamily)) {
1035         if (italic_angle != 0) {
1036           bItalic = TRUE;
1037         } else {
1038           bItalic = FALSE;
1039         }
1040         weight = old_weight;
1041       }
1042     } else {
1043       pSubstFont->m_bSubstOfCJK = TRUE;
1044       if (nStyle) {
1045         pSubstFont->m_WeightCJK = weight;
1046       } else {
1047         pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
1048       }
1049       if (nStyle & FX_FONT_STYLE_Italic) {
1050         pSubstFont->m_bItlicCJK = TRUE;
1051       }
1052     }
1053   } else {
1054     italic_angle = 0;
1055     weight =
1056         nStyle & FX_FONT_STYLE_BoldBold
1057             ? 900
1058             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1059   }
1060   if (!match.IsEmpty() || iBaseFont < 12) {
1061     pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1062     if (!match.IsEmpty()) {
1063       family = match;
1064     }
1065     if (iBaseFont < 12) {
1066       if (nStyle && !(iBaseFont % 4)) {
1067         if ((nStyle & 0x3) == 1) {
1068           iBaseFont += 1;
1069         }
1070         if ((nStyle & 0x3) == 2) {
1071           iBaseFont += 3;
1072         }
1073         if ((nStyle & 0x3) == 3) {
1074           iBaseFont += 2;
1075         }
1076       }
1077       if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
1078         if (m_FoxitFaces[iBaseFont]) {
1079           return m_FoxitFaces[iBaseFont];
1080         }
1081         m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(
1082             m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
1083             m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
1084         if (m_FoxitFaces[iBaseFont]) {
1085           return m_FoxitFaces[iBaseFont];
1086         }
1087       } else {
1088         family = g_Base14FontNames[iBaseFont];
1089       }
1090       pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1091     }
1092   } else {
1093     if (flags & FXFONT_ITALIC) {
1094       bItalic = TRUE;
1095     }
1096   }
1097   iExact = !match.IsEmpty();
1098   void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily,
1099                                      family, iExact);
1100   if (iExact) {
1101     pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1102   }
1103   if (hFont == NULL) {
1104     if (bCJK) {
1105       if (italic_angle != 0) {
1106         bItalic = TRUE;
1107       } else {
1108         bItalic = FALSE;
1109       }
1110       weight = old_weight;
1111     }
1112     if (!match.IsEmpty()) {
1113       hFont = m_pFontInfo->GetFont(match);
1114       if (hFont == NULL) {
1115         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1116                                 PitchFamily);
1117       }
1118     } else {
1119       if (Charset == FXFONT_SYMBOL_CHARSET) {
1120 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
1121     _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
1122         if (SubstName == FX_BSTRC("Symbol")) {
1123           pSubstFont->m_Family = "Chrome Symbol";
1124           pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1125           pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
1126           if (m_FoxitFaces[12]) {
1127             return m_FoxitFaces[12];
1128           }
1129           const uint8_t* pFontData = NULL;
1130           FX_DWORD size = 0;
1131           m_pFontMgr->GetStandardFont(pFontData, size, 12);
1132           m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
1133           return m_FoxitFaces[12];
1134         }
1135 #endif
1136         pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
1137         return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC,
1138                              weight, italic_angle, 0, pSubstFont);
1139       }
1140       if (Charset == FXFONT_ANSI_CHARSET) {
1141         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1142         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1143                                 PitchFamily);
1144       }
1145       int index = m_CharsetArray.Find(Charset);
1146       if (index < 0) {
1147         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1148                                 PitchFamily);
1149       }
1150       hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
1151     }
1152   }
1153   pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
1154   if (hFont == NULL) {
1155     return NULL;
1156   }
1157   m_pFontInfo->GetFaceName(hFont, SubstName);
1158   if (Charset == FXFONT_DEFAULT_CHARSET) {
1159     m_pFontInfo->GetFontCharset(hFont, Charset);
1160   }
1161   FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
1162   FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
1163   if (font_size == 0 && ttc_size == 0) {
1164     m_pFontInfo->DeleteFont(hFont);
1165     return NULL;
1166   }
1167   FXFT_Face face = NULL;
1168   if (ttc_size) {
1169     uint8_t temp[1024];
1170     m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
1171     FX_DWORD checksum = 0;
1172     for (int i = 0; i < 256; i++) {
1173       checksum += ((FX_DWORD*)temp)[i];
1174     }
1175     uint8_t* pFontData;
1176     face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum,
1177                                         ttc_size - font_size, pFontData);
1178     if (face == NULL) {
1179       pFontData = FX_Alloc(uint8_t, ttc_size);
1180       m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
1181       face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData,
1182                                           ttc_size, ttc_size - font_size);
1183     }
1184   } else {
1185     uint8_t* pFontData;
1186     face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
1187     if (face == NULL) {
1188       pFontData = FX_Alloc(uint8_t, font_size);
1189       m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
1190       face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData,
1191                                        font_size,
1192                                        m_pFontInfo->GetFaceIndex(hFont));
1193     }
1194   }
1195   if (face == NULL) {
1196     m_pFontInfo->DeleteFont(hFont);
1197     return NULL;
1198   }
1199   pSubstFont->m_Family = SubstName;
1200   pSubstFont->m_Charset = Charset;
1201   FX_BOOL bNeedUpdateWeight = FALSE;
1202   if (FXFT_Is_Face_Bold(face)) {
1203     if (weight == FXFONT_FW_BOLD) {
1204       bNeedUpdateWeight = FALSE;
1205     } else {
1206       bNeedUpdateWeight = TRUE;
1207     }
1208   } else {
1209     if (weight == FXFONT_FW_NORMAL) {
1210       bNeedUpdateWeight = FALSE;
1211     } else {
1212       bNeedUpdateWeight = TRUE;
1213     }
1214   }
1215   if (bNeedUpdateWeight) {
1216     pSubstFont->m_Weight = weight;
1217   }
1218   if (bItalic && !FXFT_Is_Face_Italic(face)) {
1219     if (italic_angle == 0) {
1220       italic_angle = -12;
1221     } else if (FXSYS_abs(italic_angle) < 5) {
1222       italic_angle = 0;
1223     }
1224     pSubstFont->m_ItalicAngle = italic_angle;
1225   }
1226   m_pFontInfo->DeleteFont(hFont);
1227   return face;
1228 }
1229 extern "C" {
1230 unsigned long _FTStreamRead(FXFT_Stream stream,
1231                             unsigned long offset,
1232                             unsigned char* buffer,
1233                             unsigned long count);
1234 void _FTStreamClose(FXFT_Stream stream);
1235 };
1236 CFontFileFaceInfo::CFontFileFaceInfo() {
1237   m_pFile = NULL;
1238   m_Face = NULL;
1239   m_Charsets = 0;
1240   m_FileSize = 0;
1241   m_FontOffset = 0;
1242   m_Weight = 0;
1243   m_bItalic = FALSE;
1244   m_PitchFamily = 0;
1245 }
1246 CFontFileFaceInfo::~CFontFileFaceInfo() {
1247   if (m_Face) {
1248     FXFT_Done_Face(m_Face);
1249   }
1250   m_Face = NULL;
1251 }
1252 extern FX_BOOL _LoadFile(FXFT_Library library,
1253                          FXFT_Face* Face,
1254                          IFX_FileRead* pFile,
1255                          FXFT_Stream* stream);
1256 #if _FX_OS_ == _FX_ANDROID_
1257 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
1258   return NULL;
1259 }
1260 #endif
1261 CFX_FolderFontInfo::CFX_FolderFontInfo() {}
1262 CFX_FolderFontInfo::~CFX_FolderFontInfo() {
1263   for (const auto& pair : m_FontList) {
1264     delete pair.second;
1265   }
1266 }
1267 void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) {
1268   m_PathList.Add(path);
1269 }
1270 void CFX_FolderFontInfo::Release() {
1271   delete this;
1272 }
1273 FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) {
1274   m_pMapper = pMapper;
1275   for (int i = 0; i < m_PathList.GetSize(); i++) {
1276     ScanPath(m_PathList[i]);
1277   }
1278   return TRUE;
1279 }
1280 void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path) {
1281   void* handle = FX_OpenFolder(path);
1282   if (handle == NULL) {
1283     return;
1284   }
1285   CFX_ByteString filename;
1286   FX_BOOL bFolder;
1287   while (FX_GetNextFile(handle, filename, bFolder)) {
1288     if (bFolder) {
1289       if (filename == "." || filename == "..") {
1290         continue;
1291       }
1292     } else {
1293       CFX_ByteString ext = filename.Right(4);
1294       ext.MakeUpper();
1295       if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
1296         continue;
1297       }
1298     }
1299     CFX_ByteString fullpath = path;
1300 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
1301     fullpath += "\\";
1302 #else
1303     fullpath += "/";
1304 #endif
1305     fullpath += filename;
1306     if (bFolder) {
1307       ScanPath(fullpath);
1308     } else {
1309       ScanFile(fullpath);
1310     }
1311   }
1312   FX_CloseFolder(handle);
1313 }
1314 void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path) {
1315   FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
1316   if (pFile == NULL) {
1317     return;
1318   }
1319   FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
1320   FX_DWORD filesize = FXSYS_ftell(pFile);
1321   uint8_t buffer[16];
1322   FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
1323   size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
1324   if (readCnt != 1) {
1325     FXSYS_fclose(pFile);
1326     return;
1327   }
1328
1329   if (GET_TT_LONG(buffer) == 0x74746366) {
1330     FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
1331     if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) {
1332       FXSYS_fclose(pFile);
1333       return;
1334     }
1335     FX_DWORD face_bytes = nFaces * 4;
1336     uint8_t* offsets = FX_Alloc(uint8_t, face_bytes);
1337     readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile);
1338     if (readCnt != face_bytes) {
1339       FX_Free(offsets);
1340       FXSYS_fclose(pFile);
1341       return;
1342     }
1343     for (FX_DWORD i = 0; i < nFaces; i++) {
1344       uint8_t* p = offsets + i * 4;
1345       ReportFace(path, pFile, filesize, GET_TT_LONG(p));
1346     }
1347     FX_Free(offsets);
1348   } else {
1349     ReportFace(path, pFile, filesize, 0);
1350   }
1351   FXSYS_fclose(pFile);
1352 }
1353 void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path,
1354                                     FXSYS_FILE* pFile,
1355                                     FX_DWORD filesize,
1356                                     FX_DWORD offset) {
1357   FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1358   char buffer[16];
1359   if (!FXSYS_fread(buffer, 12, 1, pFile)) {
1360     return;
1361   }
1362   FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
1363   CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
1364   if (tables.IsEmpty()) {
1365     return;
1366   }
1367   CFX_ByteString names =
1368       _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
1369   CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);
1370   CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);
1371   if (style != "Regular") {
1372     facename += " " + style;
1373   }
1374   if (m_FontList.find(facename) != m_FontList.end()) {
1375     return;
1376   }
1377   CFX_FontFaceInfo* pInfo =
1378       new CFX_FontFaceInfo(path, facename, tables, offset, filesize);
1379   CFX_ByteString os2 =
1380       _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
1381   if (os2.GetLength() >= 86) {
1382     const uint8_t* p = (const uint8_t*)os2 + 78;
1383     FX_DWORD codepages = GET_TT_LONG(p);
1384     if (codepages & (1 << 17)) {
1385       m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
1386       pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
1387     }
1388     if (codepages & (1 << 18)) {
1389       m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
1390       pInfo->m_Charsets |= CHARSET_FLAG_GB;
1391     }
1392     if (codepages & (1 << 20)) {
1393       m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
1394       pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
1395     }
1396     if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
1397       m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
1398       pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
1399     }
1400     if (codepages & (1 << 31)) {
1401       m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
1402       pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
1403     }
1404   }
1405   m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
1406   pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
1407   pInfo->m_Styles = 0;
1408   if (style.Find(FX_BSTRC("Bold")) > -1) {
1409     pInfo->m_Styles |= FXFONT_BOLD;
1410   }
1411   if (style.Find(FX_BSTRC("Italic")) > -1 ||
1412       style.Find(FX_BSTRC("Oblique")) > -1) {
1413     pInfo->m_Styles |= FXFONT_ITALIC;
1414   }
1415   if (facename.Find(FX_BSTRC("Serif")) > -1) {
1416     pInfo->m_Styles |= FXFONT_SERIF;
1417   }
1418   m_FontList[facename] = pInfo;
1419 }
1420 void* CFX_FolderFontInfo::MapFont(int weight,
1421                                   FX_BOOL bItalic,
1422                                   int charset,
1423                                   int pitch_family,
1424                                   const FX_CHAR* family,
1425                                   int& iExact) {
1426   return NULL;
1427 }
1428 void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) {
1429   auto it = m_FontList.find(face);
1430   return it != m_FontList.end() ? it->second : nullptr;
1431 }
1432 FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont,
1433                                          FX_DWORD table,
1434                                          uint8_t* buffer,
1435                                          FX_DWORD size) {
1436   if (hFont == NULL) {
1437     return 0;
1438   }
1439   CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
1440   FXSYS_FILE* pFile = NULL;
1441   if (size > 0) {
1442     pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
1443     if (pFile == NULL) {
1444       return 0;
1445     }
1446   }
1447   FX_DWORD datasize = 0;
1448   FX_DWORD offset;
1449   if (table == 0) {
1450     datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
1451     offset = 0;
1452   } else if (table == 0x74746366) {
1453     datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
1454     offset = 0;
1455   } else {
1456     FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
1457     for (FX_DWORD i = 0; i < nTables; i++) {
1458       const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16;
1459       if (GET_TT_LONG(p) == table) {
1460         offset = GET_TT_LONG(p + 8);
1461         datasize = GET_TT_LONG(p + 12);
1462       }
1463     }
1464   }
1465   if (datasize && size >= datasize && pFile) {
1466     FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1467     FXSYS_fread(buffer, datasize, 1, pFile);
1468   }
1469   if (pFile) {
1470     FXSYS_fclose(pFile);
1471   }
1472   return datasize;
1473 }
1474 void CFX_FolderFontInfo::DeleteFont(void* hFont) {}
1475 FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) {
1476   if (hFont == NULL) {
1477     return FALSE;
1478   }
1479   CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
1480   name = pFont->m_FaceName;
1481   return TRUE;
1482 }
1483 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) {
1484   return FALSE;
1485 }