Fix FX_BOOL type mismatches.
[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             int iExact;
596             hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact);
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         }
692         if (codepage < cp.codepage) {
693             iEnd = iMid - 1;
694         } else {
695             iStart = iMid + 1;
696         }
697     } while (iStart <= iEnd);
698     return 1;
699 }
700 FX_DWORD _GetCodePageRangeFromCharset(int charset)
701 {
702     if (charset == FXFONT_EASTEUROPE_CHARSET) {
703         return 1 << 1;
704     }
705     if (charset == FXFONT_GREEK_CHARSET) {
706         return 1 << 3;
707     }
708     if (charset == FXFONT_TURKISH_CHARSET) {
709         return 1 << 4;
710     }
711     if (charset == FXFONT_HEBREW_CHARSET) {
712         return 1 << 5;
713     }
714     if (charset == FXFONT_ARABIC_CHARSET) {
715         return 1 << 6;
716     }
717     if (charset == FXFONT_BALTIC_CHARSET) {
718         return 1 << 7;
719     }
720     if (charset == FXFONT_THAI_CHARSET) {
721         return 1 << 16;
722     }
723     if (charset == FXFONT_SHIFTJIS_CHARSET) {
724         return 1 << 17;
725     }
726     if (charset == FXFONT_GB2312_CHARSET) {
727         return 1 << 18;
728     }
729     if (charset == FXFONT_CHINESEBIG5_CHARSET) {
730         return 1 << 20;
731     }
732     if (charset == FXFONT_HANGEUL_CHARSET) {
733         return 1 << 19;
734     }
735     if (charset == FXFONT_SYMBOL_CHARSET) {
736         return 1 << 31;
737     }
738     return 1 << 21;
739 }
740 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int picthfamily)
741 {
742     if (iBaseFont < 12) {
743         if (m_FoxitFaces[iBaseFont]) {
744             return m_FoxitFaces[iBaseFont];
745         }
746         const uint8_t* pFontData = NULL;
747         FX_DWORD size = 0;
748         if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
749             m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
750             return m_FoxitFaces[iBaseFont];
751         }
752     }
753     pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
754     pSubstFont->m_ItalicAngle = italic_angle;
755     if (weight) {
756         pSubstFont->m_Weight = weight;
757     }
758     if (picthfamily & FXFONT_FF_ROMAN) {
759         pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
760         pSubstFont->m_Family = "Chrome Serif";
761         if (m_MMFaces[1]) {
762             return m_MMFaces[1];
763         }
764         const uint8_t* pFontData = NULL;
765         FX_DWORD size;
766         m_pFontMgr->GetStandardFont(pFontData, size, 14);
767         m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
768         return m_MMFaces[1];
769     }
770     pSubstFont->m_Family = "Chrome Sans";
771     if (m_MMFaces[0]) {
772         return m_MMFaces[0];
773     }
774     const uint8_t* pFontData = NULL;
775     FX_DWORD size = 0;
776     m_pFontMgr->GetStandardFont(pFontData, size, 15);
777     m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
778     return m_MMFaces[0];
779 }
780 const struct _AltFontFamily {
781     const FX_CHAR* m_pFontName;
782     const FX_CHAR* m_pFontFamily;
783 }
784 g_AltFontFamilies[] = {
785     {"AGaramondPro", "Adobe Garamond Pro"},
786     {"BankGothicBT-Medium", "BankGothic Md BT"},
787     {"ForteMT", "Forte"},
788 };
789 extern "C" {
790     static int compareFontFamilyString(const void* key, const void* element)
791     {
792         CFX_ByteString str_key((const FX_CHAR*)key);
793         if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
794             return 0;
795         }
796         return FXSYS_stricmp((const FX_CHAR*)key, ((_AltFontFamily*)element)->m_pFontName);
797     }
798 }
799 #define FX_FONT_STYLE_None              0x00
800 #define FX_FONT_STYLE_Bold              0x01
801 #define FX_FONT_STYLE_Italic    0x02
802 #define FX_FONT_STYLE_BoldBold  0x04
803 static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle)
804 {
805     if (fontName.Find("Script") >= 0) {
806         if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
807             fontName = "ScriptMTBold";
808         } else if (fontName.Find("Palace") >= 0) {
809             fontName = "PalaceScriptMT";
810         } else if (fontName.Find("French") >= 0) {
811             fontName = "FrenchScriptMT";
812         } else if (fontName.Find("FreeStyle") >= 0) {
813             fontName = "FreeStyleScript";
814         }
815         return fontName;
816     }
817     _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(fontName.c_str(), g_AltFontFamilies,
818                             sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString);
819     if (found == NULL) {
820         return fontName;
821     }
822     return found->m_pFontFamily;
823 };
824 typedef struct _FX_FontStyle {
825     const FX_CHAR* style;
826     int32_t len;
827 } FX_FontStyle;
828 const FX_FontStyle g_FontStyles[] = {
829   { "Bold", 4 },
830   { "Italic", 6 },
831   { "BoldItalic", 10 },
832   { "Reg", 3 },
833   { "Regular", 7 },
834 };
835 CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex)
836 {
837     CFX_ByteTextBuf buf;
838     if (!iLen || iLen <= iIndex) {
839         return buf.GetByteString();
840     }
841     while (iIndex < iLen) {
842         if (pStyle[iIndex] == ',') {
843             break;
844         }
845         buf.AppendChar(pStyle[iIndex]);
846         ++iIndex;
847     }
848     return buf.GetByteString();
849 }
850 int32_t GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert)
851 {
852     int32_t iLen = bsStyle.GetLength();
853     if (!iLen) {
854         return -1;
855     }
856     int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
857     const FX_FontStyle *pStyle = NULL;
858     for (int i = iSize - 1; i >= 0; --i) {
859         pStyle = g_FontStyles + i;
860         if (!pStyle || pStyle->len > iLen) {
861             continue;
862         }
863         if (!bRevert) {
864             if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
865                 return i;
866             }
867         } else {
868             if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
869                 return i;
870             }
871         }
872     }
873     return -1;
874 }
875 FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int &PitchFamily)
876 {
877     if (name == FX_BSTRC("MyriadPro")) {
878         PitchFamily &= ~FXFONT_FF_ROMAN;
879         return TRUE;
880     }
881     return FALSE;
882 }
883 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, FX_BOOL bTrueType, FX_DWORD flags,
884                                         int weight, int italic_angle, int WindowCP, CFX_SubstFont* pSubstFont)
885 {
886     if (!(flags & FXFONT_USEEXTERNATTR)) {
887         weight = FXFONT_FW_NORMAL;
888         italic_angle = 0;
889     }
890     CFX_ByteString SubstName = name;
891     SubstName.Remove(0x20);
892     if (bTrueType) {
893         if (name[0] == '@') {
894             SubstName = name.Mid(1);
895         }
896     }
897     _PDF_GetStandardFontName(SubstName);
898     if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
899         pSubstFont->m_Family = "Chrome Symbol";
900         pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
901         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
902         if (m_FoxitFaces[12]) {
903             return m_FoxitFaces[12];
904         }
905         const uint8_t* pFontData = NULL;
906         FX_DWORD size = 0;
907         m_pFontMgr->GetStandardFont(pFontData, size, 12);
908         m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
909         return m_FoxitFaces[12];
910     }
911     if (SubstName == FX_BSTRC("ZapfDingbats")) {
912         pSubstFont->m_Family = "Chrome Dingbats";
913         pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
914         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
915         if (m_FoxitFaces[13]) {
916             return m_FoxitFaces[13];
917         }
918         const uint8_t* pFontData = NULL;
919         FX_DWORD size = 0;
920         m_pFontMgr->GetStandardFont(pFontData, size, 13);
921         m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
922         return m_FoxitFaces[13];
923     }
924     int iBaseFont = 0;
925     CFX_ByteString family, style;
926     FX_BOOL     bHasComma = FALSE;
927     FX_BOOL bHasHypen = FALSE;
928     int find = SubstName.Find(FX_BSTRC(","), 0);
929     if (find >= 0) {
930         family = SubstName.Left(find);
931         _PDF_GetStandardFontName(family);
932         style = SubstName.Mid(find + 1);
933         bHasComma = TRUE;
934     } else {
935         family = SubstName;
936     }
937     for (; iBaseFont < 12; iBaseFont ++)
938         if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
939             break;
940         }
941     int PitchFamily = 0;
942     FX_BOOL bItalic = FALSE;
943     FX_DWORD nStyle = 0;
944     FX_BOOL bStyleAvail = FALSE;
945     if (iBaseFont < 12) {
946         family = g_Base14FontNames[iBaseFont];
947         if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
948             nStyle |= FX_FONT_STYLE_Bold;
949         }
950         if ((iBaseFont % 4) / 2) {
951             nStyle |= FX_FONT_STYLE_Italic;
952         }
953         if (iBaseFont < 4) {
954             PitchFamily |= FXFONT_FF_FIXEDPITCH;
955         }
956         if (iBaseFont >= 8) {
957             PitchFamily |= FXFONT_FF_ROMAN;
958         }
959     } else {
960         if (!bHasComma) {
961             find = family.ReverseFind('-');
962             if (find >= 0) {
963                 style = family.Mid(find + 1);
964                 family = family.Left(find);
965                 bHasHypen = TRUE;
966             }
967         }
968         if (!bHasHypen) {
969             int nLen = family.GetLength();
970             int32_t nRet = GetStyleType(family, TRUE);
971             if (nRet > -1) {
972                 family = family.Left(nLen - g_FontStyles[nRet].len);
973                 if (nRet == 0) {
974                     nStyle |= FX_FONT_STYLE_Bold;
975                 }
976                 if (nRet == 1) {
977                     nStyle |= FX_FONT_STYLE_Italic;
978                 }
979                 if (nRet == 2) {
980                     nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
981                 }
982             }
983         }
984         if (flags & FXFONT_SERIF) {
985             PitchFamily |= FXFONT_FF_ROMAN;
986         }
987         if (flags & FXFONT_SCRIPT) {
988             PitchFamily |= FXFONT_FF_SCRIPT;
989         }
990         if (flags & FXFONT_FIXED_PITCH) {
991             PitchFamily |= FXFONT_FF_FIXEDPITCH;
992         }
993     }
994     if (!style.IsEmpty()) {
995         int nLen = style.GetLength();
996         const FX_CHAR* pStyle = style;
997         int i = 0;
998         FX_BOOL bFirstItem = TRUE;
999         CFX_ByteString buf;
1000         while (i < nLen) {
1001             buf = ParseStyle(pStyle, nLen, i);
1002             int32_t nRet = GetStyleType(buf, FALSE);
1003             if ((i && !bStyleAvail) || (!i && nRet < 0)) {
1004                 family = SubstName;
1005                 iBaseFont = 12;
1006                 break;
1007             } else if (nRet >= 0) {
1008                 bStyleAvail = TRUE;
1009             }
1010             if (nRet == 0) {
1011                 if (nStyle & FX_FONT_STYLE_Bold) {
1012                     nStyle |= FX_FONT_STYLE_BoldBold;
1013                 } else {
1014                     nStyle |= FX_FONT_STYLE_Bold;
1015                 }
1016                 bFirstItem = FALSE;
1017             }
1018             if (nRet == 1) {
1019                 if (bFirstItem) {
1020                     nStyle |= FX_FONT_STYLE_Italic;
1021                 } else {
1022                     family = SubstName;
1023                     iBaseFont = 12;
1024                 }
1025                 break;
1026             }
1027             if (nRet == 2) {
1028                 nStyle |= FX_FONT_STYLE_Italic;
1029                 if (nStyle & FX_FONT_STYLE_Bold) {
1030                     nStyle |= FX_FONT_STYLE_BoldBold;
1031                 } else {
1032                     nStyle |= FX_FONT_STYLE_Bold;
1033                 }
1034                 bFirstItem = FALSE;
1035             }
1036             i += buf.GetLength() + 1;
1037         }
1038     }
1039     weight = weight ? weight : FXFONT_FW_NORMAL;
1040     int old_weight = weight;
1041     if (nStyle) {
1042         weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1043     }
1044     if (nStyle & FX_FONT_STYLE_Italic) {
1045         bItalic = TRUE;
1046     }
1047     FX_BOOL bCJK = FALSE;
1048     int iExact = 0;
1049     int Charset = FXFONT_ANSI_CHARSET;
1050     if (WindowCP) {
1051         Charset = _GetCharsetFromCodePage(WindowCP);
1052     } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
1053         Charset = FXFONT_SYMBOL_CHARSET;
1054     }
1055     if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
1056             Charset == FXFONT_HANGEUL_CHARSET || Charset == FXFONT_CHINESEBIG5_CHARSET) {
1057         bCJK = TRUE;
1058     }
1059     if (m_pFontInfo == NULL) {
1060         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1061         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1062     }
1063     family = _GetFontFamily(family, nStyle);
1064     CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
1065     if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
1066         match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
1067     }
1068     if (match.IsEmpty() && iBaseFont >= 12) {
1069         if (!bCJK) {
1070             if (!CheckSupportThirdPartFont(family, PitchFamily)) {
1071                 if (italic_angle != 0) {
1072                     bItalic = TRUE;
1073                 } else {
1074                     bItalic = FALSE;
1075                 }
1076                 weight = old_weight;
1077             }
1078         } else {
1079             pSubstFont->m_bSubstOfCJK = TRUE;
1080             if (nStyle) {
1081                 pSubstFont->m_WeightCJK = weight;
1082             } else {
1083                 pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
1084             }
1085             if (nStyle & FX_FONT_STYLE_Italic) {
1086                 pSubstFont->m_bItlicCJK = TRUE;
1087             }
1088         }
1089     } else {
1090         italic_angle = 0;
1091         weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1092     }
1093     if (!match.IsEmpty() || iBaseFont < 12) {
1094         pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1095         if (!match.IsEmpty()) {
1096             family = match;
1097         }
1098         if (iBaseFont < 12) {
1099             if (nStyle && !(iBaseFont % 4)) {
1100                 if ((nStyle & 0x3) == 1) {
1101                     iBaseFont += 1;
1102                 }
1103                 if ((nStyle & 0x3) == 2) {
1104                     iBaseFont += 3;
1105                 }
1106                 if ((nStyle & 0x3) == 3) {
1107                     iBaseFont += 2;
1108                 }
1109             }
1110             if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
1111                 if (m_FoxitFaces[iBaseFont]) {
1112                     return m_FoxitFaces[iBaseFont];
1113                 }
1114                 m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
1115                                           m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
1116                 if (m_FoxitFaces[iBaseFont]) {
1117                     return m_FoxitFaces[iBaseFont];
1118                 }
1119             } else {
1120                 family = g_Base14FontNames[iBaseFont];
1121             }
1122             pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1123         }
1124     } else {
1125         if (flags & FXFONT_ITALIC) {
1126             bItalic = TRUE;
1127         }
1128     }
1129     iExact = !match.IsEmpty();
1130     void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, iExact);
1131     if (iExact) {
1132         pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1133     }
1134     if (hFont == NULL) {
1135         if (bCJK) {
1136             if (italic_angle != 0) {
1137                 bItalic = TRUE;
1138             } else {
1139                 bItalic = FALSE;
1140             }
1141             weight = old_weight;
1142         }
1143         if (!match.IsEmpty()) {
1144             hFont = m_pFontInfo->GetFont(match);
1145             if (hFont == NULL) {
1146                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1147             }
1148         } else {
1149             if (Charset == FXFONT_SYMBOL_CHARSET) {
1150 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_  == _FXM_PLATFORM_ANDROID_
1151                 if (SubstName == FX_BSTRC("Symbol")) {
1152                     pSubstFont->m_Family = "Chrome Symbol";
1153                     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1154                     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
1155                     if (m_FoxitFaces[12]) {
1156                         return m_FoxitFaces[12];
1157                     }
1158                     const uint8_t* pFontData = NULL;
1159                     FX_DWORD size = 0;
1160                     m_pFontMgr->GetStandardFont(pFontData, size, 12);
1161                     m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
1162                     return m_FoxitFaces[12];
1163                 }
1164 #endif
1165                 pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
1166                 return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);
1167             }
1168             if (Charset == FXFONT_ANSI_CHARSET) {
1169                 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1170                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1171             }
1172             int index = m_CharsetArray.Find(Charset);
1173             if (index < 0) {
1174                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1175             }
1176             hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
1177         }
1178     }
1179     pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
1180     if (hFont == NULL) {
1181         return NULL;
1182     }
1183     m_pFontInfo->GetFaceName(hFont, SubstName);
1184     if (Charset == FXFONT_DEFAULT_CHARSET) {
1185         m_pFontInfo->GetFontCharset(hFont, Charset);
1186     }
1187     FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
1188     FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
1189     if(font_size == 0 && ttc_size == 0) {
1190         m_pFontInfo->DeleteFont(hFont);
1191         return NULL;
1192     }
1193     FXFT_Face face = NULL;
1194     if (ttc_size) {
1195         uint8_t temp[1024];
1196         m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
1197         FX_DWORD checksum = 0;
1198         for (int i = 0; i < 256; i ++) {
1199             checksum += ((FX_DWORD*)temp)[i];
1200         }
1201         uint8_t* pFontData;
1202         face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData);
1203         if (face == NULL) {
1204             pFontData = FX_Alloc(uint8_t, ttc_size);
1205             m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
1206             face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size,
1207                                                 ttc_size - font_size);
1208         }
1209     } else {
1210         uint8_t* pFontData;
1211         face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
1212         if (face == NULL) {
1213             pFontData = FX_Alloc(uint8_t, font_size);
1214             m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
1215             face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, font_size, m_pFontInfo->GetFaceIndex(hFont));
1216         }
1217     }
1218     if (face == NULL) {
1219         m_pFontInfo->DeleteFont(hFont);
1220         return NULL;
1221     }
1222     pSubstFont->m_Family = SubstName;
1223     pSubstFont->m_Charset = Charset;
1224     FX_BOOL bNeedUpdateWeight = FALSE;
1225     if (FXFT_Is_Face_Bold(face)) {
1226         if (weight == FXFONT_FW_BOLD) {
1227             bNeedUpdateWeight = FALSE;
1228         } else {
1229             bNeedUpdateWeight = TRUE;
1230         }
1231     } else {
1232         if (weight == FXFONT_FW_NORMAL) {
1233             bNeedUpdateWeight = FALSE;
1234         } else {
1235             bNeedUpdateWeight = TRUE;
1236         }
1237     }
1238     if (bNeedUpdateWeight) {
1239         pSubstFont->m_Weight = weight;
1240     }
1241     if (bItalic && !FXFT_Is_Face_Italic(face)) {
1242         if (italic_angle == 0) {
1243             italic_angle = -12;
1244         } else if (FXSYS_abs(italic_angle) < 5) {
1245             italic_angle = 0;
1246         }
1247         pSubstFont->m_ItalicAngle = italic_angle;
1248     }
1249     m_pFontInfo->DeleteFont(hFont);
1250     return face;
1251 }
1252 extern "C" {
1253     unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,
1254                                 unsigned char* buffer, unsigned long count);
1255     void _FTStreamClose(FXFT_Stream stream);
1256 };
1257 CFontFileFaceInfo::CFontFileFaceInfo()
1258 {
1259     m_pFile = NULL;
1260     m_Face = NULL;
1261     m_Charsets = 0;
1262     m_FileSize = 0;
1263     m_FontOffset = 0;
1264     m_Weight = 0;
1265     m_bItalic = FALSE;
1266     m_PitchFamily = 0;
1267 }
1268 CFontFileFaceInfo::~CFontFileFaceInfo()
1269 {
1270     if (m_Face) {
1271         FXFT_Done_Face(m_Face);
1272     }
1273     m_Face = NULL;
1274 }
1275 extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream);
1276 #if _FX_OS_ == _FX_ANDROID_
1277 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault()
1278 {
1279     return NULL;
1280 }
1281 #endif
1282 CFX_FolderFontInfo::CFX_FolderFontInfo()
1283 {
1284 }
1285 CFX_FolderFontInfo::~CFX_FolderFontInfo()
1286 {
1287     FX_POSITION pos = m_FontList.GetStartPosition();
1288     while (pos) {
1289         CFX_ByteString key;
1290         void* value;
1291         m_FontList.GetNextAssoc(pos, key, value);
1292         delete (CFontFaceInfo*)value;
1293     }
1294 }
1295 void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path)
1296 {
1297     m_PathList.Add(path);
1298 }
1299 void CFX_FolderFontInfo::Release()
1300 {
1301     delete this;
1302 }
1303 FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper)
1304 {
1305     m_pMapper = pMapper;
1306     for (int i = 0; i < m_PathList.GetSize(); i ++) {
1307         ScanPath(m_PathList[i]);
1308     }
1309     return TRUE;
1310 }
1311 void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path)
1312 {
1313     void* handle = FX_OpenFolder(path);
1314     if (handle == NULL) {
1315         return;
1316     }
1317     CFX_ByteString filename;
1318     FX_BOOL bFolder;
1319     while (FX_GetNextFile(handle, filename, bFolder)) {
1320         if (bFolder) {
1321             if (filename == "." || filename == "..") {
1322                 continue;
1323             }
1324         } else {
1325             CFX_ByteString ext = filename.Right(4);
1326             ext.MakeUpper();
1327             if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
1328                 continue;
1329             }
1330         }
1331         CFX_ByteString fullpath = path;
1332 #if _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_
1333         fullpath += "\\";
1334 #else
1335         fullpath += "/";
1336 #endif
1337         fullpath += filename;
1338         if (bFolder) {
1339             ScanPath(fullpath);
1340         } else {
1341             ScanFile(fullpath);
1342         }
1343     }
1344     FX_CloseFolder(handle);
1345 }
1346 void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path)
1347 {
1348     FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
1349     if (pFile == NULL) {
1350         return;
1351     }
1352     FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
1353     FX_DWORD filesize = FXSYS_ftell(pFile);
1354     uint8_t buffer[16];
1355     FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
1356     size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
1357     if (readCnt != 1) {
1358         FXSYS_fclose(pFile);
1359         return;
1360     }
1361
1362     if (GET_TT_LONG(buffer) == 0x74746366) {
1363         FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
1364         if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) {
1365             FXSYS_fclose(pFile);
1366             return;
1367         }
1368         FX_DWORD face_bytes = nFaces * 4;
1369         uint8_t* offsets = FX_Alloc(uint8_t, face_bytes);
1370         readCnt = FXSYS_fread(offsets, face_bytes, 1, pFile);
1371         if (readCnt != face_bytes) {
1372             FX_Free(offsets);
1373             FXSYS_fclose(pFile);
1374             return;
1375         }
1376         for (FX_DWORD i = 0; i < nFaces; i ++) {
1377             uint8_t* p = offsets + i * 4;
1378             ReportFace(path, pFile, filesize, GET_TT_LONG(p));
1379         }
1380         FX_Free(offsets);
1381     } else {
1382         ReportFace(path, pFile, filesize, 0);
1383     }
1384     FXSYS_fclose(pFile);
1385 }
1386 void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, FXSYS_FILE* pFile, FX_DWORD filesize, FX_DWORD offset)
1387 {
1388     FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1389     char buffer[16];
1390     if (!FXSYS_fread(buffer, 12, 1, pFile)) {
1391         return;
1392     }
1393     FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
1394     CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
1395     if (tables.IsEmpty()) {
1396         return;
1397     }
1398     CFX_ByteString names = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
1399     CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);
1400     CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);
1401     if (style != "Regular") {
1402         facename += " " + style;
1403     }
1404     void* p;
1405     if (m_FontList.Lookup(facename, p)) {
1406         return;
1407     }
1408     CFontFaceInfo* pInfo = new CFontFaceInfo;
1409     pInfo->m_FilePath = path;
1410     pInfo->m_FaceName = facename;
1411     pInfo->m_FontTables = tables;
1412     pInfo->m_FontOffset = offset;
1413     pInfo->m_FileSize = filesize;
1414     pInfo->m_Charsets = 0;
1415     CFX_ByteString os2 = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
1416     if (os2.GetLength() >= 86) {
1417         const uint8_t* p = (const uint8_t*)os2 + 78;
1418         FX_DWORD codepages = GET_TT_LONG(p);
1419         if (codepages & (1 << 17)) {
1420             m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
1421             pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
1422         }
1423         if (codepages & (1 << 18)) {
1424             m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
1425             pInfo->m_Charsets |= CHARSET_FLAG_GB;
1426         }
1427         if (codepages & (1 << 20)) {
1428             m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
1429             pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
1430         }
1431         if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
1432             m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
1433             pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
1434         }
1435         if (codepages & (1 << 31)) {
1436             m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
1437             pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
1438         }
1439     }
1440     m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
1441     pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
1442     pInfo->m_Styles = 0;
1443     if (style.Find(FX_BSTRC("Bold")) > -1) {
1444         pInfo->m_Styles |= FXFONT_BOLD;
1445     }
1446     if (style.Find(FX_BSTRC("Italic")) > -1 || style.Find(FX_BSTRC("Oblique")) > -1) {
1447         pInfo->m_Styles |= FXFONT_ITALIC;
1448     }
1449     if (facename.Find(FX_BSTRC("Serif")) > -1) {
1450         pInfo->m_Styles |= FXFONT_SERIF;
1451     }
1452     m_FontList.SetAt(facename, pInfo);
1453 }
1454 void* CFX_FolderFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* family, int& iExact)
1455 {
1456     return NULL;
1457 }
1458 void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face)
1459 {
1460     void* p;
1461     if (!m_FontList.Lookup(face, p)) {
1462         return NULL;
1463     }
1464     return p;
1465 }
1466 FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, uint8_t* buffer, FX_DWORD size)
1467 {
1468     if (hFont == NULL) {
1469         return 0;
1470     }
1471     CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
1472     FXSYS_FILE* pFile = NULL;
1473     if (size > 0) {
1474         pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
1475         if (pFile == NULL) {
1476             return 0;
1477         }
1478     }
1479     FX_DWORD datasize = 0;
1480     FX_DWORD offset;
1481     if (table == 0)     {
1482         datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
1483         offset = 0;
1484     } else if (table == 0x74746366)     {
1485         datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
1486         offset = 0;
1487     } else {
1488         FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
1489         for (FX_DWORD i = 0; i < nTables; i ++) {
1490             const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16;
1491             if (GET_TT_LONG(p) == table) {
1492                 offset = GET_TT_LONG(p + 8);
1493                 datasize = GET_TT_LONG(p + 12);
1494             }
1495         }
1496     }
1497     if (datasize && size >= datasize && pFile) {
1498         FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1499         FXSYS_fread(buffer, datasize, 1, pFile);
1500     }
1501     if (pFile) {
1502         FXSYS_fclose(pFile);
1503     }
1504     return datasize;
1505 }
1506 void CFX_FolderFontInfo::DeleteFont(void* hFont)
1507 {
1508 }
1509 FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name)
1510 {
1511     if (hFont == NULL) {
1512         return FALSE;
1513     }
1514     CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
1515     name = pFont->m_FaceName;
1516     return TRUE;
1517 }
1518 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset)
1519 {
1520     return FALSE;
1521 }