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
24namespace {
25
26const int kNumStandardFonts = 14;
27
28const 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
45const 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
140const 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
149const 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
156const 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
169int 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
178int 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
183CFX_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
195uint8_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
208CFX_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
226CFX_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
239int32_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
261bool CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) {
262  if (name == "MyriadPro") {
263    PitchFamily &= ~FXFONT_FF_ROMAN;
264    return true;
265  }
266  return false;
267}
268
269void 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
280CFX_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
287CFX_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
298void CFX_FontMapper::SetSystemFontInfo(
299    std::unique_ptr<IFX_SystemFontInfo> pFontInfo) {
300  if (!pFontInfo)
301    return;
302
303  m_pFontInfo = std::move(pFontInfo);
304}
305
306CFX_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
322void 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
358void CFX_FontMapper::LoadInstalledFonts() {
359  if (!m_pFontInfo || m_bListLoaded)
360    return;
361
362  m_pFontInfo->EnumFontList(this);
363  m_bListLoaded = true;
364}
365
366CFX_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
384FXFT_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
424FXFT_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
720FXFT_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
754int CFX_FontMapper::GetFaceSize() const {
755  return pdfium::CollectionSize<int>(m_FaceArray);
756}
757
758bool 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
770FXFT_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
793FXFT_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
811int 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