• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 "xfa/fgas/font/cfgas_fontmgr.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "build/build_config.h"
14 #include "core/fxcrt/cfx_memorystream.h"
15 #include "core/fxcrt/fx_codepage.h"
16 #include "core/fxcrt/fx_memory_wrappers.h"
17 #include "core/fxge/cfx_font.h"
18 #include "core/fxge/cfx_fontmapper.h"
19 #include "core/fxge/cfx_fontmgr.h"
20 #include "core/fxge/cfx_gemodule.h"
21 #include "core/fxge/fx_font.h"
22 #include "third_party/base/ptr_util.h"
23 #include "third_party/base/stl_util.h"
24 #include "xfa/fgas/font/cfgas_gefont.h"
25 #include "xfa/fgas/font/fgas_fontutils.h"
26 
27 #if !defined(OS_WIN)
28 #include "xfa/fgas/font/cfx_fontsourceenum_file.h"
29 #endif
30 
31 namespace {
32 
VerifyUnicode(const RetainPtr<CFGAS_GEFont> & pFont,wchar_t wcUnicode)33 bool VerifyUnicode(const RetainPtr<CFGAS_GEFont>& pFont, wchar_t wcUnicode) {
34   RetainPtr<CFX_Face> pFace = pFont->GetDevFont()->GetFace();
35   if (!pFace)
36     return false;
37 
38   FXFT_FaceRec* pFaceRec = pFace->GetRec();
39   FT_CharMap charmap = FXFT_Get_Face_Charmap(pFaceRec);
40   if (FXFT_Select_Charmap(pFaceRec, FT_ENCODING_UNICODE) != 0)
41     return false;
42 
43   if (FT_Get_Char_Index(pFaceRec, wcUnicode) == 0) {
44     FT_Set_Charmap(pFaceRec, charmap);
45     return false;
46   }
47   return true;
48 }
49 
50 }  // namespace
51 
52 #if defined(OS_WIN)
53 
54 namespace {
55 
GetSimilarityScore(FX_FONTDESCRIPTOR const * pFont,uint32_t dwFontStyles)56 int32_t GetSimilarityScore(FX_FONTDESCRIPTOR const* pFont,
57                            uint32_t dwFontStyles) {
58   int32_t iValue = 0;
59   if (FontStyleIsSymbolic(dwFontStyles) ==
60       FontStyleIsSymbolic(pFont->dwFontStyles)) {
61     iValue += 64;
62   }
63   if (FontStyleIsFixedPitch(dwFontStyles) ==
64       FontStyleIsFixedPitch(pFont->dwFontStyles)) {
65     iValue += 32;
66   }
67   if (FontStyleIsSerif(dwFontStyles) == FontStyleIsSerif(pFont->dwFontStyles))
68     iValue += 16;
69   if (FontStyleIsScript(dwFontStyles) == FontStyleIsScript(pFont->dwFontStyles))
70     iValue += 8;
71   return iValue;
72 }
73 
MatchDefaultFont(FX_FONTMATCHPARAMS * pParams,const std::deque<FX_FONTDESCRIPTOR> & fonts)74 const FX_FONTDESCRIPTOR* MatchDefaultFont(
75     FX_FONTMATCHPARAMS* pParams,
76     const std::deque<FX_FONTDESCRIPTOR>& fonts) {
77   const FX_FONTDESCRIPTOR* pBestFont = nullptr;
78   int32_t iBestSimilar = 0;
79   for (const auto& font : fonts) {
80     if (FontStyleIsForceBold(font.dwFontStyles) &&
81         FontStyleIsItalic(font.dwFontStyles)) {
82       continue;
83     }
84 
85     if (pParams->pwsFamily) {
86       if (FXSYS_wcsicmp(pParams->pwsFamily, font.wsFontFace))
87         continue;
88       if (font.uCharSet == FX_CHARSET_Symbol)
89         return &font;
90     }
91     if (font.uCharSet == FX_CHARSET_Symbol)
92       continue;
93     if (pParams->wCodePage != 0xFFFF) {
94       if (FX_GetCodePageFromCharset(font.uCharSet) != pParams->wCodePage)
95         continue;
96     } else {
97       if (pParams->dwUSB < 128) {
98         uint32_t dwByte = pParams->dwUSB / 32;
99         uint32_t dwUSB = 1 << (pParams->dwUSB % 32);
100         if ((font.FontSignature.fsUsb[dwByte] & dwUSB) == 0)
101           continue;
102       }
103     }
104     if (pParams->matchParagraphStyle) {
105       if ((font.dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F))
106         return &font;
107       continue;
108     }
109     if (pParams->pwsFamily) {
110       if (FXSYS_wcsicmp(pParams->pwsFamily, font.wsFontFace) == 0)
111         return &font;
112     }
113     int32_t iSimilarValue = GetSimilarityScore(&font, pParams->dwFontStyles);
114     if (iBestSimilar < iSimilarValue) {
115       iBestSimilar = iSimilarValue;
116       pBestFont = &font;
117     }
118   }
119   return iBestSimilar < 1 ? nullptr : pBestFont;
120 }
121 
GetGdiFontStyles(const LOGFONTW & lf)122 uint32_t GetGdiFontStyles(const LOGFONTW& lf) {
123   uint32_t dwStyles = 0;
124   if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH)
125     dwStyles |= FXFONT_FIXED_PITCH;
126   uint8_t nFamilies = lf.lfPitchAndFamily & 0xF0;
127   if (nFamilies == FF_ROMAN)
128     dwStyles |= FXFONT_SERIF;
129   if (nFamilies == FF_SCRIPT)
130     dwStyles |= FXFONT_SCRIPT;
131   if (lf.lfCharSet == SYMBOL_CHARSET)
132     dwStyles |= FXFONT_SYMBOLIC;
133   return dwStyles;
134 }
135 
GdiFontEnumProc(ENUMLOGFONTEX * lpelfe,NEWTEXTMETRICEX * lpntme,DWORD dwFontType,LPARAM lParam)136 int32_t CALLBACK GdiFontEnumProc(ENUMLOGFONTEX* lpelfe,
137                                  NEWTEXTMETRICEX* lpntme,
138                                  DWORD dwFontType,
139                                  LPARAM lParam) {
140   if (dwFontType != TRUETYPE_FONTTYPE)
141     return 1;
142   const LOGFONTW& lf = ((LPENUMLOGFONTEXW)lpelfe)->elfLogFont;
143   if (lf.lfFaceName[0] == L'@')
144     return 1;
145   FX_FONTDESCRIPTOR font;
146   memset(&font, 0, sizeof(FX_FONTDESCRIPTOR));
147   font.uCharSet = lf.lfCharSet;
148   font.dwFontStyles = GetGdiFontStyles(lf);
149   FXSYS_wcsncpy(font.wsFontFace, (const wchar_t*)lf.lfFaceName, 31);
150   font.wsFontFace[31] = 0;
151   memcpy(&font.FontSignature, &lpntme->ntmFontSig, sizeof(lpntme->ntmFontSig));
152   reinterpret_cast<std::deque<FX_FONTDESCRIPTOR>*>(lParam)->push_back(font);
153   return 1;
154 }
155 
EnumGdiFonts(const wchar_t * pwsFaceName,wchar_t wUnicode)156 std::deque<FX_FONTDESCRIPTOR> EnumGdiFonts(const wchar_t* pwsFaceName,
157                                            wchar_t wUnicode) {
158   std::deque<FX_FONTDESCRIPTOR> fonts;
159   LOGFONTW lfFind;
160   memset(&lfFind, 0, sizeof(lfFind));
161   lfFind.lfCharSet = DEFAULT_CHARSET;
162   if (pwsFaceName) {
163     FXSYS_wcsncpy(lfFind.lfFaceName, pwsFaceName, 31);
164     lfFind.lfFaceName[31] = 0;
165   }
166   HDC hDC = ::GetDC(nullptr);
167   EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind, (FONTENUMPROCW)GdiFontEnumProc,
168                       (LPARAM)&fonts, 0);
169   ::ReleaseDC(nullptr, hDC);
170   return fonts;
171 }
172 
173 }  // namespace
174 
CFGAS_FontMgr()175 CFGAS_FontMgr::CFGAS_FontMgr() : m_FontFaces(EnumGdiFonts(nullptr, 0xFEFF)) {}
176 
177 CFGAS_FontMgr::~CFGAS_FontMgr() = default;
178 
EnumFonts()179 bool CFGAS_FontMgr::EnumFonts() {
180   return true;
181 }
182 
GetFontByUnicodeImpl(wchar_t wUnicode,uint32_t dwFontStyles,const wchar_t * pszFontFamily,uint32_t dwHash,uint16_t wCodePage,uint16_t wBitField)183 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicodeImpl(
184     wchar_t wUnicode,
185     uint32_t dwFontStyles,
186     const wchar_t* pszFontFamily,
187     uint32_t dwHash,
188     uint16_t wCodePage,
189     uint16_t wBitField) {
190   const FX_FONTDESCRIPTOR* pFD = FindFont(pszFontFamily, dwFontStyles, false,
191                                           wCodePage, wBitField, wUnicode);
192   if (!pFD && pszFontFamily) {
193     pFD =
194         FindFont(nullptr, dwFontStyles, false, wCodePage, wBitField, wUnicode);
195   }
196   if (!pFD)
197     return nullptr;
198 
199   uint16_t newCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
200   const wchar_t* pFontFace = pFD->wsFontFace;
201   RetainPtr<CFGAS_GEFont> pFont =
202       CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, newCodePage, this);
203   if (!pFont)
204     return nullptr;
205 
206   pFont->SetLogicalFontStyle(dwFontStyles);
207   if (!VerifyUnicode(pFont, wUnicode)) {
208     m_FailedUnicodesSet.insert(wUnicode);
209     return nullptr;
210   }
211 
212   m_Hash2Fonts[dwHash].push_back(pFont);
213   return pFont;
214 }
215 
FindFont(const wchar_t * pszFontFamily,uint32_t dwFontStyles,bool matchParagraphStyle,uint16_t wCodePage,uint32_t dwUSB,wchar_t wUnicode)216 const FX_FONTDESCRIPTOR* CFGAS_FontMgr::FindFont(const wchar_t* pszFontFamily,
217                                                  uint32_t dwFontStyles,
218                                                  bool matchParagraphStyle,
219                                                  uint16_t wCodePage,
220                                                  uint32_t dwUSB,
221                                                  wchar_t wUnicode) {
222   FX_FONTMATCHPARAMS params;
223   memset(&params, 0, sizeof(params));
224   params.dwUSB = dwUSB;
225   params.wUnicode = wUnicode;
226   params.wCodePage = wCodePage;
227   params.pwsFamily = pszFontFamily;
228   params.dwFontStyles = dwFontStyles;
229   params.matchParagraphStyle = matchParagraphStyle;
230 
231   const FX_FONTDESCRIPTOR* pDesc = MatchDefaultFont(&params, m_FontFaces);
232   if (pDesc)
233     return pDesc;
234 
235   if (!pszFontFamily)
236     return nullptr;
237 
238   // Use a named object to store the returned value of EnumGdiFonts() instead
239   // of using a temporary object. This can prevent use-after-free issues since
240   // pDesc may point to one of std::deque object's elements.
241   std::deque<FX_FONTDESCRIPTOR> namedFonts =
242       EnumGdiFonts(pszFontFamily, wUnicode);
243   params.pwsFamily = nullptr;
244   pDesc = MatchDefaultFont(&params, namedFonts);
245   if (!pDesc)
246     return nullptr;
247 
248   auto it = std::find(m_FontFaces.rbegin(), m_FontFaces.rend(), *pDesc);
249   if (it != m_FontFaces.rend())
250     return &*it;
251 
252   m_FontFaces.push_back(*pDesc);
253   return &m_FontFaces.back();
254 }
255 
256 #else  // defined(OS_WIN)
257 
258 namespace {
259 
260 const uint16_t g_CodePages[] = {FX_CODEPAGE_MSWin_WesternEuropean,
261                                 FX_CODEPAGE_MSWin_EasternEuropean,
262                                 FX_CODEPAGE_MSWin_Cyrillic,
263                                 FX_CODEPAGE_MSWin_Greek,
264                                 FX_CODEPAGE_MSWin_Turkish,
265                                 FX_CODEPAGE_MSWin_Hebrew,
266                                 FX_CODEPAGE_MSWin_Arabic,
267                                 FX_CODEPAGE_MSWin_Baltic,
268                                 FX_CODEPAGE_MSWin_Vietnamese,
269                                 FX_CODEPAGE_DefANSI,
270                                 FX_CODEPAGE_DefANSI,
271                                 FX_CODEPAGE_DefANSI,
272                                 FX_CODEPAGE_DefANSI,
273                                 FX_CODEPAGE_DefANSI,
274                                 FX_CODEPAGE_DefANSI,
275                                 FX_CODEPAGE_DefANSI,
276                                 FX_CODEPAGE_MSDOS_Thai,
277                                 FX_CODEPAGE_ShiftJIS,
278                                 FX_CODEPAGE_ChineseSimplified,
279                                 FX_CODEPAGE_Hangul,
280                                 FX_CODEPAGE_ChineseTraditional,
281                                 FX_CODEPAGE_Johab,
282                                 FX_CODEPAGE_DefANSI,
283                                 FX_CODEPAGE_DefANSI,
284                                 FX_CODEPAGE_DefANSI,
285                                 FX_CODEPAGE_DefANSI,
286                                 FX_CODEPAGE_DefANSI,
287                                 FX_CODEPAGE_DefANSI,
288                                 FX_CODEPAGE_DefANSI,
289                                 FX_CODEPAGE_DefANSI,
290                                 FX_CODEPAGE_DefANSI,
291                                 FX_CODEPAGE_DefANSI,
292                                 FX_CODEPAGE_DefANSI,
293                                 FX_CODEPAGE_DefANSI,
294                                 FX_CODEPAGE_DefANSI,
295                                 FX_CODEPAGE_DefANSI,
296                                 FX_CODEPAGE_DefANSI,
297                                 FX_CODEPAGE_DefANSI,
298                                 FX_CODEPAGE_DefANSI,
299                                 FX_CODEPAGE_DefANSI,
300                                 FX_CODEPAGE_DefANSI,
301                                 FX_CODEPAGE_DefANSI,
302                                 FX_CODEPAGE_DefANSI,
303                                 FX_CODEPAGE_DefANSI,
304                                 FX_CODEPAGE_DefANSI,
305                                 FX_CODEPAGE_DefANSI,
306                                 FX_CODEPAGE_DefANSI,
307                                 FX_CODEPAGE_DefANSI,
308                                 FX_CODEPAGE_MSDOS_Greek2,
309                                 FX_CODEPAGE_MSDOS_Russian,
310                                 FX_CODEPAGE_MSDOS_Norwegian,
311                                 FX_CODEPAGE_MSDOS_Arabic,
312                                 FX_CODEPAGE_MSDOS_FrenchCanadian,
313                                 FX_CODEPAGE_MSDOS_Hebrew,
314                                 FX_CODEPAGE_MSDOS_Icelandic,
315                                 FX_CODEPAGE_MSDOS_Portuguese,
316                                 FX_CODEPAGE_MSDOS_Turkish,
317                                 FX_CODEPAGE_MSDOS_Cyrillic,
318                                 FX_CODEPAGE_MSDOS_EasternEuropean,
319                                 FX_CODEPAGE_MSDOS_Baltic,
320                                 FX_CODEPAGE_MSDOS_Greek1,
321                                 FX_CODEPAGE_Arabic_ASMO708,
322                                 FX_CODEPAGE_MSDOS_WesternEuropean,
323                                 FX_CODEPAGE_MSDOS_US};
324 
FX_GetCodePageBit(uint16_t wCodePage)325 uint16_t FX_GetCodePageBit(uint16_t wCodePage) {
326   for (size_t i = 0; i < FX_ArraySize(g_CodePages); ++i) {
327     if (g_CodePages[i] == wCodePage)
328       return static_cast<uint16_t>(i);
329   }
330   return static_cast<uint16_t>(-1);
331 }
332 
FX_GetUnicodeBit(wchar_t wcUnicode)333 uint16_t FX_GetUnicodeBit(wchar_t wcUnicode) {
334   const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wcUnicode);
335   return x ? x->wBitField : 999;
336 }
337 
GetUInt8(const uint8_t * p)338 inline uint8_t GetUInt8(const uint8_t* p) {
339   return p[0];
340 }
341 
GetUInt16(const uint8_t * p)342 inline uint16_t GetUInt16(const uint8_t* p) {
343   return static_cast<uint16_t>(p[0] << 8 | p[1]);
344 }
345 
346 extern "C" {
347 
ftStreamRead(FXFT_StreamRec * stream,unsigned long offset,unsigned char * buffer,unsigned long count)348 unsigned long ftStreamRead(FXFT_StreamRec* stream,
349                            unsigned long offset,
350                            unsigned char* buffer,
351                            unsigned long count) {
352   if (count == 0)
353     return 0;
354 
355   IFX_SeekableReadStream* pFile =
356       static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
357   if (!pFile->ReadBlockAtOffset(buffer, offset, count))
358     return 0;
359 
360   return count;
361 }
362 
ftStreamClose(FXFT_StreamRec * stream)363 void ftStreamClose(FXFT_StreamRec* stream) {}
364 
365 }  // extern "C"
366 
367 // TODO(thestig): Pass in |name_table| as a std::vector?
GetNames(const uint8_t * name_table)368 std::vector<WideString> GetNames(const uint8_t* name_table) {
369   std::vector<WideString> results;
370   if (!name_table)
371     return results;
372 
373   const uint8_t* lpTable = name_table;
374   WideString wsFamily;
375   const uint8_t* sp = lpTable + 2;
376   const uint8_t* lpNameRecord = lpTable + 6;
377   uint16_t nNameCount = GetUInt16(sp);
378   const uint8_t* lpStr = lpTable + GetUInt16(sp + 2);
379   for (uint16_t j = 0; j < nNameCount; j++) {
380     uint16_t nNameID = GetUInt16(lpNameRecord + j * 12 + 6);
381     if (nNameID != 1)
382       continue;
383 
384     uint16_t nPlatformID = GetUInt16(lpNameRecord + j * 12 + 0);
385     uint16_t nNameLength = GetUInt16(lpNameRecord + j * 12 + 8);
386     uint16_t nNameOffset = GetUInt16(lpNameRecord + j * 12 + 10);
387     wsFamily.clear();
388     if (nPlatformID != 1) {
389       for (uint16_t k = 0; k < nNameLength / 2; k++) {
390         wchar_t wcTemp = GetUInt16(lpStr + nNameOffset + k * 2);
391         wsFamily += wcTemp;
392       }
393       results.push_back(wsFamily);
394       continue;
395     }
396     for (uint16_t k = 0; k < nNameLength; k++) {
397       wchar_t wcTemp = GetUInt8(lpStr + nNameOffset + k);
398       wsFamily += wcTemp;
399     }
400     results.push_back(wsFamily);
401   }
402   return results;
403 }
404 
GetUSBCSB(FXFT_FaceRec * pFace,uint32_t * USB,uint32_t * CSB)405 void GetUSBCSB(FXFT_FaceRec* pFace, uint32_t* USB, uint32_t* CSB) {
406   TT_OS2* pOS2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(pFace, ft_sfnt_os2));
407   if (!pOS2) {
408     USB[0] = 0;
409     USB[1] = 0;
410     USB[2] = 0;
411     USB[3] = 0;
412     CSB[0] = 0;
413     CSB[1] = 0;
414     return;
415   }
416   USB[0] = pOS2->ulUnicodeRange1;
417   USB[1] = pOS2->ulUnicodeRange2;
418   USB[2] = pOS2->ulUnicodeRange3;
419   USB[3] = pOS2->ulUnicodeRange4;
420   CSB[0] = pOS2->ulCodePageRange1;
421   CSB[1] = pOS2->ulCodePageRange2;
422 }
423 
GetFlags(FXFT_FaceRec * pFace)424 uint32_t GetFlags(FXFT_FaceRec* pFace) {
425   uint32_t flags = 0;
426   if (FXFT_Is_Face_Bold(pFace))
427     flags |= FXFONT_FORCE_BOLD;
428   if (FXFT_Is_Face_Italic(pFace))
429     flags |= FXFONT_ITALIC;
430   if (FT_IS_FIXED_WIDTH(pFace))
431     flags |= FXFONT_FIXED_PITCH;
432 
433   TT_OS2* pOS2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(pFace, ft_sfnt_os2));
434   if (!pOS2)
435     return flags;
436 
437   if (pOS2->ulCodePageRange1 & (1 << 31))
438     flags |= FXFONT_SYMBOLIC;
439   if (pOS2->panose[0] == 2) {
440     uint8_t uSerif = pOS2->panose[1];
441     if ((uSerif > 1 && uSerif < 10) || uSerif > 13)
442       flags |= FXFONT_SERIF;
443   }
444   return flags;
445 }
446 
CreateFontStream(CFX_FontMapper * pFontMapper,uint32_t index)447 RetainPtr<IFX_SeekableReadStream> CreateFontStream(
448     CFX_FontMapper* pFontMapper,
449     uint32_t index) {
450   size_t dwFileSize = 0;
451   std::unique_ptr<uint8_t, FxFreeDeleter> pBuffer =
452       pFontMapper->RawBytesForIndex(index, &dwFileSize);
453   if (!pBuffer)
454     return nullptr;
455 
456   return pdfium::MakeRetain<CFX_MemoryStream>(std::move(pBuffer), dwFileSize);
457 }
458 
CreateFontStream(const ByteString & bsFaceName)459 RetainPtr<IFX_SeekableReadStream> CreateFontStream(
460     const ByteString& bsFaceName) {
461   CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
462   CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper();
463   pFontMapper->LoadInstalledFonts();
464 
465   for (int32_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
466     if (pFontMapper->GetFaceName(i) == bsFaceName)
467       return CreateFontStream(pFontMapper, i);
468   }
469   return nullptr;
470 }
471 
LoadFace(const RetainPtr<IFX_SeekableReadStream> & pFontStream,int32_t iFaceIndex)472 RetainPtr<CFX_Face> LoadFace(
473     const RetainPtr<IFX_SeekableReadStream>& pFontStream,
474     int32_t iFaceIndex) {
475   if (!pFontStream)
476     return nullptr;
477 
478   CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
479   FXFT_LibraryRec* library = pFontMgr->GetFTLibrary();
480   if (!library)
481     return nullptr;
482 
483   // TODO(palmer): This memory will be freed with |ft_free| (which is |free|).
484   // Ultimately, we want to change this to:
485   //   FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1);
486   // https://bugs.chromium.org/p/pdfium/issues/detail?id=690
487   FXFT_StreamRec* ftStream =
488       static_cast<FXFT_StreamRec*>(ft_scalloc(sizeof(FXFT_StreamRec), 1));
489   memset(ftStream, 0, sizeof(FXFT_StreamRec));
490   ftStream->base = nullptr;
491   ftStream->descriptor.pointer = static_cast<void*>(pFontStream.Get());
492   ftStream->pos = 0;
493   ftStream->size = static_cast<unsigned long>(pFontStream->GetSize());
494   ftStream->read = ftStreamRead;
495   ftStream->close = ftStreamClose;
496 
497   FT_Open_Args ftArgs;
498   memset(&ftArgs, 0, sizeof(FT_Open_Args));
499   ftArgs.flags |= FT_OPEN_STREAM;
500   ftArgs.stream = ftStream;
501 
502   RetainPtr<CFX_Face> pFace = CFX_Face::Open(library, &ftArgs, iFaceIndex);
503   if (!pFace) {
504     ft_sfree(ftStream);
505     return nullptr;
506   }
507   FT_Set_Pixel_Sizes(pFace->GetRec(), 0, 64);
508   return pFace;
509 }
510 
VerifyUnicodeForFontDescriptor(CFX_FontDescriptor * pDesc,wchar_t wcUnicode)511 bool VerifyUnicodeForFontDescriptor(CFX_FontDescriptor* pDesc,
512                                     wchar_t wcUnicode) {
513   RetainPtr<IFX_SeekableReadStream> pFileRead =
514       CreateFontStream(pDesc->m_wsFaceName.ToUTF8());
515   if (!pFileRead)
516     return false;
517 
518   RetainPtr<CFX_Face> pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex);
519   if (!pFace)
520     return false;
521 
522   FT_Error retCharmap =
523       FXFT_Select_Charmap(pFace->GetRec(), FT_ENCODING_UNICODE);
524   FT_Error retIndex = FT_Get_Char_Index(pFace->GetRec(), wcUnicode);
525 
526   if (FXFT_Get_Face_External_Stream(pFace->GetRec()))
527     FXFT_Clear_Face_External_Stream(pFace->GetRec());
528 
529   return !retCharmap && retIndex;
530 }
531 
IsPartName(const WideString & name1,const WideString & name2)532 bool IsPartName(const WideString& name1, const WideString& name2) {
533   return name1.Contains(name2.AsStringView());
534 }
535 
CalcPenalty(CFX_FontDescriptor * pInstalled,uint16_t wCodePage,uint32_t dwFontStyles,const WideString & FontName,wchar_t wcUnicode)536 int32_t CalcPenalty(CFX_FontDescriptor* pInstalled,
537                     uint16_t wCodePage,
538                     uint32_t dwFontStyles,
539                     const WideString& FontName,
540                     wchar_t wcUnicode) {
541   int32_t nPenalty = 30000;
542   if (FontName.GetLength() != 0) {
543     if (FontName != pInstalled->m_wsFaceName) {
544       size_t i;
545       for (i = 0; i < pInstalled->m_wsFamilyNames.size(); ++i) {
546         if (pInstalled->m_wsFamilyNames[i] == FontName)
547           break;
548       }
549       if (i == pInstalled->m_wsFamilyNames.size())
550         nPenalty += 0xFFFF;
551       else
552         nPenalty -= 28000;
553     } else {
554       nPenalty -= 30000;
555     }
556     if (nPenalty == 30000 && !IsPartName(pInstalled->m_wsFaceName, FontName)) {
557       size_t i;
558       for (i = 0; i < pInstalled->m_wsFamilyNames.size(); i++) {
559         if (IsPartName(pInstalled->m_wsFamilyNames[i], FontName))
560           break;
561       }
562       if (i == pInstalled->m_wsFamilyNames.size())
563         nPenalty += 0xFFFF;
564       else
565         nPenalty -= 26000;
566     } else {
567       nPenalty -= 27000;
568     }
569   }
570   uint32_t dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles;
571   if (FontStyleIsForceBold(dwStyleMask))
572     nPenalty += 4500;
573   if (FontStyleIsFixedPitch(dwStyleMask))
574     nPenalty += 10000;
575   if (FontStyleIsItalic(dwStyleMask))
576     nPenalty += 10000;
577   if (FontStyleIsSerif(dwStyleMask))
578     nPenalty += 500;
579   if (FontStyleIsSymbolic(dwStyleMask))
580     nPenalty += 0xFFFF;
581   if (nPenalty >= 0xFFFF)
582     return 0xFFFF;
583 
584   uint16_t wBit = (wCodePage == FX_CODEPAGE_DefANSI || wCodePage == 0xFFFF)
585                       ? static_cast<uint16_t>(-1)
586                       : FX_GetCodePageBit(wCodePage);
587   if (wBit != static_cast<uint16_t>(-1)) {
588     ASSERT(wBit < 64);
589     if ((pInstalled->m_dwCsb[wBit / 32] & (1 << (wBit % 32))) == 0)
590       nPenalty += 0xFFFF;
591     else
592       nPenalty -= 60000;
593   }
594   wBit = (wcUnicode == 0 || wcUnicode == 0xFFFE) ? static_cast<uint16_t>(999)
595                                                  : FX_GetUnicodeBit(wcUnicode);
596   if (wBit != static_cast<uint16_t>(999)) {
597     ASSERT(wBit < 128);
598     if ((pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32))) == 0)
599       nPenalty += 0xFFFF;
600     else
601       nPenalty -= 60000;
602   }
603   return nPenalty;
604 }
605 
606 }  // namespace
607 
CFX_FontDescriptor()608 CFX_FontDescriptor::CFX_FontDescriptor()
609     : m_nFaceIndex(0), m_dwFontStyles(0), m_dwUsb(), m_dwCsb() {}
610 
~CFX_FontDescriptor()611 CFX_FontDescriptor::~CFX_FontDescriptor() {}
612 
CFGAS_FontMgr()613 CFGAS_FontMgr::CFGAS_FontMgr()
614     : m_pFontSource(pdfium::MakeUnique<CFX_FontSourceEnum_File>()) {}
615 
~CFGAS_FontMgr()616 CFGAS_FontMgr::~CFGAS_FontMgr() {}
617 
EnumFontsFromFontMapper()618 bool CFGAS_FontMgr::EnumFontsFromFontMapper() {
619   CFX_FontMapper* pFontMapper =
620       CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper();
621   pFontMapper->LoadInstalledFonts();
622 
623   for (int32_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
624     RetainPtr<IFX_SeekableReadStream> pFontStream =
625         CreateFontStream(pFontMapper, i);
626     if (!pFontStream)
627       continue;
628 
629     WideString wsFaceName =
630         WideString::FromDefANSI(pFontMapper->GetFaceName(i).AsStringView());
631     RegisterFaces(pFontStream, &wsFaceName);
632   }
633 
634   return !m_InstalledFonts.empty();
635 }
636 
EnumFontsFromFiles()637 bool CFGAS_FontMgr::EnumFontsFromFiles() {
638   m_pFontSource->GetNext();
639   while (m_pFontSource->HasNext()) {
640     RetainPtr<IFX_SeekableStream> stream = m_pFontSource->GetStream();
641     if (stream)
642       RegisterFaces(stream, nullptr);
643     m_pFontSource->GetNext();
644   }
645   return !m_InstalledFonts.empty();
646 }
647 
EnumFonts()648 bool CFGAS_FontMgr::EnumFonts() {
649   return EnumFontsFromFontMapper() || EnumFontsFromFiles();
650 }
651 
GetFontByUnicodeImpl(wchar_t wUnicode,uint32_t dwFontStyles,const wchar_t * pszFontFamily,uint32_t dwHash,uint16_t wCodePage,uint16_t)652 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicodeImpl(
653     wchar_t wUnicode,
654     uint32_t dwFontStyles,
655     const wchar_t* pszFontFamily,
656     uint32_t dwHash,
657     uint16_t wCodePage,
658     uint16_t /* wBitField */) {
659   std::vector<CFX_FontDescriptorInfo>* sortedFontInfos =
660       m_Hash2CandidateList[dwHash].get();
661   if (!sortedFontInfos) {
662     auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>();
663     sortedFontInfos = pNewFonts.get();
664     MatchFonts(sortedFontInfos, wCodePage, dwFontStyles,
665                WideString(pszFontFamily), wUnicode);
666     m_Hash2CandidateList[dwHash] = std::move(pNewFonts);
667   }
668   for (const auto& info : *sortedFontInfos) {
669     CFX_FontDescriptor* pDesc = info.pFont;
670     if (!VerifyUnicodeForFontDescriptor(pDesc, wUnicode))
671       continue;
672     RetainPtr<CFGAS_GEFont> pFont =
673         LoadFontInternal(pDesc->m_wsFaceName, pDesc->m_nFaceIndex);
674     if (!pFont)
675       continue;
676     pFont->SetLogicalFontStyle(dwFontStyles);
677     m_Hash2Fonts[dwHash].push_back(pFont);
678     return pFont;
679   }
680   if (!pszFontFamily)
681     m_FailedUnicodesSet.insert(wUnicode);
682   return nullptr;
683 }
684 
LoadFontInternal(const WideString & wsFaceName,int32_t iFaceIndex)685 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFontInternal(
686     const WideString& wsFaceName,
687     int32_t iFaceIndex) {
688   RetainPtr<IFX_SeekableReadStream> pFontStream =
689       CreateFontStream(wsFaceName.ToUTF8());
690   if (!pFontStream)
691     return nullptr;
692 
693   auto pInternalFont = pdfium::MakeUnique<CFX_Font>();
694   if (!pInternalFont->LoadFile(pFontStream, iFaceIndex))
695     return nullptr;
696 
697   RetainPtr<CFGAS_GEFont> pFont =
698       CFGAS_GEFont::LoadFont(std::move(pInternalFont), this);
699   if (!pFont)
700     return nullptr;
701 
702   m_IFXFont2FileRead[pFont] = pFontStream;
703   return pFont;
704 }
705 
MatchFonts(std::vector<CFX_FontDescriptorInfo> * pMatchedFonts,uint16_t wCodePage,uint32_t dwFontStyles,const WideString & FontName,wchar_t wcUnicode)706 void CFGAS_FontMgr::MatchFonts(
707     std::vector<CFX_FontDescriptorInfo>* pMatchedFonts,
708     uint16_t wCodePage,
709     uint32_t dwFontStyles,
710     const WideString& FontName,
711     wchar_t wcUnicode) {
712   pMatchedFonts->clear();
713   for (const auto& pFont : m_InstalledFonts) {
714     int32_t nPenalty =
715         CalcPenalty(pFont.get(), wCodePage, dwFontStyles, FontName, wcUnicode);
716     if (nPenalty >= 0xffff)
717       continue;
718     pMatchedFonts->push_back({pFont.get(), nPenalty});
719     if (pMatchedFonts->size() == 0xffff)
720       break;
721   }
722   std::sort(pMatchedFonts->begin(), pMatchedFonts->end());
723 }
724 
RegisterFace(RetainPtr<CFX_Face> pFace,const WideString * pFaceName)725 void CFGAS_FontMgr::RegisterFace(RetainPtr<CFX_Face> pFace,
726                                  const WideString* pFaceName) {
727   if ((pFace->GetRec()->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
728     return;
729 
730   auto pFont = pdfium::MakeUnique<CFX_FontDescriptor>();
731   pFont->m_dwFontStyles |= GetFlags(pFace->GetRec());
732 
733   GetUSBCSB(pFace->GetRec(), pFont->m_dwUsb, pFont->m_dwCsb);
734 
735   FT_ULong dwTag;
736   FT_ENC_TAG(dwTag, 'n', 'a', 'm', 'e');
737 
738   std::vector<uint8_t> table;
739   unsigned long nLength = 0;
740   unsigned int error =
741       FT_Load_Sfnt_Table(pFace->GetRec(), dwTag, 0, nullptr, &nLength);
742   if (error == 0 && nLength != 0) {
743     table.resize(nLength);
744     if (FT_Load_Sfnt_Table(pFace->GetRec(), dwTag, 0, table.data(), nullptr))
745       table.clear();
746   }
747   pFont->m_wsFamilyNames = GetNames(table.empty() ? nullptr : table.data());
748   pFont->m_wsFamilyNames.push_back(
749       WideString::FromUTF8(pFace->GetRec()->family_name));
750   pFont->m_wsFaceName =
751       pFaceName
752           ? *pFaceName
753           : WideString::FromDefANSI(FT_Get_Postscript_Name(pFace->GetRec()));
754   pFont->m_nFaceIndex = pFace->GetRec()->face_index;
755   m_InstalledFonts.push_back(std::move(pFont));
756 }
757 
RegisterFaces(const RetainPtr<IFX_SeekableReadStream> & pFontStream,const WideString * pFaceName)758 void CFGAS_FontMgr::RegisterFaces(
759     const RetainPtr<IFX_SeekableReadStream>& pFontStream,
760     const WideString* pFaceName) {
761   int32_t index = 0;
762   int32_t num_faces = 0;
763   do {
764     RetainPtr<CFX_Face> pFace = LoadFace(pFontStream, index++);
765     if (!pFace)
766       continue;
767     // All faces keep number of faces. It can be retrieved from any one face.
768     if (num_faces == 0)
769       num_faces = pFace->GetRec()->num_faces;
770     RegisterFace(pFace, pFaceName);
771     if (FXFT_Get_Face_External_Stream(pFace->GetRec()))
772       FXFT_Clear_Face_External_Stream(pFace->GetRec());
773   } while (index < num_faces);
774 }
775 
776 #endif  // defined(OS_WIN)
777 
GetFontByCodePage(uint16_t wCodePage,uint32_t dwFontStyles,const wchar_t * pszFontFamily)778 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage(
779     uint16_t wCodePage,
780     uint32_t dwFontStyles,
781     const wchar_t* pszFontFamily) {
782   ByteString bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles);
783   bsHash += FX_UTF8Encode(WideStringView(pszFontFamily));
784   uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false);
785   auto* pFontVector = &m_Hash2Fonts[dwHash];
786   if (!pFontVector->empty()) {
787     for (auto iter = pFontVector->begin(); iter != pFontVector->end(); ++iter) {
788       if (*iter != nullptr)
789         return *iter;
790     }
791     return nullptr;
792   }
793 
794 #if defined(OS_WIN)
795   const FX_FONTDESCRIPTOR* pFD =
796       FindFont(pszFontFamily, dwFontStyles, true, wCodePage, 999, 0);
797   if (!pFD)
798     pFD = FindFont(nullptr, dwFontStyles, true, wCodePage, 999, 0);
799   if (!pFD)
800     pFD = FindFont(nullptr, dwFontStyles, false, wCodePage, 999, 0);
801   if (!pFD)
802     return nullptr;
803 
804   RetainPtr<CFGAS_GEFont> pFont =
805       CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
806 #else   // defined(OS_WIN)
807   std::vector<CFX_FontDescriptorInfo>* sortedFontInfos =
808       m_Hash2CandidateList[dwHash].get();
809   if (!sortedFontInfos) {
810     auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>();
811     sortedFontInfos = pNewFonts.get();
812     MatchFonts(sortedFontInfos, wCodePage, dwFontStyles,
813                WideString(pszFontFamily), 0);
814     m_Hash2CandidateList[dwHash] = std::move(pNewFonts);
815   }
816   if (sortedFontInfos->empty())
817     return nullptr;
818 
819   CFX_FontDescriptor* pDesc = (*sortedFontInfos)[0].pFont;
820   RetainPtr<CFGAS_GEFont> pFont =
821       LoadFontInternal(pDesc->m_wsFaceName, pDesc->m_nFaceIndex);
822 #endif  // defined(OS_WIN)
823 
824   if (!pFont)
825     return nullptr;
826 
827   pFont->SetLogicalFontStyle(dwFontStyles);
828   pFontVector->push_back(pFont);
829   return pFont;
830 }
831 
GetFontByUnicode(wchar_t wUnicode,uint32_t dwFontStyles,const wchar_t * pszFontFamily)832 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode(
833     wchar_t wUnicode,
834     uint32_t dwFontStyles,
835     const wchar_t* pszFontFamily) {
836   if (pdfium::ContainsKey(m_FailedUnicodesSet, wUnicode))
837     return nullptr;
838 
839   const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode);
840   uint16_t wCodePage = x ? x->wCodePage : 0xFFFF;
841   uint16_t wBitField = x ? x->wBitField : 0x03E7;
842   ByteString bsHash;
843   if (wCodePage == 0xFFFF) {
844     bsHash =
845         ByteString::Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles);
846   } else {
847     bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles);
848   }
849   bsHash += FX_UTF8Encode(WideStringView(pszFontFamily));
850   uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false);
851   std::vector<RetainPtr<CFGAS_GEFont>>& fonts = m_Hash2Fonts[dwHash];
852   for (auto& pFont : fonts) {
853     if (VerifyUnicode(pFont, wUnicode))
854       return pFont;
855   }
856 
857   return GetFontByUnicodeImpl(wUnicode, dwFontStyles, pszFontFamily, dwHash,
858                               wCodePage, wBitField);
859 }
860 
LoadFont(const wchar_t * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)861 RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont(const wchar_t* pszFontFamily,
862                                                 uint32_t dwFontStyles,
863                                                 uint16_t wCodePage) {
864 #if defined(OS_WIN)
865   ByteString bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles);
866   bsHash += FX_UTF8Encode(WideStringView(pszFontFamily));
867   uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false);
868   std::vector<RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash];
869   if (!pFontArray->empty())
870     return (*pFontArray)[0];
871 
872   const FX_FONTDESCRIPTOR* pFD =
873       FindFont(pszFontFamily, dwFontStyles, true, wCodePage, 999, 0);
874   if (!pFD)
875     pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage, 999, 0);
876   if (!pFD)
877     return nullptr;
878 
879   RetainPtr<CFGAS_GEFont> pFont =
880       CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
881   if (!pFont)
882     return nullptr;
883 
884   pFont->SetLogicalFontStyle(dwFontStyles);
885   pFontArray->push_back(pFont);
886   return pFont;
887 #else   // defined(OS_WIN)
888   return GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
889 #endif  // defined(OS_WIN)
890 }
891 
RemoveFont(const RetainPtr<CFGAS_GEFont> & pEFont)892 void CFGAS_FontMgr::RemoveFont(const RetainPtr<CFGAS_GEFont>& pEFont) {
893   if (!pEFont)
894     return;
895 
896 #if !defined(OS_WIN)
897   m_IFXFont2FileRead.erase(pEFont);
898 #endif
899 
900   auto iter = m_Hash2Fonts.begin();
901   while (iter != m_Hash2Fonts.end()) {
902     auto old_iter = iter++;
903     bool all_empty = true;
904     for (size_t i = 0; i < old_iter->second.size(); i++) {
905       if (old_iter->second[i] == pEFont)
906         old_iter->second[i].Reset();
907       else if (old_iter->second[i])
908         all_empty = false;
909     }
910     if (all_empty)
911       m_Hash2Fonts.erase(old_iter);
912   }
913 }
914