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