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