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