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