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