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