Allow external font-path configuration from pdfium_test.
[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_bListLoaded(FALSE),
457       m_pFontInfo(nullptr),
458       m_pFontEnumerator(nullptr),
459       m_pFontMgr(mgr) {
460   m_MMFaces[0] = nullptr;
461   m_MMFaces[1] = nullptr;
462   FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces));
463 }
464 CFX_FontMapper::~CFX_FontMapper() {
465   for (int i = 0; i < 14; i++)
466     if (m_FoxitFaces[i]) {
467       FXFT_Done_Face(m_FoxitFaces[i]);
468     }
469   if (m_MMFaces[0]) {
470     FXFT_Done_Face(m_MMFaces[0]);
471   }
472   if (m_MMFaces[1]) {
473     FXFT_Done_Face(m_MMFaces[1]);
474   }
475   if (m_pFontInfo) {
476     m_pFontInfo->Release();
477   }
478 }
479 void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) {
480   if (pFontInfo == NULL) {
481     return;
482   }
483   if (m_pFontInfo) {
484     m_pFontInfo->Release();
485   }
486   m_pFontInfo = pFontInfo;
487 }
488 static CFX_ByteString _TT_NormalizeName(const FX_CHAR* family) {
489   CFX_ByteString norm(family, -1);
490   norm.Remove(' ');
491   norm.Remove('-');
492   norm.Remove(',');
493   int pos = norm.Find('+');
494   if (pos > 0) {
495     norm = norm.Left(pos);
496   }
497   norm.MakeLower();
498   return norm;
499 }
500 CFX_ByteString _FPDF_GetNameFromTT(const uint8_t* name_table,
501                                    FX_DWORD name_id) {
502   const uint8_t* ptr = name_table + 2;
503   int name_count = GET_TT_SHORT(ptr);
504   int string_offset = GET_TT_SHORT(ptr + 2);
505   const uint8_t* string_ptr = name_table + string_offset;
506   ptr += 4;
507   for (int i = 0; i < name_count; i++) {
508     if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 &&
509         GET_TT_SHORT(ptr + 2) == 0) {
510       return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10),
511                              GET_TT_SHORT(ptr + 8));
512     }
513     ptr += 12;
514   }
515   return CFX_ByteString();
516 }
517 static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile,
518                                                FX_DWORD size) {
519   CFX_ByteString buffer;
520   if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) {
521     return CFX_ByteString();
522   }
523   buffer.ReleaseBuffer(size);
524   return buffer;
525 }
526 CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile,
527                                      const uint8_t* pTables,
528                                      FX_DWORD nTables,
529                                      FX_DWORD tag) {
530   for (FX_DWORD i = 0; i < nTables; i++) {
531     const uint8_t* p = pTables + i * 16;
532     if (GET_TT_LONG(p) == tag) {
533       FX_DWORD offset = GET_TT_LONG(p + 8);
534       FX_DWORD size = GET_TT_LONG(p + 12);
535       FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
536       return _FPDF_ReadStringFromFile(pFile, size);
537     }
538   }
539   return CFX_ByteString();
540 }
541 CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile,
542                                                const uint8_t* pTables,
543                                                FX_DWORD nTables,
544                                                FX_DWORD tag) {
545   for (FX_DWORD i = 0; i < nTables; i++) {
546     const uint8_t* p = pTables + i * 16;
547     if (GET_TT_LONG(p) == tag) {
548       FX_DWORD offset = GET_TT_LONG(p + 8);
549       FX_DWORD size = GET_TT_LONG(p + 12);
550       CFX_ByteString buffer;
551       if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) {
552         return CFX_ByteString();
553       }
554       buffer.ReleaseBuffer(size);
555       return buffer;
556     }
557   }
558   return CFX_ByteString();
559 }
560 CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) {
561   if (m_pFontInfo == NULL) {
562     CFX_ByteString();
563   }
564   CFX_ByteString result;
565   FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0);
566   if (size) {
567     uint8_t* buffer = FX_Alloc(uint8_t, size);
568     m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);
569     result = _FPDF_GetNameFromTT(buffer, 6);
570     FX_Free(buffer);
571   }
572   return result;
573 }
574 void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) {
575   if (m_pFontInfo == NULL) {
576     return;
577   }
578   if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {
579     m_CharsetArray.Add((FX_DWORD)charset);
580     m_FaceArray.Add(name);
581   }
582   if (name == m_LastFamily) {
583     return;
584   }
585   const uint8_t* ptr = name;
586   FX_BOOL bLocalized = FALSE;
587   for (int i = 0; i < name.GetLength(); i++)
588     if (ptr[i] > 0x80) {
589       bLocalized = TRUE;
590       break;
591     }
592   if (bLocalized) {
593     void* hFont = m_pFontInfo->GetFont(name);
594     if (hFont == NULL) {
595       int iExact;
596       hFont =
597           m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact);
598       if (hFont == NULL) {
599         return;
600       }
601     }
602     CFX_ByteString new_name = GetPSNameFromTT(hFont);
603     if (!new_name.IsEmpty()) {
604       new_name.Insert(0, ' ');
605       m_InstalledTTFonts.Add(new_name);
606     }
607     m_pFontInfo->DeleteFont(hFont);
608   }
609   m_InstalledTTFonts.Add(name);
610   m_LastFamily = name;
611 }
612 void CFX_FontMapper::LoadInstalledFonts() {
613   if (m_pFontInfo == NULL) {
614     return;
615   }
616   if (m_bListLoaded) {
617     return;
618   }
619   if (m_bListLoaded) {
620     return;
621   }
622   m_pFontInfo->EnumFontList(this);
623   m_bListLoaded = TRUE;
624 }
625 CFX_ByteString CFX_FontMapper::MatchInstalledFonts(
626     const CFX_ByteString& norm_name) {
627   LoadInstalledFonts();
628   int i;
629   for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i--) {
630     CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);
631     if (norm1 == norm_name) {
632       break;
633     }
634   }
635   if (i < 0) {
636     return CFX_ByteString();
637   }
638   CFX_ByteString match = m_InstalledTTFonts[i];
639   if (match[0] == ' ') {
640     match = m_InstalledTTFonts[i + 1];
641   }
642   return match;
643 }
644 typedef struct _CHARSET_MAP_ {
645   uint8_t charset;
646   FX_WORD codepage;
647 } CHARSET_MAP;
648 static const CHARSET_MAP g_Codepage2CharsetTable[] = {
649     {1, 0},      {2, 42},     {254, 437},  {255, 850},  {222, 874},
650     {128, 932},  {134, 936},  {129, 949},  {136, 950},  {238, 1250},
651     {204, 1251}, {0, 1252},   {161, 1253}, {162, 1254}, {177, 1255},
652     {178, 1256}, {186, 1257}, {163, 1258}, {130, 1361}, {77, 10000},
653     {78, 10001}, {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005},
654     {84, 10004}, {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029},
655     {89, 10007},
656 };
657 uint8_t _GetCharsetFromCodePage(FX_WORD codepage) {
658   int32_t iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;
659   FXSYS_assert(iEnd >= 0);
660   int32_t iStart = 0, iMid;
661   do {
662     iMid = (iStart + iEnd) / 2;
663     const CHARSET_MAP& cp = g_Codepage2CharsetTable[iMid];
664     if (codepage == cp.codepage) {
665       return cp.charset;
666     }
667     if (codepage < cp.codepage) {
668       iEnd = iMid - 1;
669     } else {
670       iStart = iMid + 1;
671     }
672   } while (iStart <= iEnd);
673   return 1;
674 }
675 FX_DWORD _GetCodePageRangeFromCharset(int charset) {
676   if (charset == FXFONT_EASTEUROPE_CHARSET) {
677     return 1 << 1;
678   }
679   if (charset == FXFONT_GREEK_CHARSET) {
680     return 1 << 3;
681   }
682   if (charset == FXFONT_TURKISH_CHARSET) {
683     return 1 << 4;
684   }
685   if (charset == FXFONT_HEBREW_CHARSET) {
686     return 1 << 5;
687   }
688   if (charset == FXFONT_ARABIC_CHARSET) {
689     return 1 << 6;
690   }
691   if (charset == FXFONT_BALTIC_CHARSET) {
692     return 1 << 7;
693   }
694   if (charset == FXFONT_THAI_CHARSET) {
695     return 1 << 16;
696   }
697   if (charset == FXFONT_SHIFTJIS_CHARSET) {
698     return 1 << 17;
699   }
700   if (charset == FXFONT_GB2312_CHARSET) {
701     return 1 << 18;
702   }
703   if (charset == FXFONT_CHINESEBIG5_CHARSET) {
704     return 1 << 20;
705   }
706   if (charset == FXFONT_HANGEUL_CHARSET) {
707     return 1 << 19;
708   }
709   if (charset == FXFONT_SYMBOL_CHARSET) {
710     return 1 << 31;
711   }
712   return 1 << 21;
713 }
714 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont,
715                                            int iBaseFont,
716                                            int italic_angle,
717                                            int weight,
718                                            int picthfamily) {
719   if (iBaseFont < 12) {
720     if (m_FoxitFaces[iBaseFont]) {
721       return m_FoxitFaces[iBaseFont];
722     }
723     const uint8_t* pFontData = NULL;
724     FX_DWORD size = 0;
725     if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
726       m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
727       return m_FoxitFaces[iBaseFont];
728     }
729   }
730   pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
731   pSubstFont->m_ItalicAngle = italic_angle;
732   if (weight) {
733     pSubstFont->m_Weight = weight;
734   }
735   if (picthfamily & FXFONT_FF_ROMAN) {
736     pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
737     pSubstFont->m_Family = "Chrome Serif";
738     if (m_MMFaces[1]) {
739       return m_MMFaces[1];
740     }
741     const uint8_t* pFontData = NULL;
742     FX_DWORD size;
743     m_pFontMgr->GetStandardFont(pFontData, size, 14);
744     m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
745     return m_MMFaces[1];
746   }
747   pSubstFont->m_Family = "Chrome Sans";
748   if (m_MMFaces[0]) {
749     return m_MMFaces[0];
750   }
751   const uint8_t* pFontData = NULL;
752   FX_DWORD size = 0;
753   m_pFontMgr->GetStandardFont(pFontData, size, 15);
754   m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
755   return m_MMFaces[0];
756 }
757 const struct _AltFontFamily {
758   const FX_CHAR* m_pFontName;
759   const FX_CHAR* m_pFontFamily;
760 } g_AltFontFamilies[] = {
761     {"AGaramondPro", "Adobe Garamond Pro"},
762     {"BankGothicBT-Medium", "BankGothic Md BT"},
763     {"ForteMT", "Forte"},
764 };
765 extern "C" {
766 static int compareFontFamilyString(const void* key, const void* element) {
767   CFX_ByteString str_key((const FX_CHAR*)key);
768   if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
769     return 0;
770   }
771   return FXSYS_stricmp((const FX_CHAR*)key,
772                        ((_AltFontFamily*)element)->m_pFontName);
773 }
774 }
775 #define FX_FONT_STYLE_None 0x00
776 #define FX_FONT_STYLE_Bold 0x01
777 #define FX_FONT_STYLE_Italic 0x02
778 #define FX_FONT_STYLE_BoldBold 0x04
779 static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle) {
780   if (fontName.Find("Script") >= 0) {
781     if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
782       fontName = "ScriptMTBold";
783     } else if (fontName.Find("Palace") >= 0) {
784       fontName = "PalaceScriptMT";
785     } else if (fontName.Find("French") >= 0) {
786       fontName = "FrenchScriptMT";
787     } else if (fontName.Find("FreeStyle") >= 0) {
788       fontName = "FreeStyleScript";
789     }
790     return fontName;
791   }
792   _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(
793       fontName.c_str(), g_AltFontFamilies,
794       sizeof g_AltFontFamilies / sizeof(_AltFontFamily), sizeof(_AltFontFamily),
795       compareFontFamilyString);
796   if (found == NULL) {
797     return fontName;
798   }
799   return found->m_pFontFamily;
800 };
801 typedef struct _FX_FontStyle {
802   const FX_CHAR* style;
803   int32_t len;
804 } FX_FontStyle;
805 const FX_FontStyle g_FontStyles[] = {
806     {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7},
807 };
808 CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) {
809   CFX_ByteTextBuf buf;
810   if (!iLen || iLen <= iIndex) {
811     return buf.GetByteString();
812   }
813   while (iIndex < iLen) {
814     if (pStyle[iIndex] == ',') {
815       break;
816     }
817     buf.AppendChar(pStyle[iIndex]);
818     ++iIndex;
819   }
820   return buf.GetByteString();
821 }
822 int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) {
823   int32_t iLen = bsStyle.GetLength();
824   if (!iLen) {
825     return -1;
826   }
827   int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
828   const FX_FontStyle* pStyle = NULL;
829   for (int i = iSize - 1; i >= 0; --i) {
830     pStyle = g_FontStyles + i;
831     if (!pStyle || pStyle->len > iLen) {
832       continue;
833     }
834     if (!bRevert) {
835       if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
836         return i;
837       }
838     } else {
839       if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
840         return i;
841       }
842     }
843   }
844   return -1;
845 }
846 FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) {
847   if (name == FX_BSTRC("MyriadPro")) {
848     PitchFamily &= ~FXFONT_FF_ROMAN;
849     return TRUE;
850   }
851   return FALSE;
852 }
853 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name,
854                                         FX_BOOL bTrueType,
855                                         FX_DWORD flags,
856                                         int weight,
857                                         int italic_angle,
858                                         int WindowCP,
859                                         CFX_SubstFont* pSubstFont) {
860   if (!(flags & FXFONT_USEEXTERNATTR)) {
861     weight = FXFONT_FW_NORMAL;
862     italic_angle = 0;
863   }
864   CFX_ByteString SubstName = name;
865   SubstName.Remove(0x20);
866   if (bTrueType) {
867     if (name[0] == '@') {
868       SubstName = name.Mid(1);
869     }
870   }
871   _PDF_GetStandardFontName(SubstName);
872   if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
873     pSubstFont->m_Family = "Chrome Symbol";
874     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
875     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
876     if (m_FoxitFaces[12]) {
877       return m_FoxitFaces[12];
878     }
879     const uint8_t* pFontData = NULL;
880     FX_DWORD size = 0;
881     m_pFontMgr->GetStandardFont(pFontData, size, 12);
882     m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
883     return m_FoxitFaces[12];
884   }
885   if (SubstName == FX_BSTRC("ZapfDingbats")) {
886     pSubstFont->m_Family = "Chrome Dingbats";
887     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
888     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
889     if (m_FoxitFaces[13]) {
890       return m_FoxitFaces[13];
891     }
892     const uint8_t* pFontData = NULL;
893     FX_DWORD size = 0;
894     m_pFontMgr->GetStandardFont(pFontData, size, 13);
895     m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
896     return m_FoxitFaces[13];
897   }
898   int iBaseFont = 0;
899   CFX_ByteString family, style;
900   FX_BOOL bHasComma = FALSE;
901   FX_BOOL bHasHypen = FALSE;
902   int find = SubstName.Find(FX_BSTRC(","), 0);
903   if (find >= 0) {
904     family = SubstName.Left(find);
905     _PDF_GetStandardFontName(family);
906     style = SubstName.Mid(find + 1);
907     bHasComma = TRUE;
908   } else {
909     family = SubstName;
910   }
911   for (; iBaseFont < 12; iBaseFont++)
912     if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
913       break;
914     }
915   int PitchFamily = 0;
916   FX_BOOL bItalic = FALSE;
917   FX_DWORD nStyle = 0;
918   FX_BOOL bStyleAvail = FALSE;
919   if (iBaseFont < 12) {
920     family = g_Base14FontNames[iBaseFont];
921     if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
922       nStyle |= FX_FONT_STYLE_Bold;
923     }
924     if ((iBaseFont % 4) / 2) {
925       nStyle |= FX_FONT_STYLE_Italic;
926     }
927     if (iBaseFont < 4) {
928       PitchFamily |= FXFONT_FF_FIXEDPITCH;
929     }
930     if (iBaseFont >= 8) {
931       PitchFamily |= FXFONT_FF_ROMAN;
932     }
933   } else {
934     if (!bHasComma) {
935       find = family.ReverseFind('-');
936       if (find >= 0) {
937         style = family.Mid(find + 1);
938         family = family.Left(find);
939         bHasHypen = TRUE;
940       }
941     }
942     if (!bHasHypen) {
943       int nLen = family.GetLength();
944       int32_t nRet = GetStyleType(family, TRUE);
945       if (nRet > -1) {
946         family = family.Left(nLen - g_FontStyles[nRet].len);
947         if (nRet == 0) {
948           nStyle |= FX_FONT_STYLE_Bold;
949         }
950         if (nRet == 1) {
951           nStyle |= FX_FONT_STYLE_Italic;
952         }
953         if (nRet == 2) {
954           nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
955         }
956       }
957     }
958     if (flags & FXFONT_SERIF) {
959       PitchFamily |= FXFONT_FF_ROMAN;
960     }
961     if (flags & FXFONT_SCRIPT) {
962       PitchFamily |= FXFONT_FF_SCRIPT;
963     }
964     if (flags & FXFONT_FIXED_PITCH) {
965       PitchFamily |= FXFONT_FF_FIXEDPITCH;
966     }
967   }
968   if (!style.IsEmpty()) {
969     int nLen = style.GetLength();
970     const FX_CHAR* pStyle = style;
971     int i = 0;
972     FX_BOOL bFirstItem = TRUE;
973     CFX_ByteString buf;
974     while (i < nLen) {
975       buf = ParseStyle(pStyle, nLen, i);
976       int32_t nRet = GetStyleType(buf, FALSE);
977       if ((i && !bStyleAvail) || (!i && nRet < 0)) {
978         family = SubstName;
979         iBaseFont = 12;
980         break;
981       } else if (nRet >= 0) {
982         bStyleAvail = TRUE;
983       }
984       if (nRet == 0) {
985         if (nStyle & FX_FONT_STYLE_Bold) {
986           nStyle |= FX_FONT_STYLE_BoldBold;
987         } else {
988           nStyle |= FX_FONT_STYLE_Bold;
989         }
990         bFirstItem = FALSE;
991       }
992       if (nRet == 1) {
993         if (bFirstItem) {
994           nStyle |= FX_FONT_STYLE_Italic;
995         } else {
996           family = SubstName;
997           iBaseFont = 12;
998         }
999         break;
1000       }
1001       if (nRet == 2) {
1002         nStyle |= FX_FONT_STYLE_Italic;
1003         if (nStyle & FX_FONT_STYLE_Bold) {
1004           nStyle |= FX_FONT_STYLE_BoldBold;
1005         } else {
1006           nStyle |= FX_FONT_STYLE_Bold;
1007         }
1008         bFirstItem = FALSE;
1009       }
1010       i += buf.GetLength() + 1;
1011     }
1012   }
1013   weight = weight ? weight : FXFONT_FW_NORMAL;
1014   int old_weight = weight;
1015   if (nStyle) {
1016     weight =
1017         nStyle & FX_FONT_STYLE_BoldBold
1018             ? 900
1019             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1020   }
1021   if (nStyle & FX_FONT_STYLE_Italic) {
1022     bItalic = TRUE;
1023   }
1024   FX_BOOL bCJK = FALSE;
1025   int iExact = 0;
1026   int Charset = FXFONT_ANSI_CHARSET;
1027   if (WindowCP) {
1028     Charset = _GetCharsetFromCodePage(WindowCP);
1029   } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
1030     Charset = FXFONT_SYMBOL_CHARSET;
1031   }
1032   if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
1033       Charset == FXFONT_HANGEUL_CHARSET ||
1034       Charset == FXFONT_CHINESEBIG5_CHARSET) {
1035     bCJK = TRUE;
1036   }
1037   if (m_pFontInfo == NULL) {
1038     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1039     return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1040                             PitchFamily);
1041   }
1042   family = _GetFontFamily(family, nStyle);
1043   CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
1044   if (match.IsEmpty() && family != SubstName &&
1045       (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
1046     match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
1047   }
1048   if (match.IsEmpty() && iBaseFont >= 12) {
1049     if (!bCJK) {
1050       if (!CheckSupportThirdPartFont(family, PitchFamily)) {
1051         if (italic_angle != 0) {
1052           bItalic = TRUE;
1053         } else {
1054           bItalic = FALSE;
1055         }
1056         weight = old_weight;
1057       }
1058     } else {
1059       pSubstFont->m_bSubstOfCJK = TRUE;
1060       if (nStyle) {
1061         pSubstFont->m_WeightCJK = weight;
1062       } else {
1063         pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
1064       }
1065       if (nStyle & FX_FONT_STYLE_Italic) {
1066         pSubstFont->m_bItlicCJK = TRUE;
1067       }
1068     }
1069   } else {
1070     italic_angle = 0;
1071     weight =
1072         nStyle & FX_FONT_STYLE_BoldBold
1073             ? 900
1074             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1075   }
1076   if (!match.IsEmpty() || iBaseFont < 12) {
1077     pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1078     if (!match.IsEmpty()) {
1079       family = match;
1080     }
1081     if (iBaseFont < 12) {
1082       if (nStyle && !(iBaseFont % 4)) {
1083         if ((nStyle & 0x3) == 1) {
1084           iBaseFont += 1;
1085         }
1086         if ((nStyle & 0x3) == 2) {
1087           iBaseFont += 3;
1088         }
1089         if ((nStyle & 0x3) == 3) {
1090           iBaseFont += 2;
1091         }
1092       }
1093       if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
1094         if (m_FoxitFaces[iBaseFont]) {
1095           return m_FoxitFaces[iBaseFont];
1096         }
1097         m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(
1098             m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
1099             m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
1100         if (m_FoxitFaces[iBaseFont]) {
1101           return m_FoxitFaces[iBaseFont];
1102         }
1103       } else {
1104         family = g_Base14FontNames[iBaseFont];
1105       }
1106       pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1107     }
1108   } else {
1109     if (flags & FXFONT_ITALIC) {
1110       bItalic = TRUE;
1111     }
1112   }
1113   iExact = !match.IsEmpty();
1114   void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily,
1115                                      family, iExact);
1116   if (iExact) {
1117     pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1118   }
1119   if (hFont == NULL) {
1120     if (bCJK) {
1121       if (italic_angle != 0) {
1122         bItalic = TRUE;
1123       } else {
1124         bItalic = FALSE;
1125       }
1126       weight = old_weight;
1127     }
1128     if (!match.IsEmpty()) {
1129       hFont = m_pFontInfo->GetFont(match);
1130       if (hFont == NULL) {
1131         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1132                                 PitchFamily);
1133       }
1134     } else {
1135       if (Charset == FXFONT_SYMBOL_CHARSET) {
1136 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
1137     _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
1138         if (SubstName == FX_BSTRC("Symbol")) {
1139           pSubstFont->m_Family = "Chrome Symbol";
1140           pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1141           pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
1142           if (m_FoxitFaces[12]) {
1143             return m_FoxitFaces[12];
1144           }
1145           const uint8_t* pFontData = NULL;
1146           FX_DWORD size = 0;
1147           m_pFontMgr->GetStandardFont(pFontData, size, 12);
1148           m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
1149           return m_FoxitFaces[12];
1150         }
1151 #endif
1152         pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
1153         return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC,
1154                              weight, italic_angle, 0, pSubstFont);
1155       }
1156       if (Charset == FXFONT_ANSI_CHARSET) {
1157         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1158         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1159                                 PitchFamily);
1160       }
1161       int index = m_CharsetArray.Find(Charset);
1162       if (index < 0) {
1163         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
1164                                 PitchFamily);
1165       }
1166       hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
1167     }
1168   }
1169   pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
1170   if (hFont == NULL) {
1171     return NULL;
1172   }
1173   m_pFontInfo->GetFaceName(hFont, SubstName);
1174   if (Charset == FXFONT_DEFAULT_CHARSET) {
1175     m_pFontInfo->GetFontCharset(hFont, Charset);
1176   }
1177   FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
1178   FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
1179   if (font_size == 0 && ttc_size == 0) {
1180     m_pFontInfo->DeleteFont(hFont);
1181     return NULL;
1182   }
1183   FXFT_Face face = NULL;
1184   if (ttc_size) {
1185     uint8_t temp[1024];
1186     m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
1187     FX_DWORD checksum = 0;
1188     for (int i = 0; i < 256; i++) {
1189       checksum += ((FX_DWORD*)temp)[i];
1190     }
1191     uint8_t* pFontData;
1192     face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum,
1193                                         ttc_size - font_size, pFontData);
1194     if (face == NULL) {
1195       pFontData = FX_Alloc(uint8_t, ttc_size);
1196       m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
1197       face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData,
1198                                           ttc_size, ttc_size - font_size);
1199     }
1200   } else {
1201     uint8_t* pFontData;
1202     face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
1203     if (face == NULL) {
1204       pFontData = FX_Alloc(uint8_t, font_size);
1205       m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
1206       face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData,
1207                                        font_size,
1208                                        m_pFontInfo->GetFaceIndex(hFont));
1209     }
1210   }
1211   if (face == NULL) {
1212     m_pFontInfo->DeleteFont(hFont);
1213     return NULL;
1214   }
1215   pSubstFont->m_Family = SubstName;
1216   pSubstFont->m_Charset = Charset;
1217   FX_BOOL bNeedUpdateWeight = FALSE;
1218   if (FXFT_Is_Face_Bold(face)) {
1219     if (weight == FXFONT_FW_BOLD) {
1220       bNeedUpdateWeight = FALSE;
1221     } else {
1222       bNeedUpdateWeight = TRUE;
1223     }
1224   } else {
1225     if (weight == FXFONT_FW_NORMAL) {
1226       bNeedUpdateWeight = FALSE;
1227     } else {
1228       bNeedUpdateWeight = TRUE;
1229     }
1230   }
1231   if (bNeedUpdateWeight) {
1232     pSubstFont->m_Weight = weight;
1233   }
1234   if (bItalic && !FXFT_Is_Face_Italic(face)) {
1235     if (italic_angle == 0) {
1236       italic_angle = -12;
1237     } else if (FXSYS_abs(italic_angle) < 5) {
1238       italic_angle = 0;
1239     }
1240     pSubstFont->m_ItalicAngle = italic_angle;
1241   }
1242   m_pFontInfo->DeleteFont(hFont);
1243   return face;
1244 }
1245 extern "C" {
1246 unsigned long _FTStreamRead(FXFT_Stream stream,
1247                             unsigned long offset,
1248                             unsigned char* buffer,
1249                             unsigned long count);
1250 void _FTStreamClose(FXFT_Stream stream);
1251 };
1252 CFontFileFaceInfo::CFontFileFaceInfo() {
1253   m_pFile = NULL;
1254   m_Face = NULL;
1255   m_Charsets = 0;
1256   m_FileSize = 0;
1257   m_FontOffset = 0;
1258   m_Weight = 0;
1259   m_bItalic = FALSE;
1260   m_PitchFamily = 0;
1261 }
1262 CFontFileFaceInfo::~CFontFileFaceInfo() {
1263   if (m_Face) {
1264     FXFT_Done_Face(m_Face);
1265   }
1266   m_Face = NULL;
1267 }
1268 extern FX_BOOL _LoadFile(FXFT_Library library,
1269                          FXFT_Face* Face,
1270                          IFX_FileRead* pFile,
1271                          FXFT_Stream* stream);
1272 #if _FX_OS_ == _FX_ANDROID_
1273 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
1274   return NULL;
1275 }
1276 #endif
1277 CFX_FolderFontInfo::CFX_FolderFontInfo() {}
1278 CFX_FolderFontInfo::~CFX_FolderFontInfo() {
1279   FX_POSITION pos = m_FontList.GetStartPosition();
1280   while (pos) {
1281     CFX_ByteString key;
1282     void* value;
1283     m_FontList.GetNextAssoc(pos, key, value);
1284     delete (CFX_FontFaceInfo*)value;
1285   }
1286 }
1287 void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) {
1288   m_PathList.Add(path);
1289 }
1290 void CFX_FolderFontInfo::Release() {
1291   delete this;
1292 }
1293 FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) {
1294   m_pMapper = pMapper;
1295   for (int i = 0; i < m_PathList.GetSize(); i++) {
1296     ScanPath(m_PathList[i]);
1297   }
1298   return TRUE;
1299 }
1300 void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path) {
1301   void* handle = FX_OpenFolder(path);
1302   if (handle == NULL) {
1303     return;
1304   }
1305   CFX_ByteString filename;
1306   FX_BOOL bFolder;
1307   while (FX_GetNextFile(handle, filename, bFolder)) {
1308     if (bFolder) {
1309       if (filename == "." || filename == "..") {
1310         continue;
1311       }
1312     } else {
1313       CFX_ByteString ext = filename.Right(4);
1314       ext.MakeUpper();
1315       if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
1316         continue;
1317       }
1318     }
1319     CFX_ByteString fullpath = path;
1320 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
1321     fullpath += "\\";
1322 #else
1323     fullpath += "/";
1324 #endif
1325     fullpath += filename;
1326     if (bFolder) {
1327       ScanPath(fullpath);
1328     } else {
1329       ScanFile(fullpath);
1330     }
1331   }
1332   FX_CloseFolder(handle);
1333 }
1334 void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path) {
1335   FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
1336   if (pFile == NULL) {
1337     return;
1338   }
1339   FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
1340   FX_DWORD filesize = FXSYS_ftell(pFile);
1341   uint8_t buffer[16];
1342   FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
1343   size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
1344   if (readCnt != 1) {
1345     FXSYS_fclose(pFile);
1346     return;
1347   }
1348
1349   if (GET_TT_LONG(buffer) == 0x74746366) {
1350     FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
1351     if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) {
1352       FXSYS_fclose(pFile);
1353       return;
1354     }
1355     FX_DWORD face_bytes = nFaces * 4;
1356     uint8_t* offsets = FX_Alloc(uint8_t, face_bytes);
1357     readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile);
1358     if (readCnt != face_bytes) {
1359       FX_Free(offsets);
1360       FXSYS_fclose(pFile);
1361       return;
1362     }
1363     for (FX_DWORD i = 0; i < nFaces; i++) {
1364       uint8_t* p = offsets + i * 4;
1365       ReportFace(path, pFile, filesize, GET_TT_LONG(p));
1366     }
1367     FX_Free(offsets);
1368   } else {
1369     ReportFace(path, pFile, filesize, 0);
1370   }
1371   FXSYS_fclose(pFile);
1372 }
1373 void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path,
1374                                     FXSYS_FILE* pFile,
1375                                     FX_DWORD filesize,
1376                                     FX_DWORD offset) {
1377   FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1378   char buffer[16];
1379   if (!FXSYS_fread(buffer, 12, 1, pFile)) {
1380     return;
1381   }
1382   FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
1383   CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
1384   if (tables.IsEmpty()) {
1385     return;
1386   }
1387   CFX_ByteString names =
1388       _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
1389   CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);
1390   CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);
1391   if (style != "Regular") {
1392     facename += " " + style;
1393   }
1394   void* p;
1395   if (m_FontList.Lookup(facename, p)) {
1396     return;
1397   }
1398   CFX_FontFaceInfo* pInfo =
1399       new CFX_FontFaceInfo(path, facename, tables, offset, filesize);
1400   CFX_ByteString os2 =
1401       _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
1402   if (os2.GetLength() >= 86) {
1403     const uint8_t* p = (const uint8_t*)os2 + 78;
1404     FX_DWORD codepages = GET_TT_LONG(p);
1405     if (codepages & (1 << 17)) {
1406       m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
1407       pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
1408     }
1409     if (codepages & (1 << 18)) {
1410       m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
1411       pInfo->m_Charsets |= CHARSET_FLAG_GB;
1412     }
1413     if (codepages & (1 << 20)) {
1414       m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
1415       pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
1416     }
1417     if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
1418       m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
1419       pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
1420     }
1421     if (codepages & (1 << 31)) {
1422       m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
1423       pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
1424     }
1425   }
1426   m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
1427   pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
1428   pInfo->m_Styles = 0;
1429   if (style.Find(FX_BSTRC("Bold")) > -1) {
1430     pInfo->m_Styles |= FXFONT_BOLD;
1431   }
1432   if (style.Find(FX_BSTRC("Italic")) > -1 ||
1433       style.Find(FX_BSTRC("Oblique")) > -1) {
1434     pInfo->m_Styles |= FXFONT_ITALIC;
1435   }
1436   if (facename.Find(FX_BSTRC("Serif")) > -1) {
1437     pInfo->m_Styles |= FXFONT_SERIF;
1438   }
1439   m_FontList.SetAt(facename, pInfo);
1440 }
1441 void* CFX_FolderFontInfo::MapFont(int weight,
1442                                   FX_BOOL bItalic,
1443                                   int charset,
1444                                   int pitch_family,
1445                                   const FX_CHAR* family,
1446                                   int& iExact) {
1447   return NULL;
1448 }
1449 void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) {
1450   void* p;
1451   if (!m_FontList.Lookup(face, p)) {
1452     return NULL;
1453   }
1454   return p;
1455 }
1456 FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont,
1457                                          FX_DWORD table,
1458                                          uint8_t* buffer,
1459                                          FX_DWORD size) {
1460   if (hFont == NULL) {
1461     return 0;
1462   }
1463   CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
1464   FXSYS_FILE* pFile = NULL;
1465   if (size > 0) {
1466     pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
1467     if (pFile == NULL) {
1468       return 0;
1469     }
1470   }
1471   FX_DWORD datasize = 0;
1472   FX_DWORD offset;
1473   if (table == 0) {
1474     datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
1475     offset = 0;
1476   } else if (table == 0x74746366) {
1477     datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
1478     offset = 0;
1479   } else {
1480     FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
1481     for (FX_DWORD i = 0; i < nTables; i++) {
1482       const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16;
1483       if (GET_TT_LONG(p) == table) {
1484         offset = GET_TT_LONG(p + 8);
1485         datasize = GET_TT_LONG(p + 12);
1486       }
1487     }
1488   }
1489   if (datasize && size >= datasize && pFile) {
1490     FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1491     FXSYS_fread(buffer, datasize, 1, pFile);
1492   }
1493   if (pFile) {
1494     FXSYS_fclose(pFile);
1495   }
1496   return datasize;
1497 }
1498 void CFX_FolderFontInfo::DeleteFont(void* hFont) {}
1499 FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) {
1500   if (hFont == NULL) {
1501     return FALSE;
1502   }
1503   CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
1504   name = pFont->m_FaceName;
1505   return TRUE;
1506 }
1507 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) {
1508   return FALSE;
1509 }