• 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/check_op.h"
17 #include "core/fxcrt/containers/adapters.h"
18 #include "core/fxcrt/containers/contains.h"
19 #include "core/fxcrt/data_vector.h"
20 #include "core/fxcrt/fx_codepage.h"
21 #include "core/fxcrt/fx_extension.h"
22 #include "core/fxcrt/fx_memory.h"
23 #include "core/fxcrt/unowned_ptr_exclusion.h"
24 #include "core/fxge/cfx_fontmgr.h"
25 #include "core/fxge/cfx_substfont.h"
26 #include "core/fxge/fx_font.h"
27 #include "core/fxge/systemfontinfo_iface.h"
28 
29 namespace {
30 
31 static_assert(CFX_FontMapper::kLast + 1 == CFX_FontMapper::kNumStandardFonts,
32               "StandardFont enum count mismatch");
33 
34 constexpr std::array<const char*, CFX_FontMapper::kNumStandardFonts>
35     kBase14FontNames = {{
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,const ByteString & fontname)179 const char* GetFontFamily(uint32_t nStyle, const ByteString& fontname) {
180   if (fontname.Contains("Script")) {
181     if (FontStyleIsForceBold(nStyle)) {
182       return "ScriptMTBold";
183     }
184     if (fontname.Contains("Palace")) {
185       return "PalaceScriptMT";
186     } else if (fontname.Contains("French")) {
187       return "FrenchScriptMT";
188     } else if (fontname.Contains("FreeStyle")) {
189       return "FreeStyleScript";
190     }
191     return nullptr;
192   }
193   for (const auto& alternate : kAltFontFamilies) {
194     if (fontname.Contains(alternate.m_pFontName)) {
195       return alternate.m_pFontFamily;
196     }
197   }
198   return nullptr;
199 }
200 
ParseStyle(const ByteString & bsStyle,size_t iStart)201 ByteString ParseStyle(const ByteString& bsStyle, size_t iStart) {
202   ByteStringView bsRegion = bsStyle.AsStringView().Substr(iStart);
203   size_t iIndex = bsRegion.Find(',').value_or(bsRegion.GetLength());
204   return ByteString(bsRegion.First(iIndex));
205 }
206 
207 struct FX_FontStyle {
208   const char* name;
209   size_t len;
210   uint32_t style;
211 };
212 
213 constexpr FX_FontStyle kFontStyles[] = {
214     {"Regular", 7, FXFONT_NORMAL},
215     {"Reg", 3, FXFONT_NORMAL},
216     {"BoldItalic", 10, FXFONT_FORCE_BOLD | FXFONT_ITALIC},
217     {"Italic", 6, FXFONT_ITALIC},
218     {"Bold", 4, FXFONT_FORCE_BOLD},
219 };
220 
GetStyleType(ByteStringView font_name,bool reverse_search)221 const FX_FontStyle* GetStyleType(ByteStringView font_name,
222                                  bool reverse_search) {
223   if (font_name.IsEmpty())
224     return nullptr;
225 
226   for (const FX_FontStyle& style : kFontStyles) {
227     if (style.len > font_name.GetLength())
228       continue;
229 
230     ByteStringView style_view =
231         reverse_search ? font_name.Last(style.len) : font_name.First(style.len);
232     if (style_view == style.name)
233       return &style;
234   }
235   return nullptr;
236 }
237 
ParseStyles(const ByteString & style_str,bool * is_style_available,int * weight,uint32_t * style)238 bool ParseStyles(const ByteString& style_str,
239                  bool* is_style_available,
240                  int* weight,
241                  uint32_t* style) {
242   if (style_str.IsEmpty())
243     return false;
244 
245   size_t i = 0;
246   bool is_first_item = true;
247   while (i < style_str.GetLength()) {
248     ByteString buf = ParseStyle(style_str, i);
249     const FX_FontStyle* style_result =
250         GetStyleType(buf.AsStringView(), /*reverse_search=*/false);
251     if ((i && !*is_style_available) || (!i && !style_result))
252       return true;
253 
254     uint32_t parsed_style;
255     if (style_result) {
256       *is_style_available = true;
257       parsed_style = style_result->style;
258     } else {
259       parsed_style = FXFONT_NORMAL;
260     }
261 
262     if (FontStyleIsForceBold(parsed_style)) {
263       // If we're already bold, then we're double bold, use special weight.
264       if (FontStyleIsForceBold(*style)) {
265         *weight = FXFONT_FW_BOLD_BOLD;
266       } else {
267         *weight = FXFONT_FW_BOLD;
268         *style |= FXFONT_FORCE_BOLD;
269       }
270 
271       is_first_item = false;
272     }
273     if (FontStyleIsItalic(parsed_style) && FontStyleIsForceBold(parsed_style)) {
274       *style |= FXFONT_ITALIC;
275     } else if (FontStyleIsItalic(parsed_style)) {
276       if (!is_first_item)
277         return true;
278 
279       *style |= FXFONT_ITALIC;
280       break;
281     }
282     i += buf.GetLength() + 1;
283   }
284   return false;
285 }
286 
CheckSupportThirdPartFont(const ByteString & name,int * pitch_family)287 bool CheckSupportThirdPartFont(const ByteString& name, int* pitch_family) {
288   if (name != "MyriadPro")
289     return false;
290   *pitch_family &= ~FXFONT_FF_ROMAN;
291   return true;
292 }
293 
GetStyleFromBaseFont(int base_font)294 uint32_t GetStyleFromBaseFont(int base_font) {
295   int pos = base_font % 4;
296   uint32_t style = FXFONT_NORMAL;
297   if (pos == 1 || pos == 2)
298     style |= FXFONT_FORCE_BOLD;
299   if (pos / 2)
300     style |= FXFONT_ITALIC;
301   return style;
302 }
303 
GetPitchFamilyFromBaseFont(int base_font)304 int GetPitchFamilyFromBaseFont(int base_font) {
305   if (base_font < 4)
306     return FXFONT_FF_FIXEDPITCH;
307   if (base_font >= 8)
308     return FXFONT_FF_ROMAN;
309   return 0;
310 }
311 
GetPitchFamilyFromFlags(uint32_t flags)312 int GetPitchFamilyFromFlags(uint32_t flags) {
313   int pitch_family = 0;
314   if (FontStyleIsSerif(flags))
315     pitch_family |= FXFONT_FF_ROMAN;
316   if (FontStyleIsScript(flags))
317     pitch_family |= FXFONT_FF_SCRIPT;
318   if (FontStyleIsFixedPitch(flags))
319     pitch_family |= FXFONT_FF_FIXEDPITCH;
320   return pitch_family;
321 }
322 
AdjustBaseFontForStyle(int base_font,uint32_t style)323 int AdjustBaseFontForStyle(int base_font, uint32_t style) {
324   if (!style || (base_font % 4))
325     return base_font;
326 
327   if (FontStyleIsForceBold(style) && FontStyleIsItalic(style))
328     base_font += 2;
329   else if (FontStyleIsForceBold(style))
330     base_font += 1;
331   else if (FontStyleIsItalic(style))
332     base_font += 3;
333   return base_font;
334 }
335 
GetCharset(FX_CodePage code_page,int base_font,uint32_t flags)336 FX_Charset GetCharset(FX_CodePage code_page, int base_font, uint32_t flags) {
337   if (code_page != FX_CodePage::kDefANSI)
338     return FX_GetCharsetFromCodePage(code_page);
339   if (FontStyleIsSymbolic(flags) &&
340       base_font == CFX_FontMapper::kNumStandardFonts) {
341     return FX_Charset::kSymbol;
342   }
343   return FX_Charset::kANSI;
344 }
345 
IsStrUpper(const ByteString & str)346 bool IsStrUpper(const ByteString& str) {
347   for (size_t i = 0; i < str.GetLength(); ++i) {
348     if (!FXSYS_IsUpperASCII(str[i]))
349       return false;
350   }
351   return true;
352 }
353 
RemoveSubsettedFontPrefix(ByteString * subst_name)354 void RemoveSubsettedFontPrefix(ByteString* subst_name) {
355   constexpr size_t kPrefixLength = 6;
356   if (subst_name->GetLength() > kPrefixLength &&
357       (*subst_name)[kPrefixLength] == '+' &&
358       IsStrUpper(subst_name->First(kPrefixLength))) {
359     *subst_name =
360         subst_name->Last(subst_name->GetLength() - (kPrefixLength + 1));
361   }
362 }
363 
GetSubstName(const ByteString & name,bool is_truetype)364 ByteString GetSubstName(const ByteString& name, bool is_truetype) {
365   ByteString subst_name = name;
366   if (is_truetype && name.Front() == '@')
367     subst_name.Delete(0);
368   else
369     subst_name.Remove(' ');
370   RemoveSubsettedFontPrefix(&subst_name);
371   CFX_FontMapper::GetStandardFontName(&subst_name);
372   return subst_name;
373 }
374 
IsNarrowFontName(const ByteString & name)375 bool IsNarrowFontName(const ByteString& name) {
376   static const char kNarrowFonts[][10] = {"Narrow", "Condensed"};
377   for (const char* font : kNarrowFonts) {
378     std::optional<size_t> pos = name.Find(font);
379     if (pos.has_value() && pos.value() != 0)
380       return true;
381   }
382   return false;
383 }
384 
385 class ScopedFontDeleter {
386  public:
387   FX_STACK_ALLOCATED();
388 
ScopedFontDeleter(SystemFontInfoIface * font_info,void * font)389   ScopedFontDeleter(SystemFontInfoIface* font_info, void* font)
390       : font_info_(font_info), font_(font) {}
~ScopedFontDeleter()391   ~ScopedFontDeleter() { font_info_->DeleteFont(font_); }
392 
393  private:
394   UnownedPtr<SystemFontInfoIface> const font_info_;
395   UNOWNED_PTR_EXCLUSION void* const font_;  // void type incompatible.
396 };
397 
398 }  // namespace
399 
CFX_FontMapper(CFX_FontMgr * mgr)400 CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) : m_pFontMgr(mgr) {}
401 
402 CFX_FontMapper::~CFX_FontMapper() = default;
403 
SetSystemFontInfo(std::unique_ptr<SystemFontInfoIface> pFontInfo)404 void CFX_FontMapper::SetSystemFontInfo(
405     std::unique_ptr<SystemFontInfoIface> pFontInfo) {
406   if (!pFontInfo)
407     return;
408 
409   m_bListLoaded = false;
410   m_pFontInfo = std::move(pFontInfo);
411 }
412 
TakeSystemFontInfo()413 std::unique_ptr<SystemFontInfoIface> CFX_FontMapper::TakeSystemFontInfo() {
414   return std::move(m_pFontInfo);
415 }
416 
GetChecksumFromTT(void * font_handle)417 uint32_t CFX_FontMapper::GetChecksumFromTT(void* font_handle) {
418   uint32_t buffer[256];
419   m_pFontInfo->GetFontData(font_handle, kTableTTCF,
420                            pdfium::as_writable_byte_span(buffer));
421 
422   uint32_t checksum = 0;
423   for (auto x : buffer) {
424     checksum += x;
425   }
426   return checksum;
427 }
428 
GetPSNameFromTT(void * font_handle)429 ByteString CFX_FontMapper::GetPSNameFromTT(void* font_handle) {
430   size_t size = m_pFontInfo->GetFontData(font_handle, kTableNAME, {});
431   if (!size)
432     return ByteString();
433 
434   DataVector<uint8_t> buffer(size);
435   size_t bytes_read = m_pFontInfo->GetFontData(font_handle, kTableNAME, buffer);
436   return bytes_read == size ? GetNameFromTT(buffer, 6) : ByteString();
437 }
438 
AddInstalledFont(const ByteString & name,FX_Charset charset)439 void CFX_FontMapper::AddInstalledFont(const ByteString& name,
440                                       FX_Charset charset) {
441   if (!m_pFontInfo)
442     return;
443 
444   m_FaceArray.push_back({name, static_cast<uint32_t>(charset)});
445   if (name == m_LastFamily)
446     return;
447 
448   bool is_localized = std::any_of(name.begin(), name.end(), [](const char& c) {
449     return static_cast<uint8_t>(c) > 0x80;
450   });
451 
452   if (is_localized) {
453     void* font_handle = m_pFontInfo->GetFont(name);
454     if (!font_handle) {
455       font_handle =
456           m_pFontInfo->MapFont(0, false, FX_Charset::kDefault, 0, name);
457       if (!font_handle)
458         return;
459     }
460 
461     ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
462     ByteString new_name = GetPSNameFromTT(font_handle);
463     if (!new_name.IsEmpty())
464       m_LocalizedTTFonts.emplace_back(new_name, name);
465   }
466   m_InstalledTTFonts.push_back(name);
467   m_LastFamily = name;
468 }
469 
LoadInstalledFonts()470 void CFX_FontMapper::LoadInstalledFonts() {
471   if (!m_pFontInfo || m_bListLoaded)
472     return;
473 
474   m_pFontInfo->EnumFontList(this);
475   m_bListLoaded = true;
476 }
477 
MatchInstalledFonts(const ByteString & norm_name)478 ByteString CFX_FontMapper::MatchInstalledFonts(const ByteString& norm_name) {
479   LoadInstalledFonts();
480   for (const ByteString& font : pdfium::Reversed(m_InstalledTTFonts)) {
481     if (TT_NormalizeName(font) == norm_name) {
482       return font;
483     }
484   }
485   for (const auto& font_data : pdfium::Reversed(m_LocalizedTTFonts)) {
486     if (TT_NormalizeName(font_data.first) == norm_name) {
487       return font_data.second;
488     }
489   }
490   return ByteString();
491 }
492 
UseInternalSubst(int base_font,int weight,int italic_angle,int pitch_family,CFX_SubstFont * subst_font)493 RetainPtr<CFX_Face> CFX_FontMapper::UseInternalSubst(
494     int base_font,
495     int weight,
496     int italic_angle,
497     int pitch_family,
498     CFX_SubstFont* subst_font) {
499   if (base_font < kNumStandardFonts) {
500     if (!m_StandardFaces[base_font]) {
501       m_StandardFaces[base_font] = m_pFontMgr->NewFixedFace(
502           nullptr, m_pFontMgr->GetStandardFont(base_font), 0);
503     }
504     return m_StandardFaces[base_font];
505   }
506 
507   subst_font->SetIsBuiltInGenericFont();
508   subst_font->m_ItalicAngle = italic_angle;
509   if (weight)
510     subst_font->m_Weight = weight;
511   if (FontFamilyIsRoman(pitch_family)) {
512     subst_font->UseChromeSerif();
513     if (!m_GenericSerifFace) {
514       m_GenericSerifFace = m_pFontMgr->NewFixedFace(
515           nullptr, m_pFontMgr->GetGenericSerifFont(), 0);
516     }
517     return m_GenericSerifFace;
518   }
519   subst_font->m_Family = "Chrome Sans";
520   if (!m_GenericSansFace) {
521     m_GenericSansFace =
522         m_pFontMgr->NewFixedFace(nullptr, m_pFontMgr->GetGenericSansFont(), 0);
523   }
524   return m_GenericSansFace;
525 }
526 
UseExternalSubst(void * font_handle,ByteString face_name,int weight,bool is_italic,int italic_angle,FX_Charset charset,CFX_SubstFont * subst_font)527 RetainPtr<CFX_Face> CFX_FontMapper::UseExternalSubst(
528     void* font_handle,
529     ByteString face_name,
530     int weight,
531     bool is_italic,
532     int italic_angle,
533     FX_Charset charset,
534     CFX_SubstFont* subst_font) {
535   DCHECK(font_handle);
536 
537   ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
538   m_pFontInfo->GetFaceName(font_handle, &face_name);
539   if (charset == FX_Charset::kDefault)
540     m_pFontInfo->GetFontCharset(font_handle, &charset);
541   size_t ttc_size = m_pFontInfo->GetFontData(font_handle, kTableTTCF, {});
542   size_t font_size = m_pFontInfo->GetFontData(font_handle, 0, {});
543   if (font_size == 0 && ttc_size == 0)
544     return nullptr;
545 
546   RetainPtr<CFX_Face> face =
547       ttc_size
548           ? GetCachedTTCFace(font_handle, ttc_size, font_size)
549           : GetCachedFace(font_handle, face_name, weight, is_italic, font_size);
550   if (!face)
551     return nullptr;
552 
553   subst_font->m_Family = face_name;
554   subst_font->m_Charset = charset;
555   int face_weight = face->IsBold() ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
556   if (weight != face_weight)
557     subst_font->m_Weight = weight;
558   if (is_italic && !face->IsItalic()) {
559     if (italic_angle == 0)
560       italic_angle = -12;
561     else if (abs(italic_angle) < 5)
562       italic_angle = 0;
563     subst_font->m_ItalicAngle = italic_angle;
564   }
565   return face;
566 }
567 
FindSubstFont(const ByteString & name,bool is_truetype,uint32_t flags,int weight,int italic_angle,FX_CodePage code_page,CFX_SubstFont * subst_font)568 RetainPtr<CFX_Face> CFX_FontMapper::FindSubstFont(const ByteString& name,
569                                                   bool is_truetype,
570                                                   uint32_t flags,
571                                                   int weight,
572                                                   int italic_angle,
573                                                   FX_CodePage code_page,
574                                                   CFX_SubstFont* subst_font) {
575   if (weight == 0)
576     weight = FXFONT_FW_NORMAL;
577 
578   if (!(flags & FXFONT_USEEXTERNATTR)) {
579     weight = FXFONT_FW_NORMAL;
580     italic_angle = 0;
581   }
582   const ByteString subst_name = GetSubstName(name, is_truetype);
583   if (subst_name == "Symbol" && !is_truetype) {
584     subst_font->m_Family = "Chrome Symbol";
585     subst_font->m_Charset = FX_Charset::kSymbol;
586     return UseInternalSubst(kSymbol, weight, italic_angle, 0, subst_font);
587   }
588   if (subst_name == "ZapfDingbats") {
589     subst_font->m_Family = "Chrome Dingbats";
590     subst_font->m_Charset = FX_Charset::kSymbol;
591     return UseInternalSubst(kDingbats, weight, italic_angle, 0, subst_font);
592   }
593   int base_font = 0;
594   ByteString family;
595   ByteString style;
596   bool has_comma = false;
597   bool has_hyphen = false;
598   {
599     std::optional<size_t> pos = subst_name.Find(",");
600     if (pos.has_value()) {
601       family = subst_name.First(pos.value());
602       GetStandardFontName(&family);
603       style = subst_name.Last(subst_name.GetLength() - (pos.value() + 1));
604       has_comma = true;
605     } else {
606       family = subst_name;
607     }
608   }
609   for (; base_font < kSymbol; base_font++) {
610     if (family == kBase14FontNames[base_font])
611       break;
612   }
613   int pitch_family;
614   uint32_t nStyle;
615   bool is_style_available = false;
616   if (base_font < kSymbol) {
617     nStyle = GetStyleFromBaseFont(base_font);
618     pitch_family = GetPitchFamilyFromBaseFont(base_font);
619   } else {
620     base_font = kNumStandardFonts;
621     nStyle = FXFONT_NORMAL;
622     if (!has_comma) {
623       std::optional<size_t> pos = family.ReverseFind('-');
624       if (pos.has_value()) {
625         style = family.Last(family.GetLength() - (pos.value() + 1));
626         family = family.First(pos.value());
627         has_hyphen = true;
628       }
629     }
630     if (!has_hyphen) {
631       size_t nLen = family.GetLength();
632       const FX_FontStyle* style_result =
633           GetStyleType(family.AsStringView(), /*reverse_search=*/true);
634       if (style_result) {
635         family = family.First(nLen - style_result->len);
636         nStyle |= style_result->style;
637       }
638     }
639     pitch_family = GetPitchFamilyFromFlags(flags);
640   }
641 
642   const int old_weight = weight;
643   if (FontStyleIsForceBold(nStyle))
644     weight = FXFONT_FW_BOLD;
645 
646   if (ParseStyles(style, &is_style_available, &weight, &nStyle)) {
647     family = subst_name;
648     base_font = kNumStandardFonts;
649   }
650 
651   if (!m_pFontInfo) {
652     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
653                             subst_font);
654   }
655 
656   const FX_Charset Charset = GetCharset(code_page, base_font, flags);
657   const bool is_cjk = FX_CharSetIsCJK(Charset);
658   bool is_italic = FontStyleIsItalic(nStyle);
659 
660   const char* maybe_family = GetFontFamily(nStyle, family);
661   if (maybe_family) {
662     family = ByteString(maybe_family);
663   }
664 
665   ByteString match = MatchInstalledFonts(TT_NormalizeName(family));
666   if (match.IsEmpty() && family != subst_name &&
667       (!has_comma && (!has_hyphen || (has_hyphen && !is_style_available)))) {
668     match = MatchInstalledFonts(TT_NormalizeName(subst_name));
669   }
670   if (match.IsEmpty() && base_font >= kNumStandardFonts) {
671     if (!is_cjk) {
672       if (!CheckSupportThirdPartFont(family, &pitch_family)) {
673         is_italic = italic_angle != 0;
674         weight = old_weight;
675       }
676       if (IsNarrowFontName(subst_name))
677         family = kNarrowFamily;
678     } else {
679       subst_font->m_bSubstCJK = true;
680       if (nStyle)
681         subst_font->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL;
682       if (FontStyleIsItalic(nStyle))
683         subst_font->m_bItalicCJK = true;
684     }
685   } else {
686     italic_angle = 0;
687     if (nStyle == FXFONT_NORMAL)
688       weight = FXFONT_FW_NORMAL;
689   }
690 
691   if (!match.IsEmpty() || base_font < kNumStandardFonts) {
692     if (!match.IsEmpty())
693       family = match;
694     if (base_font < kNumStandardFonts) {
695       base_font = AdjustBaseFontForStyle(base_font, nStyle);
696       family = kBase14FontNames[base_font];
697     }
698   } else if (FontStyleIsItalic(flags)) {
699     is_italic = true;
700   }
701   void* font_handle =
702       m_pFontInfo->MapFont(weight, is_italic, Charset, pitch_family, family);
703   if (font_handle) {
704     return UseExternalSubst(font_handle, subst_name, weight, is_italic,
705                             italic_angle, Charset, subst_font);
706   }
707 
708   if (is_cjk) {
709     is_italic = italic_angle != 0;
710     weight = old_weight;
711   }
712   if (!match.IsEmpty()) {
713     font_handle = m_pFontInfo->GetFont(match);
714     if (!font_handle) {
715       return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
716                               subst_font);
717     }
718     return UseExternalSubst(font_handle, subst_name, weight, is_italic,
719                             italic_angle, Charset, subst_font);
720   }
721 
722   if (Charset == FX_Charset::kSymbol) {
723 #if !BUILDFLAG(IS_WIN)
724     if (subst_name == "Symbol") {
725       subst_font->m_Family = "Chrome Symbol";
726       subst_font->m_Charset = FX_Charset::kSymbol;
727       return UseInternalSubst(kSymbol, old_weight, italic_angle, pitch_family,
728                               subst_font);
729     }
730 #endif
731     return FindSubstFont(family, is_truetype, flags & ~FXFONT_SYMBOLIC, weight,
732                          italic_angle, FX_CodePage::kDefANSI, subst_font);
733   }
734 
735   if (Charset == FX_Charset::kANSI) {
736     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
737                             subst_font);
738   }
739 
740   auto it = std::find_if(
741       m_FaceArray.begin(), m_FaceArray.end(), [Charset](const FaceData& face) {
742         return face.charset == static_cast<uint32_t>(Charset);
743       });
744   if (it == m_FaceArray.end()) {
745     return UseInternalSubst(base_font, old_weight, italic_angle, pitch_family,
746                             subst_font);
747   }
748   font_handle = m_pFontInfo->GetFont(it->name);
749   if (!font_handle)
750     return nullptr;
751   return UseExternalSubst(font_handle, subst_name, weight, is_italic,
752                           italic_angle, Charset, subst_font);
753 }
754 
GetFaceSize() const755 size_t CFX_FontMapper::GetFaceSize() const {
756   return m_FaceArray.size();
757 }
758 
GetFaceName(size_t index) const759 ByteString CFX_FontMapper::GetFaceName(size_t index) const {
760   CHECK_LT(index, m_FaceArray.size());
761   return m_FaceArray[index].name;
762 }
763 
HasInstalledFont(ByteStringView name) const764 bool CFX_FontMapper::HasInstalledFont(ByteStringView name) const {
765   for (const auto& font : m_InstalledTTFonts) {
766     if (font == name)
767       return true;
768   }
769   return false;
770 }
771 
HasLocalizedFont(ByteStringView name) const772 bool CFX_FontMapper::HasLocalizedFont(ByteStringView name) const {
773   for (const auto& fontPair : m_LocalizedTTFonts) {
774     if (fontPair.first == name)
775       return true;
776   }
777   return false;
778 }
779 
780 #if BUILDFLAG(IS_WIN)
InstalledFontNameStartingWith(const ByteString & name) const781 std::optional<ByteString> CFX_FontMapper::InstalledFontNameStartingWith(
782     const ByteString& name) const {
783   for (const auto& thisname : m_InstalledTTFonts) {
784     if (thisname.First(name.GetLength()) == name)
785       return thisname;
786   }
787   return std::nullopt;
788 }
789 
LocalizedFontNameStartingWith(const ByteString & name) const790 std::optional<ByteString> CFX_FontMapper::LocalizedFontNameStartingWith(
791     const ByteString& name) const {
792   for (const auto& thispair : m_LocalizedTTFonts) {
793     if (thispair.first.First(name.GetLength()) == name)
794       return thispair.second;
795   }
796   return std::nullopt;
797 }
798 #endif  // BUILDFLAG(IS_WIN)
799 
800 #ifdef PDF_ENABLE_XFA
RawBytesForIndex(size_t index)801 FixedSizeDataVector<uint8_t> CFX_FontMapper::RawBytesForIndex(size_t index) {
802   CHECK_LT(index, m_FaceArray.size());
803 
804   void* font_handle = m_pFontInfo->MapFont(0, false, FX_Charset::kDefault, 0,
805                                            GetFaceName(index));
806   if (!font_handle) {
807     return FixedSizeDataVector<uint8_t>();
808   }
809   ScopedFontDeleter scoped_font(m_pFontInfo.get(), font_handle);
810   size_t required_size = m_pFontInfo->GetFontData(font_handle, 0, {});
811   if (required_size == 0) {
812     return FixedSizeDataVector<uint8_t>();
813   }
814   auto result = FixedSizeDataVector<uint8_t>::Uninit(required_size);
815   size_t actual_size = m_pFontInfo->GetFontData(font_handle, 0, result.span());
816   if (actual_size != required_size) {
817     return FixedSizeDataVector<uint8_t>();
818   }
819   return result;
820 }
821 #endif  // PDF_ENABLE_XFA
822 
GetCachedTTCFace(void * font_handle,size_t ttc_size,size_t data_size)823 RetainPtr<CFX_Face> CFX_FontMapper::GetCachedTTCFace(void* font_handle,
824                                                      size_t ttc_size,
825                                                      size_t data_size) {
826   CHECK_GE(ttc_size, data_size);
827   uint32_t checksum = GetChecksumFromTT(font_handle);
828   RetainPtr<CFX_FontMgr::FontDesc> pFontDesc =
829       m_pFontMgr->GetCachedTTCFontDesc(ttc_size, checksum);
830   if (!pFontDesc) {
831     auto font_data = FixedSizeDataVector<uint8_t>::Uninit(ttc_size);
832     size_t size =
833         m_pFontInfo->GetFontData(font_handle, kTableTTCF, font_data.span());
834     if (size != ttc_size)
835       return nullptr;
836 
837     pFontDesc = m_pFontMgr->AddCachedTTCFontDesc(ttc_size, checksum,
838                                                  std::move(font_data));
839   }
840   size_t font_offset = ttc_size - data_size;
841   size_t face_index =
842       GetTTCIndex(pFontDesc->FontData().first(ttc_size), font_offset);
843   RetainPtr<CFX_Face> pFace(pFontDesc->GetFace(face_index));
844   if (pFace)
845     return pFace;
846 
847   pFace = m_pFontMgr->NewFixedFace(
848       pFontDesc, pFontDesc->FontData().first(ttc_size), face_index);
849   if (!pFace)
850     return nullptr;
851 
852   pFontDesc->SetFace(face_index, pFace.Get());
853   return pFace;
854 }
855 
GetCachedFace(void * font_handle,ByteString subst_name,int weight,bool is_italic,size_t data_size)856 RetainPtr<CFX_Face> CFX_FontMapper::GetCachedFace(void* font_handle,
857                                                   ByteString subst_name,
858                                                   int weight,
859                                                   bool is_italic,
860                                                   size_t data_size) {
861   RetainPtr<CFX_FontMgr::FontDesc> pFontDesc =
862       m_pFontMgr->GetCachedFontDesc(subst_name, weight, is_italic);
863   if (!pFontDesc) {
864     auto font_data = FixedSizeDataVector<uint8_t>::Uninit(data_size);
865     size_t size = m_pFontInfo->GetFontData(font_handle, 0, font_data.span());
866     if (size != data_size)
867       return nullptr;
868 
869     pFontDesc = m_pFontMgr->AddCachedFontDesc(subst_name, weight, is_italic,
870                                               std::move(font_data));
871   }
872   RetainPtr<CFX_Face> pFace(pFontDesc->GetFace(0));
873   if (pFace)
874     return pFace;
875 
876   pFace = m_pFontMgr->NewFixedFace(pFontDesc,
877                                    pFontDesc->FontData().first(data_size), 0);
878   if (!pFace)
879     return nullptr;
880 
881   pFontDesc->SetFace(0, pFace.Get());
882   return pFace;
883 }
884 
885 // static
GetStandardFontName(ByteString * name)886 std::optional<CFX_FontMapper::StandardFont> CFX_FontMapper::GetStandardFontName(
887     ByteString* name) {
888   const auto* end = std::end(kAltFontNames);
889   const auto* found =
890       std::lower_bound(std::begin(kAltFontNames), end, name->c_str(),
891                        [](const AltFontName& element, const char* name) {
892                          return FXSYS_stricmp(element.m_pName, name) < 0;
893                        });
894   if (found == end || FXSYS_stricmp(found->m_pName, name->c_str()))
895     return std::nullopt;
896 
897   *name = kBase14FontNames[static_cast<size_t>(found->m_Index)];
898   return found->m_Index;
899 }
900 
901 // static
IsStandardFontName(const ByteString & name)902 bool CFX_FontMapper::IsStandardFontName(const ByteString& name) {
903   return pdfium::Contains(kBase14FontNames, name);
904 }
905 
906 // static
IsSymbolicFont(StandardFont font)907 bool CFX_FontMapper::IsSymbolicFont(StandardFont font) {
908   return font == StandardFont::kSymbol || font == StandardFont::kDingbats;
909 }
910 
911 // static
IsFixedFont(StandardFont font)912 bool CFX_FontMapper::IsFixedFont(StandardFont font) {
913   return font == StandardFont::kCourier || font == StandardFont::kCourierBold ||
914          font == StandardFont::kCourierBoldOblique ||
915          font == StandardFont::kCourierOblique;
916 }
917