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