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