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