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