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