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