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