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