• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TT_NormalizeName(const char * family)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 
GetCharsetFromCodePage(uint16_t codepage)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 
GetFontFamily(uint32_t nStyle,ByteString * fontName)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 
ParseStyle(const char * pStyle,int iLen,int iIndex)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>
GetStyleType(const ByteString & bsStyle,bool bReverse)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 
CheckSupportThirdPartFont(const ByteString & name,int * PitchFamily)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 
UpdatePitchFamily(uint32_t flags,int * PitchFamily)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 
CFX_FontMapper(CFX_FontMgr * mgr)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 
~CFX_FontMapper()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 
SetSystemFontInfo(std::unique_ptr<IFX_SystemFontInfo> pFontInfo)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 
GetPSNameFromTT(void * hFont)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 
AddInstalledFont(const ByteString & name,int charset)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 
LoadInstalledFonts()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 
MatchInstalledFonts(const ByteString & norm_name)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 
UseInternalSubst(CFX_SubstFont * pSubstFont,int iBaseFont,int italic_angle,int weight,int pitch_family)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 
FindSubstFont(const ByteString & name,bool bTrueType,uint32_t flags,int weight,int italic_angle,int WindowCP,CFX_SubstFont * pSubstFont)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
FindSubstFontByUnicode(uint32_t dwUnicode,uint32_t flags,int weight,int italic_angle)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 
GetFaceSize() const734 int CFX_FontMapper::GetFaceSize() const {
735   return pdfium::CollectionSize<int>(m_FaceArray);
736 }
737 
IsBuiltinFace(const FXFT_Face face) const738 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 
GetCachedTTCFace(void * hFont,const uint32_t tableTTCF,uint32_t ttc_size,uint32_t font_size)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 
GetCachedFace(void * hFont,ByteString SubstName,int weight,bool bItalic,uint32_t font_size)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 
PDF_GetStandardFontName(ByteString * name)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