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