• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The PDFium Authors
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 <stdint.h>
10 
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14 
15 #include "build/build_config.h"
16 #include "core/fxcrt/data_vector.h"
17 #include "core/fxcrt/fx_codepage.h"
18 #include "core/fxcrt/fx_extension.h"
19 #include "core/fxcrt/fx_memory.h"
20 #include "core/fxcrt/fx_memory_wrappers.h"
21 #include "core/fxcrt/stl_util.h"
22 #include "core/fxge/cfx_fontmgr.h"
23 #include "core/fxge/cfx_substfont.h"
24 #include "core/fxge/fx_font.h"
25 #include "core/fxge/systemfontinfo_iface.h"
26 #include "third_party/base/check_op.h"
27 #include "third_party/base/containers/contains.h"
28 #include "third_party/base/cxx17_backports.h"
29 
30 namespace {
31 
32 static_assert(CFX_FontMapper::kLast + 1 == CFX_FontMapper::kNumStandardFonts,
33               "StandardFont enum count mismatch");
34 
35 const char* const kBase14FontNames[CFX_FontMapper::kNumStandardFonts] = {
36     "Courier",
37     "Courier-Bold",
38     "Courier-BoldOblique",
39     "Courier-Oblique",
40     "Helvetica",
41     "Helvetica-Bold",
42     "Helvetica-BoldOblique",
43     "Helvetica-Oblique",
44     "Times-Roman",
45     "Times-Bold",
46     "Times-BoldItalic",
47     "Times-Italic",
48     "Symbol",
49     "ZapfDingbats",
50 };
51 
52 struct AltFontName {
53   const char* m_pName;  // Raw, POD struct.
54   CFX_FontMapper::StandardFont m_Index;
55 };
56 
57 constexpr AltFontName kAltFontNames[] = {
58     {"Arial", CFX_FontMapper::kHelvetica},
59     {"Arial,Bold", CFX_FontMapper::kHelveticaBold},
60     {"Arial,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
61     {"Arial,Italic", CFX_FontMapper::kHelveticaOblique},
62     {"Arial-Bold", CFX_FontMapper::kHelveticaBold},
63     {"Arial-BoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
64     {"Arial-BoldItalicMT", CFX_FontMapper::kHelveticaBoldOblique},
65     {"Arial-BoldMT", CFX_FontMapper::kHelveticaBold},
66     {"Arial-Italic", CFX_FontMapper::kHelveticaOblique},
67     {"Arial-ItalicMT", CFX_FontMapper::kHelveticaOblique},
68     {"ArialBold", CFX_FontMapper::kHelveticaBold},
69     {"ArialBoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
70     {"ArialItalic", CFX_FontMapper::kHelveticaOblique},
71     {"ArialMT", CFX_FontMapper::kHelvetica},
72     {"ArialMT,Bold", CFX_FontMapper::kHelveticaBold},
73     {"ArialMT,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
74     {"ArialMT,Italic", CFX_FontMapper::kHelveticaOblique},
75     {"ArialRoundedMTBold", CFX_FontMapper::kHelveticaBold},
76     {"Courier", CFX_FontMapper::kCourier},
77     {"Courier,Bold", CFX_FontMapper::kCourierBold},
78     {"Courier,BoldItalic", CFX_FontMapper::kCourierBoldOblique},
79     {"Courier,Italic", CFX_FontMapper::kCourierOblique},
80     {"Courier-Bold", CFX_FontMapper::kCourierBold},
81     {"Courier-BoldOblique", CFX_FontMapper::kCourierBoldOblique},
82     {"Courier-Oblique", CFX_FontMapper::kCourierOblique},
83     {"CourierBold", CFX_FontMapper::kCourierBold},
84     {"CourierBoldItalic", CFX_FontMapper::kCourierBoldOblique},
85     {"CourierItalic", CFX_FontMapper::kCourierOblique},
86     {"CourierNew", CFX_FontMapper::kCourier},
87     {"CourierNew,Bold", CFX_FontMapper::kCourierBold},
88     {"CourierNew,BoldItalic", CFX_FontMapper::kCourierBoldOblique},
89     {"CourierNew,Italic", CFX_FontMapper::kCourierOblique},
90     {"CourierNew-Bold", CFX_FontMapper::kCourierBold},
91     {"CourierNew-BoldItalic", CFX_FontMapper::kCourierBoldOblique},
92     {"CourierNew-Italic", CFX_FontMapper::kCourierOblique},
93     {"CourierNewBold", CFX_FontMapper::kCourierBold},
94     {"CourierNewBoldItalic", CFX_FontMapper::kCourierBoldOblique},
95     {"CourierNewItalic", CFX_FontMapper::kCourierOblique},
96     {"CourierNewPS-BoldItalicMT", CFX_FontMapper::kCourierBoldOblique},
97     {"CourierNewPS-BoldMT", CFX_FontMapper::kCourierBold},
98     {"CourierNewPS-ItalicMT", CFX_FontMapper::kCourierOblique},
99     {"CourierNewPSMT", CFX_FontMapper::kCourier},
100     {"CourierStd", CFX_FontMapper::kCourier},
101     {"CourierStd-Bold", CFX_FontMapper::kCourierBold},
102     {"CourierStd-BoldOblique", CFX_FontMapper::kCourierBoldOblique},
103     {"CourierStd-Oblique", CFX_FontMapper::kCourierOblique},
104     {"Helvetica", CFX_FontMapper::kHelvetica},
105     {"Helvetica,Bold", CFX_FontMapper::kHelveticaBold},
106     {"Helvetica,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
107     {"Helvetica,Italic", CFX_FontMapper::kHelveticaOblique},
108     {"Helvetica-Bold", CFX_FontMapper::kHelveticaBold},
109     {"Helvetica-BoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
110     {"Helvetica-BoldOblique", CFX_FontMapper::kHelveticaBoldOblique},
111     {"Helvetica-Italic", CFX_FontMapper::kHelveticaOblique},
112     {"Helvetica-Oblique", CFX_FontMapper::kHelveticaOblique},
113     {"HelveticaBold", CFX_FontMapper::kHelveticaBold},
114     {"HelveticaBoldItalic", CFX_FontMapper::kHelveticaBoldOblique},
115     {"HelveticaItalic", CFX_FontMapper::kHelveticaOblique},
116     {"Symbol", CFX_FontMapper::kSymbol},
117     {"SymbolMT", CFX_FontMapper::kSymbol},
118     {"Times-Bold", CFX_FontMapper::kTimesBold},
119     {"Times-BoldItalic", CFX_FontMapper::kTimesBoldOblique},
120     {"Times-Italic", CFX_FontMapper::kTimesOblique},
121     {"Times-Roman", CFX_FontMapper::kTimes},
122     {"TimesBold", CFX_FontMapper::kTimesBold},
123     {"TimesBoldItalic", CFX_FontMapper::kTimesBoldOblique},
124     {"TimesItalic", CFX_FontMapper::kTimesOblique},
125     {"TimesNewRoman", CFX_FontMapper::kTimes},
126     {"TimesNewRoman,Bold", CFX_FontMapper::kTimesBold},
127     {"TimesNewRoman,BoldItalic", CFX_FontMapper::kTimesBoldOblique},
128     {"TimesNewRoman,Italic", CFX_FontMapper::kTimesOblique},
129     {"TimesNewRoman-Bold", CFX_FontMapper::kTimesBold},
130     {"TimesNewRoman-BoldItalic", CFX_FontMapper::kTimesBoldOblique},
131     {"TimesNewRoman-Italic", CFX_FontMapper::kTimesOblique},
132     {"TimesNewRomanBold", CFX_FontMapper::kTimesBold},
133     {"TimesNewRomanBoldItalic", CFX_FontMapper::kTimesBoldOblique},
134     {"TimesNewRomanItalic", CFX_FontMapper::kTimesOblique},
135     {"TimesNewRomanPS", CFX_FontMapper::kTimes},
136     {"TimesNewRomanPS-Bold", CFX_FontMapper::kTimesBold},
137     {"TimesNewRomanPS-BoldItalic", CFX_FontMapper::kTimesBoldOblique},
138     {"TimesNewRomanPS-BoldItalicMT", CFX_FontMapper::kTimesBoldOblique},
139     {"TimesNewRomanPS-BoldMT", CFX_FontMapper::kTimesBold},
140     {"TimesNewRomanPS-Italic", CFX_FontMapper::kTimesOblique},
141     {"TimesNewRomanPS-ItalicMT", CFX_FontMapper::kTimesOblique},
142     {"TimesNewRomanPSMT", CFX_FontMapper::kTimes},
143     {"TimesNewRomanPSMT,Bold", CFX_FontMapper::kTimesBold},
144     {"TimesNewRomanPSMT,BoldItalic", CFX_FontMapper::kTimesBoldOblique},
145     {"TimesNewRomanPSMT,Italic", CFX_FontMapper::kTimesOblique},
146     {"ZapfDingbats", CFX_FontMapper::kDingbats},
147 };
148 
149 struct AltFontFamily {
150   const char* m_pFontName;    // Raw, POD struct.
151   const char* m_pFontFamily;  // Raw, POD struct.
152 };
153 
154 constexpr AltFontFamily kAltFontFamilies[] = {
155     {"AGaramondPro", "Adobe Garamond Pro"},
156     {"BankGothicBT-Medium", "BankGothic Md BT"},
157     {"ForteMT", "Forte"},
158 };
159 
160 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || defined(OS_ASMJS)
161 const char kNarrowFamily[] = "LiberationSansNarrow";
162 #elif BUILDFLAG(IS_ANDROID)
163 const char kNarrowFamily[] = "RobotoCondensed";
164 #else
165 const char kNarrowFamily[] = "ArialNarrow";
166 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || defined(OS_ASMJS)
167 
TT_NormalizeName(ByteString norm)168 ByteString TT_NormalizeName(ByteString norm) {
169   norm.Remove(' ');
170   norm.Remove('-');
171   norm.Remove(',');
172   auto pos = norm.Find('+');
173   if (pos.has_value() && pos.value() != 0)
174     norm = norm.First(pos.value());
175   norm.MakeLower();
176   return norm;
177 }
178 
GetFontFamily(uint32_t nStyle,ByteString * fontName)179 void GetFontFamily(uint32_t nStyle, ByteString* fontName) {
180   if (fontName->Contains("Script")) {
181     if (FontStyleIsForceBold(nStyle))
182       *fontName = "ScriptMTBold";
183     else if (fontName->Contains("Palace"))
184       *fontName = "PalaceScriptMT";
185     else if (fontName->Contains("French"))
186       *fontName = "FrenchScriptMT";
187     else if (fontName->Contains("FreeStyle"))
188       *fontName = "FreeStyleScript";
189     return;
190   }
191   for (const auto& alternate : kAltFontFamilies) {
192     if (fontName->Contains(alternate.m_pFontName)) {
193       *fontName = alternate.m_pFontFamily;
194       return;
195     }
196   }
197 }
198 
ParseStyle(const ByteString & bsStyle,size_t iStart)199 ByteString ParseStyle(const ByteString& bsStyle, size_t iStart) {
200   ByteStringView bsRegion = bsStyle.AsStringView().Substr(iStart);
201   size_t iIndex = bsRegion.Find(',').value_or(bsRegion.GetLength());
202   return ByteString(bsRegion.First(iIndex));
203 }
204 
205 struct FX_FontStyle {
206   const char* name;
207   size_t len;
208   uint32_t style;
209 };
210 
211 constexpr FX_FontStyle kFontStyles[] = {
212     {"Regular", 7, FXFONT_NORMAL},
213     {"Reg", 3, FXFONT_NORMAL},
214     {"BoldItalic", 10, FXFONT_FORCE_BOLD | FXFONT_ITALIC},
215     {"Italic", 6, FXFONT_ITALIC},
216     {"Bold", 4, FXFONT_FORCE_BOLD},
217 };
218 
GetStyleType(ByteStringView font_name,bool reverse_search)219 const FX_FontStyle* GetStyleType(ByteStringView font_name,
220                                  bool reverse_search) {
221   if (font_name.IsEmpty())
222     return nullptr;
223 
224   for (const FX_FontStyle& style : kFontStyles) {
225     if (style.len > font_name.GetLength())
226       continue;
227 
228     ByteStringView style_view =
229         reverse_search ? font_name.Last(style.len) : font_name.First(style.len);
230     if (style_view == style.name)
231       return &style;
232   }
233   return nullptr;
234 }
235 
ParseStyles(const ByteString & style_str,bool * is_style_available,int * weight,uint32_t * style)236 bool ParseStyles(const ByteString& style_str,
237                  bool* is_style_available,
238                  int* weight,
239                  uint32_t* style) {
240   if (style_str.IsEmpty())
241     return false;
242 
243   size_t i = 0;
244   bool is_first_item = true;
245   while (i < style_str.GetLength()) {
246     ByteString buf = ParseStyle(style_str, i);
247     const FX_FontStyle* style_result =
248         GetStyleType(buf.AsStringView(), /*reverse_search=*/false);
249     if ((i && !*is_style_available) || (!i && !style_result))
250       return true;
251 
252     uint32_t parsed_style;
253     if (style_result) {
254       *is_style_available = true;
255       parsed_style = style_result->style;
256     } else {
257       parsed_style = FXFONT_NORMAL;
258     }
259 
260     if (FontStyleIsForceBold(parsed_style)) {
261       // If we're already bold, then we're double bold, use special weight.
262       if (FontStyleIsForceBold(*style)) {
263         *weight = FXFONT_FW_BOLD_BOLD;
264       } else {
265         *weight = FXFONT_FW_BOLD;
266         *style |= FXFONT_FORCE_BOLD;
267       }
268 
269       is_first_item = false;
270     }
271     if (FontStyleIsItalic(parsed_style) && FontStyleIsForceBold(parsed_style)) {
272       *style |= FXFONT_ITALIC;
273     } else if (FontStyleIsItalic(parsed_style)) {
274       if (!is_first_item)
275         return true;
276 
277       *style |= FXFONT_ITALIC;
278       break;
279     }
280     i += buf.GetLength() + 1;
281   }
282   return false;
283 }
284 
CheckSupportThirdPartFont(const ByteString & name,int * pitch_family)285 bool CheckSupportThirdPartFont(const ByteString& name, int* pitch_family) {
286   if (name != "MyriadPro")
287     return false;
288   *pitch_family &= ~FXFONT_FF_ROMAN;
289   return true;
290 }
291 
GetStyleFromBaseFont(int base_font)292 uint32_t GetStyleFromBaseFont(int base_font) {
293   int pos = base_font % 4;
294   uint32_t style = FXFONT_NORMAL;
295   if (pos == 1 || pos == 2)
296     style |= FXFONT_FORCE_BOLD;
297   if (pos / 2)
298     style |= FXFONT_ITALIC;
299   return style;
300 }
301 
GetPitchFamilyFromBaseFont(int base_font)302 int GetPitchFamilyFromBaseFont(int base_font) {
303   if (base_font < 4)
304     return FXFONT_FF_FIXEDPITCH;
305   if (base_font >= 8)
306     return FXFONT_FF_ROMAN;
307   return 0;
308 }
309 
GetPitchFamilyFromFlags(uint32_t flags)310 int GetPitchFamilyFromFlags(uint32_t flags) {
311   int pitch_family = 0;
312   if (FontStyleIsSerif(flags))
313     pitch_family |= FXFONT_FF_ROMAN;
314   if (FontStyleIsScript(flags))
315     pitch_family |= FXFONT_FF_SCRIPT;
316   if (FontStyleIsFixedPitch(flags))
317     pitch_family |= FXFONT_FF_FIXEDPITCH;
318   return pitch_family;
319 }
320 
AdjustBaseFontForStyle(int base_font,uint32_t style)321 int AdjustBaseFontForStyle(int base_font, uint32_t style) {
322   if (!style || (base_font % 4))
323     return base_font;
324 
325   if (FontStyleIsForceBold(style) && FontStyleIsItalic(style))
326     base_font += 2;
327   else if (FontStyleIsForceBold(style))
328     base_font += 1;
329   else if (FontStyleIsItalic(style))
330     base_font += 3;
331   return base_font;
332 }
333 
GetCharset(FX_CodePage code_page,int base_font,uint32_t flags)334 FX_Charset GetCharset(FX_CodePage code_page, int base_font, uint32_t flags) {
335   if (code_page != FX_CodePage::kDefANSI)
336     return FX_GetCharsetFromCodePage(code_page);
337   if (FontStyleIsSymbolic(flags) &&
338       base_font == CFX_FontMapper::kNumStandardFonts) {
339     return FX_Charset::kSymbol;
340   }
341   return FX_Charset::kANSI;
342 }
343 
IsStrUpper(const ByteString & str)344 bool IsStrUpper(const ByteString& str) {
345   for (size_t i = 0; i < str.GetLength(); ++i) {
346     if (!FXSYS_IsUpperASCII(str[i]))
347       return false;
348   }
349   return true;
350 }
351 
RemoveSubsettedFontPrefix(ByteString * subst_name)352 void RemoveSubsettedFontPrefix(ByteString* subst_name) {
353   constexpr size_t kPrefixLength = 6;
354   if (subst_name->GetLength() > kPrefixLength &&
355       (*subst_name)[kPrefixLength] == '+' &&
356       IsStrUpper(subst_name->First(kPrefixLength))) {
357     *subst_name =
358         subst_name->Last(subst_name->GetLength() - (kPrefixLength + 1));
359   }
360 }
361 
GetSubstName(const ByteString & name,bool is_truetype)362 ByteString GetSubstName(const ByteString& name, bool is_truetype) {
363   ByteString subst_name = name;
364   if (is_truetype && name.Front() == '@')
365     subst_name.Delete(0);
366   else
367     subst_name.Remove(' ');
368   RemoveSubsettedFontPrefix(&subst_name);
369   CFX_FontMapper::GetStandardFontName(&subst_name);
370   return subst_name;
371 }
372 
IsNarrowFontName(const ByteString & name)373 bool IsNarrowFontName(const ByteString& name) {
374   static const char kNarrowFonts[][10] = {"Narrow", "Condensed"};
375   for (const char* font : kNarrowFonts) {
376     absl::optional<size_t> pos = name.Find(font);
377     if (pos.has_value() && pos.value() != 0)
378       return true;
379   }
380   return false;
381 }
382 
383 class ScopedFontDeleter {
384  public:
385   FX_STACK_ALLOCATED();
386 
ScopedFontDeleter(SystemFontInfoIface * font_info,void * font)387   ScopedFontDeleter(SystemFontInfoIface* font_info, void* font)
388       : font_info_(font_info), font_(font) {}
~ScopedFontDeleter()389   ~ScopedFontDeleter() { font_info_->DeleteFont(font_); }
390 
391  private:
392   UnownedPtr<SystemFontInfoIface> const font_info_;
393   void* const font_;
394 };
395 
396 }  // namespace
397 
CFX_FontMapper(CFX_FontMgr * mgr)398 CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) : m_pFontMgr(mgr) {}
399 
400 CFX_FontMapper::~CFX_FontMapper() = default;
401 
SetSystemFontInfo(std::unique_ptr<SystemFontInfoIface> pFontInfo)402 void CFX_FontMapper::SetSystemFontInfo(
403     std::unique_ptr<SystemFontInfoIface> pFontInfo) {
404   if (!pFontInfo)
405     return;
406 
407   m_bListLoaded = false;
408   m_pFontInfo = std::move(pFontInfo);
409 }
410 
TakeSystemFontInfo()411 std::unique_ptr<SystemFontInfoIface> CFX_FontMapper::TakeSystemFontInfo() {
412   return std::move(m_pFontInfo);
413 }
414 
GetChecksumFromTT(void * font_handle)415 uint32_t CFX_FontMapper::GetChecksumFromTT(void* font_handle) {
416   uint32_t buffer[256];
417   m_pFontInfo->GetFontData(
418       font_handle, kTableTTCF,
419       pdfium::as_writable_bytes(pdfium::make_span(buffer)));
420 
421   uint32_t checksum = 0;
422   for (auto x : buffer)
423     checksum += x;
424 
425   return checksum;
426 }
427 
GetPSNameFromTT(void * font_handle)428 ByteString CFX_FontMapper::GetPSNameFromTT(void* font_handle) {
429   size_t size = m_pFontInfo->GetFontData(font_handle, kTableNAME, {});
430   if (!size)
431     return ByteString();
432 
433   DataVector<uint8_t> buffer(size);
434   size_t bytes_read = m_pFontInfo->GetFontData(font_handle, kTableNAME, buffer);
435   return bytes_read == size ? GetNameFromTT(buffer, 6) : ByteString();
436 }
437 
AddInstalledFont(const ByteString & name,FX_Charset charset)438 void CFX_FontMapper::AddInstalledFont(const ByteString& name,
439                                       FX_Charset charset) {
440   if (!m_pFontInfo)
441     return;
442 
443   m_FaceArray.push_back({name, static_cast<uint32_t>(charset)});
444   if (name == m_LastFamily)
445     return;
446 
447   bool is_localized = std::any_of(name.begin(), name.end(), [](const char& c) {
448     return static_cast<uint8_t>(c) > 0x80;
449   });
450 
451   if (is_localized) {
452     void* font_handle = m_pFontInfo->GetFont(name);
453     if (!font_handle) {
454       font_handle =
455           m_pFontInfo->MapFont(0, false, FX_Charset::kDefault, 0, name);
456       if (!font_handle)
457         return;
458     }
459 
460     ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
461     ByteString new_name = GetPSNameFromTT(font_handle);
462     if (!new_name.IsEmpty())
463       m_LocalizedTTFonts.push_back(std::make_pair(new_name, name));
464   }
465   m_InstalledTTFonts.push_back(name);
466   m_LastFamily = name;
467 }
468 
LoadInstalledFonts()469 void CFX_FontMapper::LoadInstalledFonts() {
470   if (!m_pFontInfo || m_bListLoaded)
471     return;
472 
473   m_pFontInfo->EnumFontList(this);
474   m_bListLoaded = true;
475 }
476 
MatchInstalledFonts(const ByteString & norm_name)477 ByteString CFX_FontMapper::MatchInstalledFonts(const ByteString& norm_name) {
478   LoadInstalledFonts();
479   int i;
480   for (i = fxcrt::CollectionSize<int>(m_InstalledTTFonts) - 1; i >= 0; i--) {
481     if (TT_NormalizeName(m_InstalledTTFonts[i]) == norm_name)
482       return m_InstalledTTFonts[i];
483   }
484   for (i = fxcrt::CollectionSize<int>(m_LocalizedTTFonts) - 1; i >= 0; i--) {
485     if (TT_NormalizeName(m_LocalizedTTFonts[i].first) == norm_name)
486       return m_LocalizedTTFonts[i].second;
487   }
488   return ByteString();
489 }
490 
UseInternalSubst(int base_font,int weight,int italic_angle,int pitch_family,CFX_SubstFont * subst_font)491 RetainPtr<CFX_Face> CFX_FontMapper::UseInternalSubst(
492     int base_font,
493     int weight,
494     int italic_angle,
495     int pitch_family,
496     CFX_SubstFont* subst_font) {
497   if (base_font < kNumStandardFonts) {
498     if (!m_StandardFaces[base_font]) {
499       m_StandardFaces[base_font] = m_pFontMgr->NewFixedFace(
500           nullptr, m_pFontMgr->GetStandardFont(base_font), 0);
501     }
502     return m_StandardFaces[base_font];
503   }
504 
505   subst_font->SetIsBuiltInGenericFont();
506   subst_font->m_ItalicAngle = italic_angle;
507   if (weight)
508     subst_font->m_Weight = weight;
509   if (FontFamilyIsRoman(pitch_family)) {
510     subst_font->UseChromeSerif();
511     if (!m_GenericSerifFace) {
512       m_GenericSerifFace = m_pFontMgr->NewFixedFace(
513           nullptr, m_pFontMgr->GetGenericSerifFont(), 0);
514     }
515     return m_GenericSerifFace;
516   }
517   subst_font->m_Family = "Chrome Sans";
518   if (!m_GenericSansFace) {
519     m_GenericSansFace =
520         m_pFontMgr->NewFixedFace(nullptr, m_pFontMgr->GetGenericSansFont(), 0);
521   }
522   return m_GenericSansFace;
523 }
524 
UseExternalSubst(void * font_handle,ByteString face_name,int weight,bool is_italic,int italic_angle,FX_Charset charset,CFX_SubstFont * subst_font)525 RetainPtr<CFX_Face> CFX_FontMapper::UseExternalSubst(
526     void* font_handle,
527     ByteString face_name,
528     int weight,
529     bool is_italic,
530     int italic_angle,
531     FX_Charset charset,
532     CFX_SubstFont* subst_font) {
533   DCHECK(font_handle);
534 
535   ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
536   m_pFontInfo->GetFaceName(font_handle, &face_name);
537   if (charset == FX_Charset::kDefault)
538     m_pFontInfo->GetFontCharset(font_handle, &charset);
539   size_t ttc_size = m_pFontInfo->GetFontData(font_handle, kTableTTCF, {});
540   size_t font_size = m_pFontInfo->GetFontData(font_handle, 0, {});
541   if (font_size == 0 && ttc_size == 0)
542     return nullptr;
543 
544   RetainPtr<CFX_Face> face =
545       ttc_size
546           ? GetCachedTTCFace(font_handle, ttc_size, font_size)
547           : GetCachedFace(font_handle, face_name, weight, is_italic, font_size);
548   if (!face)
549     return nullptr;
550 
551   subst_font->m_Family = face_name;
552   subst_font->m_Charset = charset;
553   int face_weight =
554       FXFT_Is_Face_Bold(face->GetRec()) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
555   if (weight != face_weight)
556     subst_font->m_Weight = weight;
557   if (is_italic && !FXFT_Is_Face_Italic(face->GetRec())) {
558     if (italic_angle == 0)
559       italic_angle = -12;
560     else if (abs(italic_angle) < 5)
561       italic_angle = 0;
562     subst_font->m_ItalicAngle = italic_angle;
563   }
564   return face;
565 }
566 
FindSubstFont(const ByteString & name,bool is_truetype,uint32_t flags,int weight,int italic_angle,FX_CodePage code_page,CFX_SubstFont * subst_font)567 RetainPtr<CFX_Face> CFX_FontMapper::FindSubstFont(const ByteString& name,
568                                                   bool is_truetype,
569                                                   uint32_t flags,
570                                                   int weight,
571                                                   int italic_angle,
572                                                   FX_CodePage code_page,
573                                                   CFX_SubstFont* subst_font) {
574   if (weight == 0)
575     weight = FXFONT_FW_NORMAL;
576 
577   if (!(flags & FXFONT_USEEXTERNATTR)) {
578     weight = FXFONT_FW_NORMAL;
579     italic_angle = 0;
580   }
581   const ByteString subst_name = GetSubstName(name, is_truetype);
582   if (subst_name == "Symbol" && !is_truetype) {
583     subst_font->m_Family = "Chrome Symbol";
584     subst_font->m_Charset = FX_Charset::kSymbol;
585     return UseInternalSubst(kSymbol, weight, italic_angle, 0, subst_font);
586   }
587   if (subst_name == "ZapfDingbats") {
588     subst_font->m_Family = "Chrome Dingbats";
589     subst_font->m_Charset = FX_Charset::kSymbol;
590     return UseInternalSubst(kDingbats, weight, italic_angle, 0, subst_font);
591   }
592   int base_font = 0;
593   ByteString family;
594   ByteString style;
595   bool has_comma = false;
596   bool has_hyphen = false;
597   {
598     absl::optional<size_t> pos = subst_name.Find(",");
599     if (pos.has_value()) {
600       family = subst_name.First(pos.value());
601       GetStandardFontName(&family);
602       style = subst_name.Last(subst_name.GetLength() - (pos.value() + 1));
603       has_comma = true;
604     } else {
605       family = subst_name;
606     }
607   }
608   for (; base_font < kSymbol; base_font++) {
609     if (family == kBase14FontNames[base_font])
610       break;
611   }
612   int pitch_family;
613   uint32_t nStyle;
614   bool is_style_available = false;
615   if (base_font < kSymbol) {
616     nStyle = GetStyleFromBaseFont(base_font);
617     pitch_family = GetPitchFamilyFromBaseFont(base_font);
618   } else {
619     base_font = kNumStandardFonts;
620     nStyle = FXFONT_NORMAL;
621     if (!has_comma) {
622       absl::optional<size_t> pos = family.ReverseFind('-');
623       if (pos.has_value()) {
624         style = family.Last(family.GetLength() - (pos.value() + 1));
625         family = family.First(pos.value());
626         has_hyphen = true;
627       }
628     }
629     if (!has_hyphen) {
630       size_t nLen = family.GetLength();
631       const FX_FontStyle* style_result =
632           GetStyleType(family.AsStringView(), /*reverse_search=*/true);
633       if (style_result) {
634         family = family.First(nLen - style_result->len);
635         nStyle |= style_result->style;
636       }
637     }
638     pitch_family = GetPitchFamilyFromFlags(flags);
639   }
640 
641   const int old_weight = weight;
642   if (FontStyleIsForceBold(nStyle))
643     weight = FXFONT_FW_BOLD;
644 
645   if (ParseStyles(style, &is_style_available, &weight, &nStyle)) {
646     family = subst_name;
647     base_font = kNumStandardFonts;
648   }
649 
650   if (!m_pFontInfo) {
651     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
652                             subst_font);
653   }
654 
655   const FX_Charset Charset = GetCharset(code_page, base_font, flags);
656   const bool is_cjk = FX_CharSetIsCJK(Charset);
657   bool is_italic = FontStyleIsItalic(nStyle);
658 
659   GetFontFamily(nStyle, &family);
660   ByteString match = MatchInstalledFonts(TT_NormalizeName(family));
661   if (match.IsEmpty() && family != subst_name &&
662       (!has_comma && (!has_hyphen || (has_hyphen && !is_style_available)))) {
663     match = MatchInstalledFonts(TT_NormalizeName(subst_name));
664   }
665   if (match.IsEmpty() && base_font >= kNumStandardFonts) {
666     if (!is_cjk) {
667       if (!CheckSupportThirdPartFont(family, &pitch_family)) {
668         is_italic = italic_angle != 0;
669         weight = old_weight;
670       }
671       if (IsNarrowFontName(subst_name))
672         family = kNarrowFamily;
673     } else {
674       subst_font->m_bSubstCJK = true;
675       if (nStyle)
676         subst_font->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL;
677       if (FontStyleIsItalic(nStyle))
678         subst_font->m_bItalicCJK = true;
679     }
680   } else {
681     italic_angle = 0;
682     if (nStyle == FXFONT_NORMAL)
683       weight = FXFONT_FW_NORMAL;
684   }
685 
686   if (!match.IsEmpty() || base_font < kNumStandardFonts) {
687     if (!match.IsEmpty())
688       family = match;
689     if (base_font < kNumStandardFonts) {
690       base_font = AdjustBaseFontForStyle(base_font, nStyle);
691       family = kBase14FontNames[base_font];
692     }
693   } else if (FontStyleIsItalic(flags)) {
694     is_italic = true;
695   }
696   void* font_handle =
697       m_pFontInfo->MapFont(weight, is_italic, Charset, pitch_family, family);
698   if (font_handle) {
699     return UseExternalSubst(font_handle, subst_name, weight, is_italic,
700                             italic_angle, Charset, subst_font);
701   }
702 
703   if (is_cjk) {
704     is_italic = italic_angle != 0;
705     weight = old_weight;
706   }
707   if (!match.IsEmpty()) {
708     font_handle = m_pFontInfo->GetFont(match);
709     if (!font_handle) {
710       return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
711                               subst_font);
712     }
713     return UseExternalSubst(font_handle, subst_name, weight, is_italic,
714                             italic_angle, Charset, subst_font);
715   }
716 
717   if (Charset == FX_Charset::kSymbol) {
718 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
719     if (subst_name == "Symbol") {
720       subst_font->m_Family = "Chrome Symbol";
721       subst_font->m_Charset = FX_Charset::kSymbol;
722       return UseInternalSubst(kSymbol, old_weight, italic_angle, pitch_family,
723                               subst_font);
724     }
725 #endif
726     return FindSubstFont(family, is_truetype, flags & ~FXFONT_SYMBOLIC, weight,
727                          italic_angle, FX_CodePage::kDefANSI, subst_font);
728   }
729 
730   if (Charset == FX_Charset::kANSI) {
731     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
732                             subst_font);
733   }
734 
735   auto it = std::find_if(
736       m_FaceArray.begin(), m_FaceArray.end(), [Charset](const FaceData& face) {
737         return face.charset == static_cast<uint32_t>(Charset);
738       });
739   if (it == m_FaceArray.end()) {
740     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
741                             subst_font);
742   }
743   font_handle = m_pFontInfo->GetFont(it->name);
744   if (!font_handle)
745     return nullptr;
746   return UseExternalSubst(font_handle, subst_name, weight, is_italic,
747                           italic_angle, Charset, subst_font);
748 }
749 
GetFaceSize() const750 size_t CFX_FontMapper::GetFaceSize() const {
751   return m_FaceArray.size();
752 }
753 
GetFaceName(size_t index) const754 ByteString CFX_FontMapper::GetFaceName(size_t index) const {
755   CHECK_LT(index, m_FaceArray.size());
756   return m_FaceArray[index].name;
757 }
758 
HasInstalledFont(ByteStringView name) const759 bool CFX_FontMapper::HasInstalledFont(ByteStringView name) const {
760   for (const auto& font : m_InstalledTTFonts) {
761     if (font == name)
762       return true;
763   }
764   return false;
765 }
766 
HasLocalizedFont(ByteStringView name) const767 bool CFX_FontMapper::HasLocalizedFont(ByteStringView name) const {
768   for (const auto& fontPair : m_LocalizedTTFonts) {
769     if (fontPair.first == name)
770       return true;
771   }
772   return false;
773 }
774 
775 #if BUILDFLAG(IS_WIN)
InstalledFontNameStartingWith(const ByteString & name) const776 absl::optional<ByteString> CFX_FontMapper::InstalledFontNameStartingWith(
777     const ByteString& name) const {
778   for (const auto& thisname : m_InstalledTTFonts) {
779     if (thisname.First(name.GetLength()) == name)
780       return thisname;
781   }
782   return absl::nullopt;
783 }
784 
LocalizedFontNameStartingWith(const ByteString & name) const785 absl::optional<ByteString> CFX_FontMapper::LocalizedFontNameStartingWith(
786     const ByteString& name) const {
787   for (const auto& thispair : m_LocalizedTTFonts) {
788     if (thispair.first.First(name.GetLength()) == name)
789       return thispair.second;
790   }
791   return absl::nullopt;
792 }
793 #endif  // BUILDFLAG(IS_WIN)
794 
795 #ifdef PDF_ENABLE_XFA
RawBytesForIndex(size_t index)796 FixedUninitDataVector<uint8_t> CFX_FontMapper::RawBytesForIndex(size_t index) {
797   CHECK_LT(index, m_FaceArray.size());
798 
799   void* font_handle = m_pFontInfo->MapFont(0, false, FX_Charset::kDefault, 0,
800                                            GetFaceName(index));
801   if (!font_handle)
802     return FixedUninitDataVector<uint8_t>();
803 
804   ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
805   size_t required_size = m_pFontInfo->GetFontData(font_handle, 0, {});
806   if (required_size == 0)
807     return FixedUninitDataVector<uint8_t>();
808 
809   FixedUninitDataVector<uint8_t> result(required_size);
810   size_t actual_size =
811       m_pFontInfo->GetFontData(font_handle, 0, result.writable_span());
812   if (actual_size != required_size)
813     return FixedUninitDataVector<uint8_t>();
814 
815   return result;
816 }
817 #endif  // PDF_ENABLE_XFA
818 
GetCachedTTCFace(void * font_handle,size_t ttc_size,size_t data_size)819 RetainPtr<CFX_Face> CFX_FontMapper::GetCachedTTCFace(void* font_handle,
820                                                      size_t ttc_size,
821                                                      size_t data_size) {
822   CHECK_GE(ttc_size, data_size);
823   uint32_t checksum = GetChecksumFromTT(font_handle);
824   RetainPtr<CFX_FontMgr::FontDesc> pFontDesc =
825       m_pFontMgr->GetCachedTTCFontDesc(ttc_size, checksum);
826   if (!pFontDesc) {
827     FixedUninitDataVector<uint8_t> font_data(ttc_size);
828     size_t size = m_pFontInfo->GetFontData(font_handle, kTableTTCF,
829                                            font_data.writable_span());
830     if (size != ttc_size)
831       return nullptr;
832 
833     pFontDesc = m_pFontMgr->AddCachedTTCFontDesc(ttc_size, checksum,
834                                                  std::move(font_data));
835   }
836   size_t font_offset = ttc_size - data_size;
837   size_t face_index =
838       GetTTCIndex(pFontDesc->FontData().first(ttc_size), font_offset);
839   RetainPtr<CFX_Face> pFace(pFontDesc->GetFace(face_index));
840   if (pFace)
841     return pFace;
842 
843   pFace = m_pFontMgr->NewFixedFace(
844       pFontDesc, pFontDesc->FontData().first(ttc_size), face_index);
845   if (!pFace)
846     return nullptr;
847 
848   pFontDesc->SetFace(face_index, pFace.Get());
849   return pFace;
850 }
851 
GetCachedFace(void * font_handle,ByteString subst_name,int weight,bool is_italic,size_t data_size)852 RetainPtr<CFX_Face> CFX_FontMapper::GetCachedFace(void* font_handle,
853                                                   ByteString subst_name,
854                                                   int weight,
855                                                   bool is_italic,
856                                                   size_t data_size) {
857   RetainPtr<CFX_FontMgr::FontDesc> pFontDesc =
858       m_pFontMgr->GetCachedFontDesc(subst_name, weight, is_italic);
859   if (!pFontDesc) {
860     FixedUninitDataVector<uint8_t> font_data(data_size);
861     size_t size =
862         m_pFontInfo->GetFontData(font_handle, 0, font_data.writable_span());
863     if (size != data_size)
864       return nullptr;
865 
866     pFontDesc = m_pFontMgr->AddCachedFontDesc(subst_name, weight, is_italic,
867                                               std::move(font_data));
868   }
869   RetainPtr<CFX_Face> pFace(pFontDesc->GetFace(0));
870   if (pFace)
871     return pFace;
872 
873   pFace = m_pFontMgr->NewFixedFace(pFontDesc,
874                                    pFontDesc->FontData().first(data_size), 0);
875   if (!pFace)
876     return nullptr;
877 
878   pFontDesc->SetFace(0, pFace.Get());
879   return pFace;
880 }
881 
882 // static
883 absl::optional<CFX_FontMapper::StandardFont>
GetStandardFontName(ByteString * name)884 CFX_FontMapper::GetStandardFontName(ByteString* name) {
885   const auto* end = std::end(kAltFontNames);
886   const auto* found =
887       std::lower_bound(std::begin(kAltFontNames), end, name->c_str(),
888                        [](const AltFontName& element, const char* name) {
889                          return FXSYS_stricmp(element.m_pName, name) < 0;
890                        });
891   if (found == end || FXSYS_stricmp(found->m_pName, name->c_str()))
892     return absl::nullopt;
893 
894   *name = kBase14FontNames[static_cast<size_t>(found->m_Index)];
895   return found->m_Index;
896 }
897 
898 // static
IsStandardFontName(const ByteString & name)899 bool CFX_FontMapper::IsStandardFontName(const ByteString& name) {
900   return pdfium::Contains(kBase14FontNames, name);
901 }
902 
903 // static
IsSymbolicFont(StandardFont font)904 bool CFX_FontMapper::IsSymbolicFont(StandardFont font) {
905   return font == StandardFont::kSymbol || font == StandardFont::kDingbats;
906 }
907 
908 // static
IsFixedFont(StandardFont font)909 bool CFX_FontMapper::IsFixedFont(StandardFont font) {
910   return font == StandardFont::kCourier || font == StandardFont::kCourierBold ||
911          font == StandardFont::kCourierBoldOblique ||
912          font == StandardFont::kCourierOblique;
913 }
914