Home | History | Annotate | Download | only in ge
      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         m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);
    568         result = _FPDF_GetNameFromTT(buffer, 6);
    569         FX_Free(buffer);
    570     }
    571     return result;
    572 }
    573 void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset)
    574 {
    575     if (m_pFontInfo == NULL) {
    576         return;
    577     }
    578     if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {
    579         m_CharsetArray.Add((FX_DWORD)charset);
    580         m_FaceArray.Add(name);
    581     }
    582     if (name == m_LastFamily) {
    583         return;
    584     }
    585     FX_LPCBYTE ptr = name;
    586     FX_BOOL bLocalized = FALSE;
    587     for (int i = 0; i < name.GetLength(); i ++)
    588         if (ptr[i] > 0x80) {
    589             bLocalized = TRUE;
    590             break;
    591         }
    592     if (bLocalized) {
    593         void* hFont = m_pFontInfo->GetFont(name);
    594         if (hFont == NULL) {
    595             FX_BOOL bExact;
    596             hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, bExact);
    597             if (hFont == NULL) {
    598                 return;
    599             }
    600         }
    601         CFX_ByteString new_name = GetPSNameFromTT(hFont);
    602         if (!new_name.IsEmpty()) {
    603             new_name.Insert(0, ' ');
    604             m_InstalledTTFonts.Add(new_name);
    605         }
    606         m_pFontInfo->DeleteFont(hFont);
    607     }
    608     m_InstalledTTFonts.Add(name);
    609     m_LastFamily = name;
    610 }
    611 void CFX_FontMapper::LoadInstalledFonts()
    612 {
    613     if (m_pFontInfo == NULL) {
    614         return;
    615     }
    616     if (m_bListLoaded) {
    617         return;
    618     }
    619     if (m_bListLoaded) {
    620         return;
    621     }
    622     m_pFontInfo->EnumFontList(this);
    623     m_bListLoaded = TRUE;
    624 }
    625 CFX_ByteString CFX_FontMapper::MatchInstalledFonts(const CFX_ByteString& norm_name)
    626 {
    627     LoadInstalledFonts();
    628     int i;
    629     for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i --) {
    630         CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);
    631         if (norm1 == norm_name) {
    632             break;
    633         }
    634     }
    635     if (i < 0) {
    636         return CFX_ByteString();
    637     }
    638     CFX_ByteString match = m_InstalledTTFonts[i];
    639     if (match[0] == ' ') {
    640         match = m_InstalledTTFonts[i + 1];
    641     }
    642     return match;
    643 }
    644 typedef struct _CHARSET_MAP_ {
    645     FX_BYTE charset;
    646     FX_WORD codepage;
    647 } CHARSET_MAP;
    648 static const CHARSET_MAP g_Codepage2CharsetTable[] = {
    649     { 1	 , 0	},
    650     { 2	 , 42	},
    651     { 254, 437	},
    652     { 255, 850	},
    653     { 222, 874	},
    654     { 128, 932	},
    655     { 134, 936	},
    656     { 129, 949	},
    657     { 136, 950	},
    658     { 238, 1250	},
    659     { 204, 1251	},
    660     { 0,   1252	},
    661     { 161, 1253	},
    662     { 162, 1254	},
    663     { 177, 1255	},
    664     { 178, 1256	},
    665     { 186, 1257	},
    666     { 163, 1258 },
    667     { 130, 1361 },
    668     { 77, 10000 },
    669     { 78, 10001 },
    670     { 79, 10003 },
    671     { 80, 10008 },
    672     { 81, 10002 },
    673     { 83, 10005 },
    674     { 84, 10004 },
    675     { 85, 10006 },
    676     { 86, 10081 },
    677     { 87, 10021 },
    678     { 88, 10029 },
    679     { 89, 10007 },
    680 };
    681 FX_BYTE _GetCharsetFromCodePage(FX_WORD codepage)
    682 {
    683     FX_INT32 iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;
    684     FXSYS_assert(iEnd >= 0);
    685     FX_INT32 iStart = 0, iMid;
    686     do {
    687         iMid = (iStart + iEnd) / 2;
    688         const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid];
    689         if (codepage == cp.codepage) {
    690             return cp.charset;
    691         } else if (codepage < cp.codepage) {
    692             iEnd = iMid - 1;
    693         } else {
    694             iStart = iMid + 1;
    695         }
    696     } while (iStart <= iEnd);
    697     return 1;
    698 }
    699 FX_DWORD _GetCodePageRangeFromCharset(int charset)
    700 {
    701     if (charset == FXFONT_EASTEUROPE_CHARSET) {
    702         return 1 << 1;
    703     }
    704     if (charset == FXFONT_GREEK_CHARSET) {
    705         return 1 << 3;
    706     }
    707     if (charset == FXFONT_TURKISH_CHARSET) {
    708         return 1 << 4;
    709     }
    710     if (charset == FXFONT_HEBREW_CHARSET) {
    711         return 1 << 5;
    712     }
    713     if (charset == FXFONT_ARABIC_CHARSET) {
    714         return 1 << 6;
    715     }
    716     if (charset == FXFONT_BALTIC_CHARSET) {
    717         return 1 << 7;
    718     }
    719     if (charset == FXFONT_THAI_CHARSET) {
    720         return 1 << 16;
    721     }
    722     if (charset == FXFONT_SHIFTJIS_CHARSET) {
    723         return 1 << 17;
    724     }
    725     if (charset == FXFONT_GB2312_CHARSET) {
    726         return 1 << 18;
    727     }
    728     if (charset == FXFONT_CHINESEBIG5_CHARSET) {
    729         return 1 << 20;
    730     }
    731     if (charset == FXFONT_HANGEUL_CHARSET) {
    732         return 1 << 19;
    733     }
    734     if (charset == FXFONT_SYMBOL_CHARSET) {
    735         return 1 << 31;
    736     }
    737     return 1 << 21;
    738 }
    739 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int picthfamily)
    740 {
    741     if (iBaseFont < 12) {
    742         if (m_FoxitFaces[iBaseFont]) {
    743             return m_FoxitFaces[iBaseFont];
    744         }
    745         FX_LPCBYTE pFontData = NULL;
    746         FX_DWORD size = 0;
    747         if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
    748             m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    749             return m_FoxitFaces[iBaseFont];
    750         }
    751     }
    752     pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
    753     pSubstFont->m_ItalicAngle = italic_angle;
    754     if (weight) {
    755         pSubstFont->m_Weight = weight;
    756     }
    757     if (picthfamily & FXFONT_FF_ROMAN) {
    758         pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
    759         pSubstFont->m_Family = "Chrome Serif";
    760         if (m_MMFaces[1]) {
    761             return m_MMFaces[1];
    762         }
    763         FX_LPCBYTE pFontData = NULL;
    764         FX_DWORD size;
    765         m_pFontMgr->GetStandardFont(pFontData, size, 14);
    766         m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    767         return m_MMFaces[1];
    768     }
    769     pSubstFont->m_Family = "Chrome Sans";
    770     if (m_MMFaces[0]) {
    771         return m_MMFaces[0];
    772     }
    773     FX_LPCBYTE pFontData = NULL;
    774     FX_DWORD size = 0;
    775     m_pFontMgr->GetStandardFont(pFontData, size, 15);
    776     m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    777     return m_MMFaces[0];
    778 }
    779 const struct _AltFontFamily {
    780     FX_LPCSTR m_pFontName;
    781     FX_LPCSTR m_pFontFamily;
    782 }
    783 g_AltFontFamilies[] = {
    784     {"AGaramondPro", "Adobe Garamond Pro"},
    785     {"BankGothicBT-Medium", "BankGothic Md BT"},
    786     {"ForteMT", "Forte"},
    787 };
    788 extern "C" {
    789     static int compareFontFamilyString(const void* key, const void* element)
    790     {
    791         CFX_ByteString str_key((FX_LPCSTR)key);
    792         if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
    793             return 0;
    794         }
    795         return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontFamily*)element)->m_pFontName);
    796     }
    797 }
    798 #define FX_FONT_STYLE_None		0x00
    799 #define FX_FONT_STYLE_Bold		0x01
    800 #define FX_FONT_STYLE_Italic	0x02
    801 #define FX_FONT_STYLE_BoldBold	0x04
    802 static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle)
    803 {
    804     if (fontName.Find("Script") >= 0) {
    805         if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
    806             fontName = "ScriptMTBold";
    807         } else if (fontName.Find("Palace") >= 0) {
    808             fontName = "PalaceScriptMT";
    809         } else if (fontName.Find("French") >= 0) {
    810             fontName = "FrenchScriptMT";
    811         } else if (fontName.Find("FreeStyle") >= 0) {
    812             fontName = "FreeStyleScript";
    813         }
    814         return fontName;
    815     }
    816     _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(fontName.c_str(), g_AltFontFamilies,
    817                             sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString);
    818     if (found == NULL) {
    819         return fontName;
    820     }
    821     return found->m_pFontFamily;
    822 };
    823 typedef struct _FX_FontStyle {
    824     FX_LPCSTR style;
    825     FX_INT32 len;
    826 } FX_FontStyle;
    827 const FX_FontStyle g_FontStyles[] = {
    828   { "Bold", 4 },
    829   { "Italic", 6 },
    830   { "BoldItalic", 10 },
    831   { "Reg", 3 },
    832   { "Regular", 7 },
    833 };
    834 CFX_ByteString ParseStyle(FX_LPCSTR pStyle, int iLen, int iIndex)
    835 {
    836     CFX_ByteTextBuf buf;
    837     if (!iLen || iLen <= iIndex) {
    838         return buf.GetByteString();
    839     }
    840     while (iIndex < iLen) {
    841         if (pStyle[iIndex] == ',') {
    842             break;
    843         }
    844         buf.AppendChar(pStyle[iIndex]);
    845         ++iIndex;
    846     }
    847     return buf.GetByteString();
    848 }
    849 FX_INT32 GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert)
    850 {
    851     FX_INT32 iLen = bsStyle.GetLength();
    852     if (!iLen) {
    853         return -1;
    854     }
    855     int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
    856     const FX_FontStyle *pStyle = NULL;
    857     for (int i = iSize - 1; i >= 0; --i) {
    858         pStyle = g_FontStyles + i;
    859         if (!pStyle || pStyle->len > iLen) {
    860             continue;
    861         }
    862         if (!bRevert) {
    863             if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
    864                 return i;
    865             }
    866         } else {
    867             if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
    868                 return i;
    869             }
    870         }
    871     }
    872     return -1;
    873 }
    874 FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int &PitchFamily)
    875 {
    876     if (name == FX_BSTRC("MyriadPro")) {
    877         PitchFamily &= ~FXFONT_FF_ROMAN;
    878         return TRUE;
    879     }
    880     return FALSE;
    881 }
    882 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, FX_BOOL bTrueType, FX_DWORD flags,
    883                                         int weight, int italic_angle, int WindowCP, CFX_SubstFont* pSubstFont)
    884 {
    885     if (!(flags & FXFONT_USEEXTERNATTR)) {
    886         weight = FXFONT_FW_NORMAL;
    887         italic_angle = 0;
    888     }
    889     CFX_ByteString SubstName = name;
    890     SubstName.Remove(0x20);
    891     if (bTrueType) {
    892         if (name[0] == '@') {
    893             SubstName = name.Mid(1);
    894         }
    895     }
    896     _PDF_GetStandardFontName(SubstName);
    897     if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
    898         pSubstFont->m_Family = "Chrome Symbol";
    899         pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
    900         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
    901         if (m_FoxitFaces[12]) {
    902             return m_FoxitFaces[12];
    903         }
    904         FX_LPCBYTE pFontData = NULL;
    905         FX_DWORD size = 0;
    906         m_pFontMgr->GetStandardFont(pFontData, size, 12);
    907         m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    908         return m_FoxitFaces[12];
    909     }
    910     if (SubstName == FX_BSTRC("ZapfDingbats")) {
    911         pSubstFont->m_Family = "Chrome Dingbats";
    912         pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
    913         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
    914         if (m_FoxitFaces[13]) {
    915             return m_FoxitFaces[13];
    916         }
    917         FX_LPCBYTE pFontData = NULL;
    918         FX_DWORD size = 0;
    919         m_pFontMgr->GetStandardFont(pFontData, size, 13);
    920         m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    921         return m_FoxitFaces[13];
    922     }
    923     int iBaseFont = 0;
    924     CFX_ByteString family, style;
    925     FX_BOOL	bHasComma = FALSE;
    926     FX_BOOL bHasHypen = FALSE;
    927     int find = SubstName.Find(FX_BSTRC(","), 0);
    928     if (find >= 0) {
    929         family = SubstName.Left(find);
    930         _PDF_GetStandardFontName(family);
    931         style = SubstName.Mid(find + 1);
    932         bHasComma = TRUE;
    933     } else {
    934         family = SubstName;
    935     }
    936     for (; iBaseFont < 12; iBaseFont ++)
    937         if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
    938             break;
    939         }
    940     int PitchFamily = 0;
    941     FX_BOOL bItalic = FALSE;
    942     FX_DWORD nStyle = 0;
    943     FX_BOOL bStyleAvail = FALSE;
    944     if (iBaseFont < 12) {
    945         family = g_Base14FontNames[iBaseFont];
    946         if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
    947             nStyle |= FX_FONT_STYLE_Bold;
    948         }
    949         if ((iBaseFont % 4) / 2) {
    950             nStyle |= FX_FONT_STYLE_Italic;
    951         }
    952         if (iBaseFont < 4) {
    953             PitchFamily |= FXFONT_FF_FIXEDPITCH;
    954         }
    955         if (iBaseFont >= 8) {
    956             PitchFamily |= FXFONT_FF_ROMAN;
    957         }
    958     } else {
    959         if (!bHasComma) {
    960             find = family.ReverseFind('-');
    961             if (find >= 0) {
    962                 style = family.Mid(find + 1);
    963                 family = family.Left(find);
    964                 bHasHypen = TRUE;
    965             }
    966         }
    967         if (!bHasHypen) {
    968             int nLen = family.GetLength();
    969             FX_INT32 nRet = GetStyleType(family, TRUE);
    970             if (nRet > -1) {
    971                 family = family.Left(nLen - g_FontStyles[nRet].len);
    972                 if (nRet == 0) {
    973                     nStyle |= FX_FONT_STYLE_Bold;
    974                 }
    975                 if (nRet == 1) {
    976                     nStyle |= FX_FONT_STYLE_Italic;
    977                 }
    978                 if (nRet == 2) {
    979                     nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
    980                 }
    981             }
    982         }
    983         if (flags & FXFONT_SERIF) {
    984             PitchFamily |= FXFONT_FF_ROMAN;
    985         }
    986         if (flags & FXFONT_SCRIPT) {
    987             PitchFamily |= FXFONT_FF_SCRIPT;
    988         }
    989         if (flags & FXFONT_FIXED_PITCH) {
    990             PitchFamily |= FXFONT_FF_FIXEDPITCH;
    991         }
    992     }
    993     if (!style.IsEmpty()) {
    994         int nLen = style.GetLength();
    995         FX_LPCSTR pStyle = style;
    996         int i = 0;
    997         FX_BOOL bFirstItem = TRUE;
    998         CFX_ByteString buf;
    999         while (i < nLen) {
   1000             buf = ParseStyle(pStyle, nLen, i);
   1001             FX_INT32 nRet = GetStyleType(buf, FALSE);
   1002             if ((i && !bStyleAvail) || (!i && nRet < 0)) {
   1003                 family = SubstName;
   1004                 iBaseFont = 12;
   1005                 break;
   1006             } else if (nRet >= 0) {
   1007                 bStyleAvail = TRUE;
   1008             }
   1009             if (nRet == 0) {
   1010                 if (nStyle & FX_FONT_STYLE_Bold) {
   1011                     nStyle |= FX_FONT_STYLE_BoldBold;
   1012                 } else {
   1013                     nStyle |= FX_FONT_STYLE_Bold;
   1014                 }
   1015                 bFirstItem = FALSE;
   1016             }
   1017             if (nRet == 1) {
   1018                 if (bFirstItem) {
   1019                     nStyle |= FX_FONT_STYLE_Italic;
   1020                 } else {
   1021                     family = SubstName;
   1022                     iBaseFont = 12;
   1023                 }
   1024                 break;
   1025             }
   1026             if (nRet == 2) {
   1027                 nStyle |= FX_FONT_STYLE_Italic;
   1028                 if (nStyle & FX_FONT_STYLE_Bold) {
   1029                     nStyle |= FX_FONT_STYLE_BoldBold;
   1030                 } else {
   1031                     nStyle |= FX_FONT_STYLE_Bold;
   1032                 }
   1033                 bFirstItem = FALSE;
   1034             }
   1035             i += buf.GetLength() + 1;
   1036         }
   1037     }
   1038     weight = weight ? weight : FXFONT_FW_NORMAL;
   1039     int old_weight = weight;
   1040     if (nStyle) {
   1041         weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
   1042     }
   1043     if (nStyle & FX_FONT_STYLE_Italic) {
   1044         bItalic = TRUE;
   1045     }
   1046     FX_BOOL bCJK = FALSE;
   1047     FX_BOOL bExact = FALSE;
   1048     int Charset = FXFONT_ANSI_CHARSET;
   1049     if (WindowCP) {
   1050         Charset = _GetCharsetFromCodePage(WindowCP);
   1051     } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
   1052         Charset = FXFONT_SYMBOL_CHARSET;
   1053     }
   1054     if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
   1055             Charset == FXFONT_HANGEUL_CHARSET || Charset == FXFONT_CHINESEBIG5_CHARSET) {
   1056         bCJK = TRUE;
   1057     }
   1058     if (m_pFontInfo == NULL) {
   1059         pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
   1060         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
   1061     }
   1062     family = _GetFontFamily(family, nStyle);
   1063     CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
   1064     if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
   1065         match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
   1066     }
   1067     if (match.IsEmpty() && iBaseFont >= 12) {
   1068         if (!bCJK) {
   1069             if (!CheckSupportThirdPartFont(family, PitchFamily)) {
   1070                 if (italic_angle != 0) {
   1071                     bItalic = TRUE;
   1072                 } else {
   1073                     bItalic = FALSE;
   1074                 }
   1075                 weight = old_weight;
   1076             }
   1077         } else {
   1078             pSubstFont->m_bSubstOfCJK = TRUE;
   1079             if (nStyle) {
   1080                 pSubstFont->m_WeightCJK = weight;
   1081             } else {
   1082                 pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
   1083             }
   1084             if (nStyle & FX_FONT_STYLE_Italic) {
   1085                 pSubstFont->m_bItlicCJK = TRUE;
   1086             }
   1087         }
   1088     } else {
   1089         italic_angle = 0;
   1090         weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
   1091     }
   1092     if (!match.IsEmpty() || iBaseFont < 12) {
   1093         pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
   1094         if (!match.IsEmpty()) {
   1095             family = match;
   1096         }
   1097         if (iBaseFont < 12) {
   1098             if (nStyle && !(iBaseFont % 4)) {
   1099                 if ((nStyle & 0x3) == 1) {
   1100                     iBaseFont += 1;
   1101                 }
   1102                 if ((nStyle & 0x3) == 2) {
   1103                     iBaseFont += 3;
   1104                 }
   1105                 if ((nStyle & 0x3) == 3) {
   1106                     iBaseFont += 2;
   1107                 }
   1108             }
   1109             if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
   1110                 if (m_FoxitFaces[iBaseFont]) {
   1111                     return m_FoxitFaces[iBaseFont];
   1112                 }
   1113                 m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
   1114                                           m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
   1115                 if (m_FoxitFaces[iBaseFont]) {
   1116                     return m_FoxitFaces[iBaseFont];
   1117                 }
   1118             } else {
   1119                 family = g_Base14FontNames[iBaseFont];
   1120             }
   1121             pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
   1122         }
   1123     } else {
   1124         if (flags & FXFONT_ITALIC) {
   1125             bItalic = TRUE;
   1126         }
   1127     }
   1128     bExact = !match.IsEmpty();
   1129     void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, bExact);
   1130     if (bExact) {
   1131         pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
   1132     }
   1133     if (hFont == NULL) {
   1134         if (bCJK) {
   1135             if (italic_angle != 0) {
   1136                 bItalic = TRUE;
   1137             } else {
   1138                 bItalic = FALSE;
   1139             }
   1140             weight = old_weight;
   1141         }
   1142         if (!match.IsEmpty()) {
   1143             hFont = m_pFontInfo->GetFont(match);
   1144             if (hFont == NULL) {
   1145                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
   1146             }
   1147         } else {
   1148             if (Charset == FXFONT_SYMBOL_CHARSET) {
   1149 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_  == _FXM_PLATFORM_ANDROID_
   1150                 if (SubstName == FX_BSTRC("Symbol")) {
   1151                     pSubstFont->m_Family = "Chrome Symbol";
   1152                     pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
   1153                     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
   1154                     if (m_FoxitFaces[12]) {
   1155                         return m_FoxitFaces[12];
   1156                     }
   1157                     FX_LPCBYTE pFontData = NULL;
   1158                     FX_DWORD size = 0;
   1159                     m_pFontMgr->GetStandardFont(pFontData, size, 12);
   1160                     m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
   1161                     return m_FoxitFaces[12];
   1162                 } else {
   1163                     pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
   1164                     return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);
   1165                 }
   1166 #else
   1167                 pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
   1168                 return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);
   1169 #endif
   1170             }
   1171             if (Charset == FXFONT_ANSI_CHARSET) {
   1172                 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
   1173                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
   1174             }
   1175             int index = m_CharsetArray.Find(Charset);
   1176             if (index < 0) {
   1177                 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
   1178             } else {
   1179                 hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
   1180             }
   1181         }
   1182     }
   1183     pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
   1184     if (hFont == NULL) {
   1185         return NULL;
   1186     }
   1187     m_pFontInfo->GetFaceName(hFont, SubstName);
   1188     if (Charset == FXFONT_DEFAULT_CHARSET) {
   1189         m_pFontInfo->GetFontCharset(hFont, Charset);
   1190     }
   1191     FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
   1192     FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
   1193     if(font_size == 0 && ttc_size == 0) {
   1194         m_pFontInfo->DeleteFont(hFont);
   1195         return NULL;
   1196     }
   1197     FXFT_Face face = NULL;
   1198     if (ttc_size) {
   1199         FX_BYTE temp[1024];
   1200         m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
   1201         FX_DWORD checksum = 0;
   1202         for (int i = 0; i < 256; i ++) {
   1203             checksum += ((FX_DWORD*)temp)[i];
   1204         }
   1205         FX_LPBYTE pFontData;
   1206         face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData);
   1207         if (face == NULL) {
   1208             pFontData = FX_Alloc(FX_BYTE, ttc_size);
   1209             m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
   1210             face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size,
   1211                                                 ttc_size - font_size);
   1212         }
   1213     } else {
   1214         FX_LPBYTE pFontData;
   1215         face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
   1216         if (face == NULL) {
   1217             pFontData = FX_Alloc(FX_BYTE, font_size);
   1218             m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
   1219             face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, font_size, m_pFontInfo->GetFaceIndex(hFont));
   1220         }
   1221     }
   1222     if (face == NULL) {
   1223         m_pFontInfo->DeleteFont(hFont);
   1224         return NULL;
   1225     }
   1226     pSubstFont->m_Family = SubstName;
   1227     pSubstFont->m_Charset = Charset;
   1228     FX_BOOL bNeedUpdateWeight = FALSE;
   1229     if (FXFT_Is_Face_Bold(face)) {
   1230         if (weight == FXFONT_FW_BOLD) {
   1231             bNeedUpdateWeight = FALSE;
   1232         } else {
   1233             bNeedUpdateWeight = TRUE;
   1234         }
   1235     } else {
   1236         if (weight == FXFONT_FW_NORMAL) {
   1237             bNeedUpdateWeight = FALSE;
   1238         } else {
   1239             bNeedUpdateWeight = TRUE;
   1240         }
   1241     }
   1242     if (bNeedUpdateWeight) {
   1243         pSubstFont->m_Weight = weight;
   1244     }
   1245     if (bItalic && !FXFT_Is_Face_Italic(face)) {
   1246         if (italic_angle == 0) {
   1247             italic_angle = -12;
   1248         } else if (FXSYS_abs(italic_angle) < 5) {
   1249             italic_angle = 0;
   1250         }
   1251         pSubstFont->m_ItalicAngle = italic_angle;
   1252     }
   1253     m_pFontInfo->DeleteFont(hFont);
   1254     return face;
   1255 }
   1256 extern "C" {
   1257     unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,
   1258                                 unsigned char* buffer, unsigned long count);
   1259     void _FTStreamClose(FXFT_Stream stream);
   1260 };
   1261 CFontFileFaceInfo::CFontFileFaceInfo()
   1262 {
   1263     m_pFile = NULL;
   1264     m_Face = NULL;
   1265     m_Charsets = 0;
   1266     m_FileSize = 0;
   1267     m_FontOffset = 0;
   1268     m_Weight = 0;
   1269     m_bItalic = FALSE;
   1270     m_PitchFamily = 0;
   1271 }
   1272 CFontFileFaceInfo::~CFontFileFaceInfo()
   1273 {
   1274     if (m_Face) {
   1275         FXFT_Done_Face(m_Face);
   1276     }
   1277     m_Face = NULL;
   1278 }
   1279 extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream);
   1280 #if _FX_OS_ == _FX_ANDROID_
   1281 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault()
   1282 {
   1283     return NULL;
   1284 }
   1285 #endif
   1286 CFX_FolderFontInfo::CFX_FolderFontInfo()
   1287 {
   1288 }
   1289 CFX_FolderFontInfo::~CFX_FolderFontInfo()
   1290 {
   1291     FX_POSITION pos = m_FontList.GetStartPosition();
   1292     while (pos) {
   1293         CFX_ByteString key;
   1294         FX_LPVOID value;
   1295         m_FontList.GetNextAssoc(pos, key, value);
   1296         delete (CFontFaceInfo*)value;
   1297     }
   1298 }
   1299 void CFX_FolderFontInfo::AddPath(FX_BSTR path)
   1300 {
   1301     m_PathList.Add(path);
   1302 }
   1303 void CFX_FolderFontInfo::Release()
   1304 {
   1305     delete this;
   1306 }
   1307 FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper)
   1308 {
   1309     m_pMapper = pMapper;
   1310     for (int i = 0; i < m_PathList.GetSize(); i ++) {
   1311         ScanPath(m_PathList[i]);
   1312     }
   1313     return TRUE;
   1314 }
   1315 void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path)
   1316 {
   1317     void* handle = FX_OpenFolder(path);
   1318     if (handle == NULL) {
   1319         return;
   1320     }
   1321     CFX_ByteString filename;
   1322     FX_BOOL bFolder;
   1323     while (FX_GetNextFile(handle, filename, bFolder)) {
   1324         if (bFolder) {
   1325             if (filename == "." || filename == "..") {
   1326                 continue;
   1327             }
   1328         } else {
   1329             CFX_ByteString ext = filename.Right(4);
   1330             ext.MakeUpper();
   1331             if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
   1332                 continue;
   1333             }
   1334         }
   1335         CFX_ByteString fullpath = path;
   1336 #if _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_
   1337         fullpath += "\\";
   1338 #else
   1339         fullpath += "/";
   1340 #endif
   1341         fullpath += filename;
   1342         if (bFolder) {
   1343             ScanPath(fullpath);
   1344         } else {
   1345             ScanFile(fullpath);
   1346         }
   1347     }
   1348     FX_CloseFolder(handle);
   1349 }
   1350 void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path)
   1351 {
   1352     FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
   1353     if (pFile == NULL) {
   1354         return;
   1355     }
   1356     FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
   1357     FX_DWORD filesize = FXSYS_ftell(pFile);
   1358     FX_BYTE buffer[16];
   1359     FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
   1360     size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
   1361     if (readCnt != 1) {
   1362         FXSYS_fclose(pFile);
   1363         return;
   1364     }
   1365 
   1366     if (GET_TT_LONG(buffer) == 0x74746366) {
   1367         FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
   1368         if (nFaces > FX_DWORD_MAX / 4) {
   1369             FXSYS_fclose(pFile);
   1370             return;
   1371         }
   1372         FX_DWORD face_bytes = nFaces * 4;
   1373         FX_LPBYTE offsets = FX_Alloc(FX_BYTE, face_bytes);
   1374         readCnt = FXSYS_fread(offsets, face_bytes, 1, pFile);
   1375         if (readCnt != face_bytes) {
   1376             FX_Free(offsets);
   1377             FXSYS_fclose(pFile);
   1378             return;
   1379         }
   1380         for (FX_DWORD i = 0; i < nFaces; i ++) {
   1381             FX_LPBYTE p = offsets + i * 4;
   1382             ReportFace(path, pFile, filesize, GET_TT_LONG(p));
   1383         }
   1384         FX_Free(offsets);
   1385     } else {
   1386         ReportFace(path, pFile, filesize, 0);
   1387     }
   1388     FXSYS_fclose(pFile);
   1389 }
   1390 void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, FXSYS_FILE* pFile, FX_DWORD filesize, FX_DWORD offset)
   1391 {
   1392     FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
   1393     char buffer[16];
   1394     if (!FXSYS_fread(buffer, 12, 1, pFile)) {
   1395         return;
   1396     }
   1397     FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
   1398     CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
   1399     if (tables.IsEmpty()) {
   1400         return;
   1401     }
   1402     CFX_ByteString names = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
   1403     CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);
   1404     CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);
   1405     if (style != "Regular") {
   1406         facename += " " + style;
   1407     }
   1408     FX_LPVOID p;
   1409     if (m_FontList.Lookup(facename, p)) {
   1410         return;
   1411     }
   1412     CFontFaceInfo* pInfo = new CFontFaceInfo;
   1413     pInfo->m_FilePath = path;
   1414     pInfo->m_FaceName = facename;
   1415     pInfo->m_FontTables = tables;
   1416     pInfo->m_FontOffset = offset;
   1417     pInfo->m_FileSize = filesize;
   1418     pInfo->m_Charsets = 0;
   1419     CFX_ByteString os2 = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
   1420     if (os2.GetLength() >= 86) {
   1421         FX_LPCBYTE p = (FX_LPCBYTE)os2 + 78;
   1422         FX_DWORD codepages = GET_TT_LONG(p);
   1423         if (codepages & (1 << 17)) {
   1424             m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
   1425             pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
   1426         }
   1427         if (codepages & (1 << 18)) {
   1428             m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
   1429             pInfo->m_Charsets |= CHARSET_FLAG_GB;
   1430         }
   1431         if (codepages & (1 << 20)) {
   1432             m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
   1433             pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
   1434         }
   1435         if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
   1436             m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
   1437             pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
   1438         }
   1439         if (codepages & (1 << 31)) {
   1440             m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
   1441             pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
   1442         }
   1443     }
   1444     m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
   1445     pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
   1446     pInfo->m_Styles = 0;
   1447     if (style.Find(FX_BSTRC("Bold")) > -1) {
   1448         pInfo->m_Styles |= FXFONT_BOLD;
   1449     }
   1450     if (style.Find(FX_BSTRC("Italic")) > -1 || style.Find(FX_BSTRC("Oblique")) > -1) {
   1451         pInfo->m_Styles |= FXFONT_ITALIC;
   1452     }
   1453     if (facename.Find(FX_BSTRC("Serif")) > -1) {
   1454         pInfo->m_Styles |= FXFONT_SERIF;
   1455     }
   1456     m_FontList.SetAt(facename, pInfo);
   1457 }
   1458 void* CFX_FolderFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL& bExact)
   1459 {
   1460     return NULL;
   1461 }
   1462 void* CFX_FolderFontInfo::GetFont(FX_LPCSTR face)
   1463 {
   1464     FX_LPVOID p;
   1465     if (!m_FontList.Lookup(face, p)) {
   1466         return NULL;
   1467     }
   1468     return p;
   1469 }
   1470 FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, FX_LPBYTE buffer, FX_DWORD size)
   1471 {
   1472     if (hFont == NULL) {
   1473         return 0;
   1474     }
   1475     CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
   1476     FXSYS_FILE* pFile = NULL;
   1477     if (size > 0) {
   1478         pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
   1479         if (pFile == NULL) {
   1480             return 0;
   1481         }
   1482     }
   1483     FX_DWORD datasize = 0;
   1484     FX_DWORD offset;
   1485     if (table == 0)	{
   1486         datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
   1487         offset = 0;
   1488     } else if (table == 0x74746366)	{
   1489         datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
   1490         offset = 0;
   1491     } else {
   1492         FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
   1493         for (FX_DWORD i = 0; i < nTables; i ++) {
   1494             FX_LPCBYTE p = (FX_LPCBYTE)pFont->m_FontTables + i * 16;
   1495             if (GET_TT_LONG(p) == table) {
   1496                 offset = GET_TT_LONG(p + 8);
   1497                 datasize = GET_TT_LONG(p + 12);
   1498             }
   1499         }
   1500     }
   1501     if (datasize && size >= datasize && pFile) {
   1502         FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
   1503         FXSYS_fread(buffer, datasize, 1, pFile);
   1504     }
   1505     if (pFile) {
   1506         FXSYS_fclose(pFile);
   1507     }
   1508     return datasize;
   1509 }
   1510 void CFX_FolderFontInfo::DeleteFont(void* hFont)
   1511 {
   1512 }
   1513 FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name)
   1514 {
   1515     if (hFont == NULL) {
   1516         return FALSE;
   1517     }
   1518     CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
   1519     name = pFont->m_FaceName;
   1520     return TRUE;
   1521 }
   1522 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset)
   1523 {
   1524     return FALSE;
   1525 }
   1526