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