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