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