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