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