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