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(¶ms, 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(¶ms, 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(¶ms, 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