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