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