Home | History | Annotate | Download | only in ge
      1 // Copyright 2016 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 "core/fxge/cfx_fontmapper.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "core/fxge/cfx_substfont.h"
     14 #include "core/fxge/fx_font.h"
     15 #include "core/fxge/ifx_systemfontinfo.h"
     16 
     17 #include "third_party/base/stl_util.h"
     18 
     19 #define FX_FONT_STYLE_None 0x00
     20 #define FX_FONT_STYLE_Bold 0x01
     21 #define FX_FONT_STYLE_Italic 0x02
     22 #define FX_FONT_STYLE_BoldBold 0x04
     23 
     24 namespace {
     25 
     26 const int kNumStandardFonts = 14;
     27 
     28 const FX_CHAR* const g_Base14FontNames[kNumStandardFonts] = {
     29     "Courier",
     30     "Courier-Bold",
     31     "Courier-BoldOblique",
     32     "Courier-Oblique",
     33     "Helvetica",
     34     "Helvetica-Bold",
     35     "Helvetica-BoldOblique",
     36     "Helvetica-Oblique",
     37     "Times-Roman",
     38     "Times-Bold",
     39     "Times-BoldItalic",
     40     "Times-Italic",
     41     "Symbol",
     42     "ZapfDingbats",
     43 };
     44 
     45 const struct AltFontName {
     46   const FX_CHAR* m_pName;
     47   int m_Index;
     48 } g_AltFontNames[] = {
     49     {"Arial", 4},
     50     {"Arial,Bold", 5},
     51     {"Arial,BoldItalic", 6},
     52     {"Arial,Italic", 7},
     53     {"Arial-Bold", 5},
     54     {"Arial-BoldItalic", 6},
     55     {"Arial-BoldItalicMT", 6},
     56     {"Arial-BoldMT", 5},
     57     {"Arial-Italic", 7},
     58     {"Arial-ItalicMT", 7},
     59     {"ArialBold", 5},
     60     {"ArialBoldItalic", 6},
     61     {"ArialItalic", 7},
     62     {"ArialMT", 4},
     63     {"ArialMT,Bold", 5},
     64     {"ArialMT,BoldItalic", 6},
     65     {"ArialMT,Italic", 7},
     66     {"ArialRoundedMTBold", 5},
     67     {"Courier", 0},
     68     {"Courier,Bold", 1},
     69     {"Courier,BoldItalic", 2},
     70     {"Courier,Italic", 3},
     71     {"Courier-Bold", 1},
     72     {"Courier-BoldOblique", 2},
     73     {"Courier-Oblique", 3},
     74     {"CourierBold", 1},
     75     {"CourierBoldItalic", 2},
     76     {"CourierItalic", 3},
     77     {"CourierNew", 0},
     78     {"CourierNew,Bold", 1},
     79     {"CourierNew,BoldItalic", 2},
     80     {"CourierNew,Italic", 3},
     81     {"CourierNew-Bold", 1},
     82     {"CourierNew-BoldItalic", 2},
     83     {"CourierNew-Italic", 3},
     84     {"CourierNewBold", 1},
     85     {"CourierNewBoldItalic", 2},
     86     {"CourierNewItalic", 3},
     87     {"CourierNewPS-BoldItalicMT", 2},
     88     {"CourierNewPS-BoldMT", 1},
     89     {"CourierNewPS-ItalicMT", 3},
     90     {"CourierNewPSMT", 0},
     91     {"CourierStd", 0},
     92     {"CourierStd-Bold", 1},
     93     {"CourierStd-BoldOblique", 2},
     94     {"CourierStd-Oblique", 3},
     95     {"Helvetica", 4},
     96     {"Helvetica,Bold", 5},
     97     {"Helvetica,BoldItalic", 6},
     98     {"Helvetica,Italic", 7},
     99     {"Helvetica-Bold", 5},
    100     {"Helvetica-BoldItalic", 6},
    101     {"Helvetica-BoldOblique", 6},
    102     {"Helvetica-Italic", 7},
    103     {"Helvetica-Oblique", 7},
    104     {"HelveticaBold", 5},
    105     {"HelveticaBoldItalic", 6},
    106     {"HelveticaItalic", 7},
    107     {"Symbol", 12},
    108     {"SymbolMT", 12},
    109     {"Times-Bold", 9},
    110     {"Times-BoldItalic", 10},
    111     {"Times-Italic", 11},
    112     {"Times-Roman", 8},
    113     {"TimesBold", 9},
    114     {"TimesBoldItalic", 10},
    115     {"TimesItalic", 11},
    116     {"TimesNewRoman", 8},
    117     {"TimesNewRoman,Bold", 9},
    118     {"TimesNewRoman,BoldItalic", 10},
    119     {"TimesNewRoman,Italic", 11},
    120     {"TimesNewRoman-Bold", 9},
    121     {"TimesNewRoman-BoldItalic", 10},
    122     {"TimesNewRoman-Italic", 11},
    123     {"TimesNewRomanBold", 9},
    124     {"TimesNewRomanBoldItalic", 10},
    125     {"TimesNewRomanItalic", 11},
    126     {"TimesNewRomanPS", 8},
    127     {"TimesNewRomanPS-Bold", 9},
    128     {"TimesNewRomanPS-BoldItalic", 10},
    129     {"TimesNewRomanPS-BoldItalicMT", 10},
    130     {"TimesNewRomanPS-BoldMT", 9},
    131     {"TimesNewRomanPS-Italic", 11},
    132     {"TimesNewRomanPS-ItalicMT", 11},
    133     {"TimesNewRomanPSMT", 8},
    134     {"TimesNewRomanPSMT,Bold", 9},
    135     {"TimesNewRomanPSMT,BoldItalic", 10},
    136     {"TimesNewRomanPSMT,Italic", 11},
    137     {"ZapfDingbats", 13},
    138 };
    139 
    140 const struct AltFontFamily {
    141   const FX_CHAR* m_pFontName;
    142   const FX_CHAR* m_pFontFamily;
    143 } g_AltFontFamilies[] = {
    144     {"AGaramondPro", "Adobe Garamond Pro"},
    145     {"BankGothicBT-Medium", "BankGothic Md BT"},
    146     {"ForteMT", "Forte"},
    147 };
    148 
    149 const struct FX_FontStyle {
    150   const FX_CHAR* style;
    151   int32_t len;
    152 } g_FontStyles[] = {
    153     {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7},
    154 };
    155 
    156 const struct CODEPAGE_MAP {
    157   uint16_t codepage;
    158   uint8_t charset;
    159 } g_Codepage2CharsetTable[] = {
    160     {0, 1},      {42, 2},     {437, 254},  {850, 255},  {874, 222},
    161     {932, 128},  {936, 134},  {949, 129},  {950, 136},  {1250, 238},
    162     {1251, 204}, {1252, 0},   {1253, 161}, {1254, 162}, {1255, 177},
    163     {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77},
    164     {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83},
    165     {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88},
    166     {10081, 86},
    167 };
    168 
    169 int CompareFontFamilyString(const void* key, const void* element) {
    170   CFX_ByteString str_key((const FX_CHAR*)key);
    171   const AltFontFamily* family = reinterpret_cast<const AltFontFamily*>(element);
    172   if (str_key.Find(family->m_pFontName) != -1)
    173     return 0;
    174   return FXSYS_stricmp(reinterpret_cast<const FX_CHAR*>(key),
    175                        family->m_pFontName);
    176 }
    177 
    178 int CompareString(const void* key, const void* element) {
    179   return FXSYS_stricmp(reinterpret_cast<const FX_CHAR*>(key),
    180                        reinterpret_cast<const AltFontName*>(element)->m_pName);
    181 }
    182 
    183 CFX_ByteString TT_NormalizeName(const FX_CHAR* family) {
    184   CFX_ByteString norm(family);
    185   norm.Remove(' ');
    186   norm.Remove('-');
    187   norm.Remove(',');
    188   int pos = norm.Find('+');
    189   if (pos > 0)
    190     norm = norm.Left(pos);
    191   norm.MakeLower();
    192   return norm;
    193 }
    194 
    195 uint8_t GetCharsetFromCodePage(uint16_t codepage) {
    196   const CODEPAGE_MAP* pEnd =
    197       g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable);
    198   const CODEPAGE_MAP* pCharmap =
    199       std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage,
    200                        [](const CODEPAGE_MAP& charset, uint16_t page) {
    201                          return charset.codepage < page;
    202                        });
    203   if (pCharmap < pEnd && codepage == pCharmap->codepage)
    204     return pCharmap->charset;
    205   return FXFONT_DEFAULT_CHARSET;
    206 }
    207 
    208 CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) {
    209   if (fontName.Find("Script") >= 0) {
    210     if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold)
    211       fontName = "ScriptMTBold";
    212     else if (fontName.Find("Palace") >= 0)
    213       fontName = "PalaceScriptMT";
    214     else if (fontName.Find("French") >= 0)
    215       fontName = "FrenchScriptMT";
    216     else if (fontName.Find("FreeStyle") >= 0)
    217       fontName = "FreeStyleScript";
    218     return fontName;
    219   }
    220   AltFontFamily* found = reinterpret_cast<AltFontFamily*>(FXSYS_bsearch(
    221       fontName.c_str(), g_AltFontFamilies, FX_ArraySize(g_AltFontFamilies),
    222       sizeof(AltFontFamily), CompareFontFamilyString));
    223   return found ? CFX_ByteString(found->m_pFontFamily) : fontName;
    224 }
    225 
    226 CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) {
    227   CFX_ByteTextBuf buf;
    228   if (!iLen || iLen <= iIndex)
    229     return buf.MakeString();
    230   while (iIndex < iLen) {
    231     if (pStyle[iIndex] == ',')
    232       break;
    233     buf.AppendChar(pStyle[iIndex]);
    234     ++iIndex;
    235   }
    236   return buf.MakeString();
    237 }
    238 
    239 int32_t GetStyleType(const CFX_ByteString& bsStyle, bool bReverse) {
    240   int32_t iLen = bsStyle.GetLength();
    241   if (!iLen)
    242     return -1;
    243   int iSize = FX_ArraySize(g_FontStyles);
    244   const FX_FontStyle* pStyle = nullptr;
    245   for (int i = iSize - 1; i >= 0; --i) {
    246     pStyle = g_FontStyles + i;
    247     if (!pStyle || pStyle->len > iLen)
    248       continue;
    249 
    250     if (bReverse) {
    251       if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0)
    252         return i;
    253     } else {
    254       if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0)
    255         return i;
    256     }
    257   }
    258   return -1;
    259 }
    260 
    261 bool CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) {
    262   if (name == "MyriadPro") {
    263     PitchFamily &= ~FXFONT_FF_ROMAN;
    264     return true;
    265   }
    266   return false;
    267 }
    268 
    269 void UpdatePitchFamily(uint32_t flags, int& PitchFamily) {
    270   if (flags & FXFONT_SERIF)
    271     PitchFamily |= FXFONT_FF_ROMAN;
    272   if (flags & FXFONT_SCRIPT)
    273     PitchFamily |= FXFONT_FF_SCRIPT;
    274   if (flags & FXFONT_FIXED_PITCH)
    275     PitchFamily |= FXFONT_FF_FIXEDPITCH;
    276 }
    277 
    278 }  // namespace
    279 
    280 CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr)
    281     : m_bListLoaded(false), m_pFontMgr(mgr) {
    282   m_MMFaces[0] = nullptr;
    283   m_MMFaces[1] = nullptr;
    284   FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces));
    285 }
    286 
    287 CFX_FontMapper::~CFX_FontMapper() {
    288   for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) {
    289     if (m_FoxitFaces[i])
    290       FXFT_Done_Face(m_FoxitFaces[i]);
    291   }
    292   if (m_MMFaces[0])
    293     FXFT_Done_Face(m_MMFaces[0]);
    294   if (m_MMFaces[1])
    295     FXFT_Done_Face(m_MMFaces[1]);
    296 }
    297 
    298 void CFX_FontMapper::SetSystemFontInfo(
    299     std::unique_ptr<IFX_SystemFontInfo> pFontInfo) {
    300   if (!pFontInfo)
    301     return;
    302 
    303   m_pFontInfo = std::move(pFontInfo);
    304 }
    305 
    306 CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) {
    307   if (!m_pFontInfo)
    308     return CFX_ByteString();
    309 
    310   uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0);
    311   if (!size)
    312     return CFX_ByteString();
    313 
    314   std::vector<uint8_t> buffer(size);
    315   uint8_t* buffer_ptr = buffer.data();
    316   uint32_t bytes_read =
    317       m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size);
    318   return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6)
    319                             : CFX_ByteString();
    320 }
    321 
    322 void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) {
    323   if (!m_pFontInfo)
    324     return;
    325 
    326   m_FaceArray.push_back({name, static_cast<uint32_t>(charset)});
    327   if (name == m_LastFamily)
    328     return;
    329 
    330   const uint8_t* ptr = name.raw_str();
    331   bool bLocalized = false;
    332   for (int i = 0; i < name.GetLength(); i++) {
    333     if (ptr[i] > 0x80) {
    334       bLocalized = true;
    335       break;
    336     }
    337   }
    338 
    339   if (bLocalized) {
    340     void* hFont = m_pFontInfo->GetFont(name.c_str());
    341     if (!hFont) {
    342       int iExact;
    343       hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0,
    344                                    name.c_str(), iExact);
    345       if (!hFont)
    346         return;
    347     }
    348 
    349     CFX_ByteString new_name = GetPSNameFromTT(hFont);
    350     if (!new_name.IsEmpty())
    351       m_LocalizedTTFonts.push_back(std::make_pair(new_name, name));
    352     m_pFontInfo->DeleteFont(hFont);
    353   }
    354   m_InstalledTTFonts.push_back(name);
    355   m_LastFamily = name;
    356 }
    357 
    358 void CFX_FontMapper::LoadInstalledFonts() {
    359   if (!m_pFontInfo || m_bListLoaded)
    360     return;
    361 
    362   m_pFontInfo->EnumFontList(this);
    363   m_bListLoaded = true;
    364 }
    365 
    366 CFX_ByteString CFX_FontMapper::MatchInstalledFonts(
    367     const CFX_ByteString& norm_name) {
    368   LoadInstalledFonts();
    369   int i;
    370   for (i = pdfium::CollectionSize<int>(m_InstalledTTFonts) - 1; i >= 0; i--) {
    371     CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str());
    372     if (norm1 == norm_name)
    373       return m_InstalledTTFonts[i];
    374   }
    375   for (i = pdfium::CollectionSize<int>(m_LocalizedTTFonts) - 1; i >= 0; i--) {
    376     CFX_ByteString norm1 =
    377         TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str());
    378     if (norm1 == norm_name)
    379       return m_LocalizedTTFonts[i].second;
    380   }
    381   return CFX_ByteString();
    382 }
    383 
    384 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont,
    385                                            int iBaseFont,
    386                                            int italic_angle,
    387                                            int weight,
    388                                            int picthfamily) {
    389   if (iBaseFont < kNumStandardFonts) {
    390     if (m_FoxitFaces[iBaseFont])
    391       return m_FoxitFaces[iBaseFont];
    392     const uint8_t* pFontData = nullptr;
    393     uint32_t size = 0;
    394     if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) {
    395       m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    396       return m_FoxitFaces[iBaseFont];
    397     }
    398   }
    399   pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
    400   pSubstFont->m_ItalicAngle = italic_angle;
    401   if (weight)
    402     pSubstFont->m_Weight = weight;
    403   if (picthfamily & FXFONT_FF_ROMAN) {
    404     pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
    405     pSubstFont->m_Family = "Chrome Serif";
    406     if (m_MMFaces[1])
    407       return m_MMFaces[1];
    408     const uint8_t* pFontData = nullptr;
    409     uint32_t size = 0;
    410     m_pFontMgr->GetBuiltinFont(14, &pFontData, &size);
    411     m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    412     return m_MMFaces[1];
    413   }
    414   pSubstFont->m_Family = "Chrome Sans";
    415   if (m_MMFaces[0])
    416     return m_MMFaces[0];
    417   const uint8_t* pFontData = nullptr;
    418   uint32_t size = 0;
    419   m_pFontMgr->GetBuiltinFont(15, &pFontData, &size);
    420   m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
    421   return m_MMFaces[0];
    422 }
    423 
    424 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name,
    425                                         bool bTrueType,
    426                                         uint32_t flags,
    427                                         int weight,
    428                                         int italic_angle,
    429                                         int WindowCP,
    430                                         CFX_SubstFont* pSubstFont) {
    431   if (!(flags & FXFONT_USEEXTERNATTR)) {
    432     weight = FXFONT_FW_NORMAL;
    433     italic_angle = 0;
    434   }
    435   CFX_ByteString SubstName = name;
    436   SubstName.Remove(' ');
    437   if (bTrueType && name[0] == '@')
    438     SubstName = name.Mid(1);
    439   PDF_GetStandardFontName(&SubstName);
    440   if (SubstName == "Symbol" && !bTrueType) {
    441     pSubstFont->m_Family = "Chrome Symbol";
    442     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
    443     return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0);
    444   }
    445   if (SubstName == "ZapfDingbats") {
    446     pSubstFont->m_Family = "Chrome Dingbats";
    447     pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
    448     return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0);
    449   }
    450   int iBaseFont = 0;
    451   CFX_ByteString family;
    452   CFX_ByteString style;
    453   bool bHasComma = false;
    454   bool bHasHyphen = false;
    455   int find = SubstName.Find(",", 0);
    456   if (find >= 0) {
    457     family = SubstName.Left(find);
    458     PDF_GetStandardFontName(&family);
    459     style = SubstName.Mid(find + 1);
    460     bHasComma = true;
    461   } else {
    462     family = SubstName;
    463   }
    464   for (; iBaseFont < 12; iBaseFont++) {
    465     if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont]))
    466       break;
    467   }
    468   int PitchFamily = 0;
    469   bool bItalic = false;
    470   uint32_t nStyle = 0;
    471   bool bStyleAvail = false;
    472   if (iBaseFont < 12) {
    473     if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2)
    474       nStyle |= FX_FONT_STYLE_Bold;
    475     if ((iBaseFont % 4) / 2)
    476       nStyle |= FX_FONT_STYLE_Italic;
    477     if (iBaseFont < 4)
    478       PitchFamily |= FXFONT_FF_FIXEDPITCH;
    479     if (iBaseFont >= 8)
    480       PitchFamily |= FXFONT_FF_ROMAN;
    481   } else {
    482     iBaseFont = kNumStandardFonts;
    483     if (!bHasComma) {
    484       find = family.ReverseFind('-');
    485       if (find >= 0) {
    486         style = family.Mid(find + 1);
    487         family = family.Left(find);
    488         bHasHyphen = true;
    489       }
    490     }
    491     if (!bHasHyphen) {
    492       int nLen = family.GetLength();
    493       int32_t nRet = GetStyleType(family, true);
    494       if (nRet > -1) {
    495         family = family.Left(nLen - g_FontStyles[nRet].len);
    496         if (nRet == 0)
    497           nStyle |= FX_FONT_STYLE_Bold;
    498         else if (nRet == 1)
    499           nStyle |= FX_FONT_STYLE_Italic;
    500         else if (nRet == 2)
    501           nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
    502       }
    503     }
    504     UpdatePitchFamily(flags, PitchFamily);
    505   }
    506   if (!style.IsEmpty()) {
    507     int nLen = style.GetLength();
    508     const FX_CHAR* pStyle = style.c_str();
    509     int i = 0;
    510     bool bFirstItem = true;
    511     CFX_ByteString buf;
    512     while (i < nLen) {
    513       buf = ParseStyle(pStyle, nLen, i);
    514       int32_t nRet = GetStyleType(buf, false);
    515       if ((i && !bStyleAvail) || (!i && nRet < 0)) {
    516         family = SubstName;
    517         iBaseFont = kNumStandardFonts;
    518         break;
    519       }
    520       if (nRet >= 0) {
    521         bStyleAvail = true;
    522       }
    523       if (nRet == 1) {
    524         if (bFirstItem) {
    525           nStyle |= FX_FONT_STYLE_Italic;
    526         } else {
    527           family = SubstName;
    528           iBaseFont = kNumStandardFonts;
    529         }
    530         break;
    531       }
    532       if (nRet == 0) {
    533         if (nStyle & FX_FONT_STYLE_Bold)
    534           nStyle |= FX_FONT_STYLE_BoldBold;
    535         else
    536           nStyle |= FX_FONT_STYLE_Bold;
    537         bFirstItem = false;
    538       } else if (nRet == 2) {
    539         nStyle |= FX_FONT_STYLE_Italic;
    540         if (nStyle & FX_FONT_STYLE_Bold)
    541           nStyle |= FX_FONT_STYLE_BoldBold;
    542         else
    543           nStyle |= FX_FONT_STYLE_Bold;
    544         bFirstItem = false;
    545       }
    546       i += buf.GetLength() + 1;
    547     }
    548   }
    549   weight = weight ? weight : FXFONT_FW_NORMAL;
    550   int old_weight = weight;
    551   if (nStyle) {
    552     weight =
    553         nStyle & FX_FONT_STYLE_BoldBold
    554             ? 900
    555             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
    556   }
    557   if (nStyle & FX_FONT_STYLE_Italic)
    558     bItalic = true;
    559   int iExact = 0;
    560   int Charset = FXFONT_ANSI_CHARSET;
    561   if (WindowCP)
    562     Charset = GetCharsetFromCodePage(WindowCP);
    563   else if (iBaseFont == kNumStandardFonts && (flags & FXFONT_SYMBOLIC))
    564     Charset = FXFONT_SYMBOL_CHARSET;
    565   bool bCJK =
    566       (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
    567        Charset == FXFONT_HANGUL_CHARSET ||
    568        Charset == FXFONT_CHINESEBIG5_CHARSET);
    569   if (!m_pFontInfo) {
    570     return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
    571                             PitchFamily);
    572   }
    573   family = GetFontFamily(family, nStyle);
    574   CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str()));
    575   if (match.IsEmpty() && family != SubstName &&
    576       (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) {
    577     match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str()));
    578   }
    579   if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) {
    580     if (!bCJK) {
    581       if (!CheckSupportThirdPartFont(family, PitchFamily)) {
    582         bItalic = italic_angle != 0;
    583         weight = old_weight;
    584       }
    585 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
    586       if (SubstName.Find("Narrow") > 0 || SubstName.Find("Condensed") > 0)
    587         family = "LiberationSansNarrow";
    588 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
    589       if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0)
    590         family = "RobotoCondensed";
    591 #else
    592       if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0)
    593         family = "ArialNarrow";
    594 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
    595     } else {
    596       pSubstFont->m_bSubstCJK = true;
    597       if (nStyle)
    598         pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL;
    599       if (nStyle & FX_FONT_STYLE_Italic)
    600         pSubstFont->m_bItalicCJK = true;
    601     }
    602   } else {
    603     italic_angle = 0;
    604     weight =
    605         nStyle & FX_FONT_STYLE_BoldBold
    606             ? 900
    607             : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
    608   }
    609   if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) {
    610     if (!match.IsEmpty())
    611       family = match;
    612     if (iBaseFont < kNumStandardFonts) {
    613       if (nStyle && !(iBaseFont % 4)) {
    614         if ((nStyle & 0x3) == 1)
    615           iBaseFont += 1;
    616         if ((nStyle & 0x3) == 2)
    617           iBaseFont += 3;
    618         if ((nStyle & 0x3) == 3)
    619           iBaseFont += 2;
    620       }
    621       family = g_Base14FontNames[iBaseFont];
    622     }
    623   } else {
    624     if (flags & FXFONT_ITALIC)
    625       bItalic = true;
    626   }
    627   iExact = !match.IsEmpty();
    628   void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily,
    629                                      family.c_str(), iExact);
    630   if (iExact)
    631     pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
    632   if (!hFont) {
    633 #ifdef PDF_ENABLE_XFA
    634     if (flags & FXFONT_EXACTMATCH)
    635       return nullptr;
    636 #endif  // PDF_ENABLE_XFA
    637     if (bCJK) {
    638       bItalic = italic_angle != 0;
    639       weight = old_weight;
    640     }
    641     if (!match.IsEmpty()) {
    642       hFont = m_pFontInfo->GetFont(match.c_str());
    643       if (!hFont) {
    644         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
    645                                 PitchFamily);
    646       }
    647     } else {
    648       if (Charset == FXFONT_SYMBOL_CHARSET) {
    649 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
    650     _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
    651         if (SubstName == "Symbol") {
    652           pSubstFont->m_Family = "Chrome Symbol";
    653           pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
    654           return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight,
    655                                   PitchFamily);
    656         }
    657 #endif
    658         return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC,
    659                              weight, italic_angle, 0, pSubstFont);
    660       }
    661       if (Charset == FXFONT_ANSI_CHARSET) {
    662         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
    663                                 PitchFamily);
    664       }
    665 
    666       auto it =
    667           std::find_if(m_FaceArray.begin(), m_FaceArray.end(),
    668                        [Charset](const FaceData& face) {
    669                          return face.charset == static_cast<uint32_t>(Charset);
    670                        });
    671       if (it == m_FaceArray.end()) {
    672         return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight,
    673                                 PitchFamily);
    674       }
    675       hFont = m_pFontInfo->GetFont(it->name.c_str());
    676     }
    677   }
    678   if (!hFont)
    679     return nullptr;
    680 
    681   m_pFontInfo->GetFaceName(hFont, SubstName);
    682   if (Charset == FXFONT_DEFAULT_CHARSET)
    683     m_pFontInfo->GetFontCharset(hFont, Charset);
    684   uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0);
    685   uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0);
    686   if (font_size == 0 && ttc_size == 0) {
    687     m_pFontInfo->DeleteFont(hFont);
    688     return nullptr;
    689   }
    690   FXFT_Face face = nullptr;
    691   if (ttc_size)
    692     face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size);
    693   else
    694     face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size);
    695   if (!face) {
    696     m_pFontInfo->DeleteFont(hFont);
    697     return nullptr;
    698   }
    699   pSubstFont->m_Family = SubstName;
    700   pSubstFont->m_Charset = Charset;
    701   bool bNeedUpdateWeight = false;
    702   if (FXFT_Is_Face_Bold(face))
    703     bNeedUpdateWeight = weight != FXFONT_FW_BOLD;
    704   else
    705     bNeedUpdateWeight = weight != FXFONT_FW_NORMAL;
    706   if (bNeedUpdateWeight)
    707     pSubstFont->m_Weight = weight;
    708   if (bItalic && !FXFT_Is_Face_Italic(face)) {
    709     if (italic_angle == 0)
    710       italic_angle = -12;
    711     else if (FXSYS_abs(italic_angle) < 5)
    712       italic_angle = 0;
    713     pSubstFont->m_ItalicAngle = italic_angle;
    714   }
    715   m_pFontInfo->DeleteFont(hFont);
    716   return face;
    717 }
    718 
    719 #ifdef PDF_ENABLE_XFA
    720 FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode,
    721                                                  uint32_t flags,
    722                                                  int weight,
    723                                                  int italic_angle) {
    724   if (!m_pFontInfo)
    725     return nullptr;
    726 
    727   bool bItalic = (flags & FXFONT_ITALIC) != 0;
    728   int PitchFamily = 0;
    729   UpdatePitchFamily(flags, PitchFamily);
    730   void* hFont =
    731       m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily);
    732   if (!hFont)
    733     return nullptr;
    734 
    735   uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0);
    736   uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0);
    737   if (font_size == 0 && ttc_size == 0) {
    738     m_pFontInfo->DeleteFont(hFont);
    739     return nullptr;
    740   }
    741   FXFT_Face face = nullptr;
    742   if (ttc_size) {
    743     face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size);
    744   } else {
    745     CFX_ByteString SubstName;
    746     m_pFontInfo->GetFaceName(hFont, SubstName);
    747     face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size);
    748   }
    749   m_pFontInfo->DeleteFont(hFont);
    750   return face;
    751 }
    752 #endif  // PDF_ENABLE_XFA
    753 
    754 int CFX_FontMapper::GetFaceSize() const {
    755   return pdfium::CollectionSize<int>(m_FaceArray);
    756 }
    757 
    758 bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const {
    759   for (size_t i = 0; i < MM_FACE_COUNT; ++i) {
    760     if (m_MMFaces[i] == face)
    761       return true;
    762   }
    763   for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) {
    764     if (m_FoxitFaces[i] == face)
    765       return true;
    766   }
    767   return false;
    768 }
    769 
    770 FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont,
    771                                            const uint32_t tableTTCF,
    772                                            uint32_t ttc_size,
    773                                            uint32_t font_size) {
    774   FXFT_Face face;
    775   uint8_t buffer[1024];
    776   m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer));
    777   uint32_t* pBuffer = reinterpret_cast<uint32_t*>(buffer);
    778   uint32_t checksum = 0;
    779   for (int i = 0; i < 256; i++)
    780     checksum += pBuffer[i];
    781   uint8_t* pFontData;
    782   face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size,
    783                                       pFontData);
    784   if (!face) {
    785     pFontData = FX_Alloc(uint8_t, ttc_size);
    786     m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size);
    787     face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size,
    788                                         ttc_size - font_size);
    789   }
    790   return face;
    791 }
    792 
    793 FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont,
    794                                         CFX_ByteString SubstName,
    795                                         int weight,
    796                                         bool bItalic,
    797                                         uint32_t font_size) {
    798   FXFT_Face face;
    799   uint8_t* pFontData;
    800   face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
    801   if (!face) {
    802     pFontData = FX_Alloc(uint8_t, font_size);
    803     m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
    804     face =
    805         m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData,
    806                                   font_size, m_pFontInfo->GetFaceIndex(hFont));
    807   }
    808   return face;
    809 }
    810 
    811 int PDF_GetStandardFontName(CFX_ByteString* name) {
    812   AltFontName* found = static_cast<AltFontName*>(
    813       FXSYS_bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames),
    814                     sizeof(AltFontName), CompareString));
    815   if (!found)
    816     return -1;
    817 
    818   *name = g_Base14FontNames[found->m_Index];
    819   return found->m_Index;
    820 }
    821