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