Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfgas_fontmgr.cpp
Go to the documentation of this file.
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_size_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/fxcrt/span_util.h"
25#include "core/fxge/cfx_font.h"
26#include "core/fxge/cfx_fontmapper.h"
27#include "core/fxge/cfx_fontmgr.h"
28#include "core/fxge/cfx_gemodule.h"
29#include "core/fxge/fx_font.h"
30#include "core/fxge/fx_fontencoding.h"
31#include "third_party/base/check.h"
32#include "third_party/base/containers/contains.h"
33#include "third_party/base/containers/span.h"
34#include "third_party/base/numerics/safe_conversions.h"
35#include "xfa/fgas/font/cfgas_gefont.h"
36#include "xfa/fgas/font/fgas_fontutils.h"
37
38namespace {
39
40bool VerifyUnicode(const RetainPtr<CFGAS_GEFont>& pFont, wchar_t wcUnicode) {
41 RetainPtr<CFX_Face> pFace = pFont->GetDevFont()->GetFace();
42 if (!pFace)
43 return false;
44
45 CFX_Face::CharMap charmap = pFace->GetCurrentCharMap();
46 if (!pFace->SelectCharMap(fxge::FontEncoding::kUnicode)) {
47 return false;
48 }
49
50 if (pFace->GetCharIndex(wcUnicode) == 0) {
51 pFace->SetCharMap(charmap);
52 return false;
53 }
54 return true;
55}
56
57uint32_t ShortFormHash(FX_CodePage wCodePage,
58 uint32_t dwFontStyles,
59 WideStringView wsFontFamily) {
60 ByteString bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles);
61 bsHash += FX_UTF8Encode(wsFontFamily);
62 return FX_HashCode_GetA(bsHash.AsStringView());
63}
64
65uint32_t LongFormHash(FX_CodePage wCodePage,
66 uint16_t wBitField,
67 uint32_t dwFontStyles,
68 WideStringView wsFontFamily) {
69 ByteString bsHash =
70 ByteString::Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles);
71 bsHash += FX_UTF8Encode(wsFontFamily);
72 return FX_HashCode_GetA(bsHash.AsStringView());
73}
74
75} // namespace
76
77#if BUILDFLAG(IS_WIN)
78
79namespace {
80
81struct FX_FONTMATCHPARAMS {
82 const wchar_t* pwsFamily;
83 uint32_t dwFontStyles;
84 uint32_t dwUSB;
85 bool matchParagraphStyle;
86 wchar_t wUnicode;
87 FX_CodePage wCodePage;
88};
89
90int32_t GetSimilarityScore(FX_FONTDESCRIPTOR const* pFont,
91 uint32_t dwFontStyles) {
92 int32_t iValue = 0;
93 if (FontStyleIsSymbolic(dwFontStyles) ==
94 FontStyleIsSymbolic(pFont->dwFontStyles)) {
95 iValue += 64;
96 }
97 if (FontStyleIsFixedPitch(dwFontStyles) ==
98 FontStyleIsFixedPitch(pFont->dwFontStyles)) {
99 iValue += 32;
100 }
101 if (FontStyleIsSerif(dwFontStyles) == FontStyleIsSerif(pFont->dwFontStyles))
102 iValue += 16;
103 if (FontStyleIsScript(dwFontStyles) == FontStyleIsScript(pFont->dwFontStyles))
104 iValue += 8;
105 return iValue;
106}
107
108const FX_FONTDESCRIPTOR* MatchDefaultFont(
109 FX_FONTMATCHPARAMS* pParams,
110 const std::deque<FX_FONTDESCRIPTOR>& fonts) {
111 const FX_FONTDESCRIPTOR* pBestFont = nullptr;
112 int32_t iBestSimilar = 0;
113 for (const auto& font : fonts) {
114 if (FontStyleIsForceBold(font.dwFontStyles) &&
115 FontStyleIsItalic(font.dwFontStyles)) {
116 continue;
117 }
118
119 if (pParams->pwsFamily) {
120 if (FXSYS_wcsicmp(pParams->pwsFamily, font.wsFontFace))
121 continue;
122 if (font.uCharSet == FX_Charset::kSymbol)
123 return &font;
124 }
125 if (font.uCharSet == FX_Charset::kSymbol)
126 continue;
127 if (pParams->wCodePage != FX_CodePage::kFailure) {
128 if (FX_GetCodePageFromCharset(font.uCharSet) != pParams->wCodePage)
129 continue;
130 } else {
131 if (pParams->dwUSB < 128) {
132 uint32_t dwByte = pParams->dwUSB / 32;
133 uint32_t dwUSB = 1 << (pParams->dwUSB % 32);
134 if ((font.FontSignature.fsUsb[dwByte] & dwUSB) == 0)
135 continue;
136 }
137 }
138 if (pParams->matchParagraphStyle) {
139 if ((font.dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F))
140 return &font;
141 continue;
142 }
143 if (pParams->pwsFamily) {
144 if (FXSYS_wcsicmp(pParams->pwsFamily, font.wsFontFace) == 0)
145 return &font;
146 }
147 int32_t iSimilarValue = GetSimilarityScore(&font, pParams->dwFontStyles);
148 if (iBestSimilar < iSimilarValue) {
149 iBestSimilar = iSimilarValue;
150 pBestFont = &font;
151 }
152 }
153 return iBestSimilar < 1 ? nullptr : pBestFont;
154}
155
156uint32_t GetGdiFontStyles(const LOGFONTW& lf) {
157 uint32_t dwStyles = 0;
158 if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH)
159 dwStyles |= FXFONT_FIXED_PITCH;
160 uint8_t nFamilies = lf.lfPitchAndFamily & 0xF0;
161 if (nFamilies == FF_ROMAN)
162 dwStyles |= FXFONT_SERIF;
163 if (nFamilies == FF_SCRIPT)
164 dwStyles |= FXFONT_SCRIPT;
165 if (lf.lfCharSet == SYMBOL_CHARSET)
166 dwStyles |= FXFONT_SYMBOLIC;
167 return dwStyles;
168}
169
170int32_t CALLBACK GdiFontEnumProc(ENUMLOGFONTEX* lpelfe,
171 NEWTEXTMETRICEX* lpntme,
172 DWORD dwFontType,
173 LPARAM lParam) {
174 if (dwFontType != TRUETYPE_FONTTYPE)
175 return 1;
176 const LOGFONTW& lf = ((LPENUMLOGFONTEXW)lpelfe)->elfLogFont;
177 if (lf.lfFaceName[0] == L'@')
178 return 1;
179 FX_FONTDESCRIPTOR font;
180 memset(&font, 0, sizeof(FX_FONTDESCRIPTOR));
181 font.uCharSet = FX_GetCharsetFromInt(lf.lfCharSet);
182 font.dwFontStyles = GetGdiFontStyles(lf);
183 FXSYS_wcsncpy(font.wsFontFace, (const wchar_t*)lf.lfFaceName, 31);
184 font.wsFontFace[31] = 0;
185 memcpy(&font.FontSignature, &lpntme->ntmFontSig, sizeof(lpntme->ntmFontSig));
186 reinterpret_cast<std::deque<FX_FONTDESCRIPTOR>*>(lParam)->push_back(font);
187 return 1;
188}
189
190std::deque<FX_FONTDESCRIPTOR> EnumGdiFonts(const wchar_t* pwsFaceName,
191 wchar_t wUnicode) {
192 std::deque<FX_FONTDESCRIPTOR> fonts;
193 LOGFONTW lfFind;
194 memset(&lfFind, 0, sizeof(lfFind));
195 lfFind.lfCharSet = DEFAULT_CHARSET;
196 if (pwsFaceName) {
197 FXSYS_wcsncpy(lfFind.lfFaceName, pwsFaceName, 31);
198 lfFind.lfFaceName[31] = 0;
199 }
200 HDC hDC = ::GetDC(nullptr);
201 EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind, (FONTENUMPROCW)GdiFontEnumProc,
202 (LPARAM)&fonts, 0);
203 ::ReleaseDC(nullptr, hDC);
204 return fonts;
205}
206
207} // namespace
208
209CFGAS_FontMgr::CFGAS_FontMgr() : m_FontFaces(EnumGdiFonts(nullptr, 0xFEFF)) {}
210
211CFGAS_FontMgr::~CFGAS_FontMgr() = default;
212
213bool CFGAS_FontMgr::EnumFonts() {
214 return true;
215}
216
217RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicodeImpl(
218 wchar_t wUnicode,
219 uint32_t dwFontStyles,
220 const wchar_t* pszFontFamily,
221 uint32_t dwHash,
222 FX_CodePage wCodePage,
223 uint16_t wBitField) {
224 const FX_FONTDESCRIPTOR* pFD = FindFont(pszFontFamily, dwFontStyles, false,
225 wCodePage, wBitField, wUnicode);
226 if (!pFD && pszFontFamily) {
227 pFD =
228 FindFont(nullptr, dwFontStyles, false, wCodePage, wBitField, wUnicode);
229 }
230 if (!pFD)
231 return nullptr;
232
233 FX_CodePage newCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
234 RetainPtr<CFGAS_GEFont> pFont =
235 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, newCodePage);
236 if (!pFont)
237 return nullptr;
238
239 pFont->SetLogicalFontStyle(dwFontStyles);
240 if (!VerifyUnicode(pFont, wUnicode)) {
241 m_FailedUnicodesSet.insert(wUnicode);
242 return nullptr;
243 }
244
245 m_Hash2Fonts[dwHash].push_back(pFont);
246 return pFont;
247}
248
249const FX_FONTDESCRIPTOR* CFGAS_FontMgr::FindFont(const wchar_t* pszFontFamily,
250 uint32_t dwFontStyles,
251 bool matchParagraphStyle,
252 FX_CodePage wCodePage,
253 uint32_t dwUSB,
254 wchar_t wUnicode) {
255 FX_FONTMATCHPARAMS params;
256 memset(&params, 0, sizeof(params));
257 params.dwUSB = dwUSB;
258 params.wUnicode = wUnicode;
259 params.wCodePage = wCodePage;
260 params.pwsFamily = pszFontFamily;
261 params.dwFontStyles = dwFontStyles;
262 params.matchParagraphStyle = matchParagraphStyle;
263
264 const FX_FONTDESCRIPTOR* pDesc = MatchDefaultFont(&params, m_FontFaces);
265 if (pDesc)
266 return pDesc;
267
268 if (!pszFontFamily)
269 return nullptr;
270
271 // Use a named object to store the returned value of EnumGdiFonts() instead
272 // of using a temporary object. This can prevent use-after-free issues since
273 // pDesc may point to one of std::deque object's elements.
274 std::deque<FX_FONTDESCRIPTOR> namedFonts =
275 EnumGdiFonts(pszFontFamily, wUnicode);
276 params.pwsFamily = nullptr;
277 pDesc = MatchDefaultFont(&params, namedFonts);
278 if (!pDesc)
279 return nullptr;
280
281 auto it = std::find(m_FontFaces.rbegin(), m_FontFaces.rend(), *pDesc);
282 if (it != m_FontFaces.rend())
283 return &*it;
284
285 m_FontFaces.push_back(*pDesc);
286 return &m_FontFaces.back();
287}
288
289#else // BUILDFLAG(IS_WIN)
290
291namespace {
292
357
358uint16_t FX_GetCodePageBit(FX_CodePage wCodePage) {
359 for (size_t i = 0; i < std::size(kCodePages); ++i) {
360 if (kCodePages[i] == wCodePage)
361 return static_cast<uint16_t>(i);
362 }
363 return static_cast<uint16_t>(-1);
364}
365
366uint16_t FX_GetUnicodeBit(wchar_t wcUnicode) {
367 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wcUnicode);
369}
370
371uint16_t ReadUInt16FromSpanAtOffset(pdfium::span<const uint8_t> data,
372 size_t offset) {
373 const uint8_t* p = &data[offset];
374 return FXSYS_UINT16_GET_MSBFIRST(p);
375}
376
377extern "C" {
378
379unsigned long ftStreamRead(FXFT_StreamRec* stream,
380 unsigned long offset,
381 unsigned char* buffer,
382 unsigned long count) {
383 if (count == 0)
384 return 0;
385
387 static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
388 if (!pFile->ReadBlockAtOffset({buffer, count}, offset))
389 return 0;
390
391 return count;
392}
393
394void ftStreamClose(FXFT_StreamRec* stream) {}
395
396} // extern "C"
397
398std::vector<WideString> GetNames(pdfium::span<const uint8_t> name_table) {
399 std::vector<WideString> results;
400 if (name_table.empty())
401 return results;
402
403 uint16_t nNameCount = ReadUInt16FromSpanAtOffset(name_table, 2);
404 pdfium::span<const uint8_t> str =
405 name_table.subspan(ReadUInt16FromSpanAtOffset(name_table, 4));
406 pdfium::span<const uint8_t> name_record = name_table.subspan(6);
407 for (uint16_t i = 0; i < nNameCount; ++i) {
408 uint16_t nNameID = ReadUInt16FromSpanAtOffset(name_table, i * 12 + 6);
409 if (nNameID != 1)
410 continue;
411
412 uint16_t nPlatformID = ReadUInt16FromSpanAtOffset(name_record, i * 12);
413 uint16_t nNameLength = ReadUInt16FromSpanAtOffset(name_record, i * 12 + 8);
414 uint16_t nNameOffset = ReadUInt16FromSpanAtOffset(name_record, i * 12 + 10);
415 if (nPlatformID != 1) {
416 WideString wsFamily;
417 for (uint16_t j = 0; j < nNameLength / 2; ++j) {
418 wchar_t wcTemp = ReadUInt16FromSpanAtOffset(str, nNameOffset + j * 2);
419 wsFamily += wcTemp;
420 }
421 results.push_back(wsFamily);
422 continue;
423 }
424
425 WideString wsFamily;
426 for (uint16_t j = 0; j < nNameLength; ++j) {
427 wchar_t wcTemp = str[nNameOffset + j];
428 wsFamily += wcTemp;
429 }
430 results.push_back(wsFamily);
431 }
432 return results;
433}
434
435uint32_t GetFlags(const RetainPtr<CFX_Face>& face) {
436 uint32_t flags = 0;
437 if (face->IsBold()) {
438 flags |= FXFONT_FORCE_BOLD;
439 }
440 if (face->IsItalic()) {
441 flags |= FXFONT_ITALIC;
442 }
443 if (face->IsFixedWidth()) {
444 flags |= FXFONT_FIXED_PITCH;
445 }
446
447 absl::optional<std::array<uint32_t, 2>> code_page_range =
448 face->GetOs2CodePageRange();
449 if (code_page_range.has_value() && (code_page_range.value()[0] & (1 << 31))) {
450 flags |= FXFONT_SYMBOLIC;
451 }
452
453 absl::optional<std::array<uint8_t, 2>> panose = face->GetOs2Panose();
454 if (panose.has_value() && panose.value()[0] == 2) {
455 uint8_t serif = panose.value()[1];
456 if ((serif > 1 && serif < 10) || serif > 13) {
457 flags |= FXFONT_SERIF;
458 }
459 }
460 return flags;
461}
462
463RetainPtr<IFX_SeekableReadStream> CreateFontStream(CFX_FontMapper* pFontMapper,
464 size_t index) {
465 FixedSizeDataVector<uint8_t> buffer = pFontMapper->RawBytesForIndex(index);
466 if (buffer.empty()) {
467 return nullptr;
468 }
469 return pdfium::MakeRetain<CFX_ReadOnlyVectorStream>(std::move(buffer));
470}
471
472RetainPtr<IFX_SeekableReadStream> CreateFontStream(
473 const ByteString& bsFaceName) {
475 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper();
476 pFontMapper->LoadInstalledFonts();
477
478 for (size_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
479 if (pFontMapper->GetFaceName(i) == bsFaceName)
480 return CreateFontStream(pFontMapper, i);
481 }
482 return nullptr;
483}
484
485RetainPtr<CFX_Face> LoadFace(
486 const RetainPtr<IFX_SeekableReadStream>& pFontStream,
487 int32_t iFaceIndex) {
488 if (!pFontStream)
489 return nullptr;
490
492 FXFT_LibraryRec* library = pFontMgr->GetFTLibrary();
493 if (!library)
494 return nullptr;
495
496 // TODO(palmer): This memory will be freed with |ft_free| (which is |free|).
497 // Ultimately, we want to change this to:
498 // FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1);
499 // https://bugs.chromium.org/p/pdfium/issues/detail?id=690
500 FXFT_StreamRec* ftStream =
501 static_cast<FXFT_StreamRec*>(ft_scalloc(sizeof(FXFT_StreamRec), 1));
502 memset(ftStream, 0, sizeof(FXFT_StreamRec));
503 ftStream->base = nullptr;
504 ftStream->descriptor.pointer = static_cast<void*>(pFontStream.Get());
505 ftStream->pos = 0;
506 ftStream->size = static_cast<unsigned long>(pFontStream->GetSize());
507 ftStream->read = ftStreamRead;
508 ftStream->close = ftStreamClose;
509
510 FT_Open_Args ftArgs;
511 memset(&ftArgs, 0, sizeof(FT_Open_Args));
512 ftArgs.flags |= FT_OPEN_STREAM;
513 ftArgs.stream = ftStream;
514
515 RetainPtr<CFX_Face> pFace = CFX_Face::Open(library, &ftArgs, iFaceIndex);
516 if (!pFace) {
517 ft_sfree(ftStream);
518 return nullptr;
519 }
520 FT_Set_Pixel_Sizes(pFace->GetRec(), 0, 64);
521 return pFace;
522}
523
524bool VerifyUnicodeForFontDescriptor(CFGAS_FontDescriptor* pDesc,
525 wchar_t wcUnicode) {
527 CreateFontStream(pDesc->m_wsFaceName.ToUTF8());
528 if (!pFileRead)
529 return false;
530
531 RetainPtr<CFX_Face> pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex);
532 if (!pFace)
533 return false;
534
535 bool select_charmap_result =
536 pFace->SelectCharMap(fxge::FontEncoding::kUnicode);
537 int ret_index = pFace->GetCharIndex(wcUnicode);
538
539 pFace->ClearExternalStream();
540
541 return select_charmap_result && ret_index;
542}
543
544bool IsPartName(const WideString& name1, const WideString& name2) {
545 return name1.Contains(name2.AsStringView());
546}
547
548int32_t CalcPenalty(CFGAS_FontDescriptor* pInstalled,
549 FX_CodePage wCodePage,
550 uint32_t dwFontStyles,
551 const WideString& FontName,
552 wchar_t wcUnicode) {
553 int32_t nPenalty = 30000;
554 if (FontName.GetLength() != 0) {
555 if (FontName != pInstalled->m_wsFaceName) {
556 size_t i;
557 for (i = 0; i < pInstalled->m_wsFamilyNames.size(); ++i) {
558 if (pInstalled->m_wsFamilyNames[i] == FontName)
559 break;
560 }
561 if (i == pInstalled->m_wsFamilyNames.size())
562 nPenalty += 0xFFFF;
563 else
564 nPenalty -= 28000;
565 } else {
566 nPenalty -= 30000;
567 }
568 if (nPenalty == 30000 && !IsPartName(pInstalled->m_wsFaceName, FontName)) {
569 size_t i;
570 for (i = 0; i < pInstalled->m_wsFamilyNames.size(); i++) {
571 if (IsPartName(pInstalled->m_wsFamilyNames[i], FontName))
572 break;
573 }
574 if (i == pInstalled->m_wsFamilyNames.size())
575 nPenalty += 0xFFFF;
576 else
577 nPenalty -= 26000;
578 } else {
579 nPenalty -= 27000;
580 }
581 }
582 uint32_t dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles;
583 if (FontStyleIsForceBold(dwStyleMask))
584 nPenalty += 4500;
585 if (FontStyleIsFixedPitch(dwStyleMask))
586 nPenalty += 10000;
587 if (FontStyleIsItalic(dwStyleMask))
588 nPenalty += 10000;
589 if (FontStyleIsSerif(dwStyleMask))
590 nPenalty += 500;
591 if (FontStyleIsSymbolic(dwStyleMask))
592 nPenalty += 0xFFFF;
593 if (nPenalty >= 0xFFFF)
594 return 0xFFFF;
595
596 uint16_t wBit =
597 (wCodePage == FX_CodePage::kDefANSI || wCodePage == FX_CodePage::kFailure)
598 ? static_cast<uint16_t>(-1)
599 : FX_GetCodePageBit(wCodePage);
600 if (wBit != static_cast<uint16_t>(-1)) {
601 DCHECK(wBit < 64);
602 if ((pInstalled->m_dwCsb[wBit / 32] & (1 << (wBit % 32))) == 0)
603 nPenalty += 0xFFFF;
604 else
605 nPenalty -= 60000;
606 }
607 wBit = (wcUnicode == 0 || wcUnicode == 0xFFFE) ? FGAS_FONTUSB::kNoBitField
608 : FX_GetUnicodeBit(wcUnicode);
609 if (wBit != FGAS_FONTUSB::kNoBitField) {
610 DCHECK(wBit < 128);
611 if ((pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32))) == 0)
612 nPenalty += 0xFFFF;
613 else
614 nPenalty -= 60000;
615 }
616 return nPenalty;
617}
618
619} // namespace
620
622
624
625CFGAS_FontMgr::CFGAS_FontMgr() = default;
626
627CFGAS_FontMgr::~CFGAS_FontMgr() = default;
628
629bool CFGAS_FontMgr::EnumFontsFromFontMapper() {
630 CFX_FontMapper* pFontMapper =
632 pFontMapper->LoadInstalledFonts();
633
634 for (size_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
635 RetainPtr<IFX_SeekableReadStream> pFontStream =
636 CreateFontStream(pFontMapper, i);
637 if (!pFontStream)
638 continue;
639
640 WideString wsFaceName =
641 WideString::FromDefANSI(pFontMapper->GetFaceName(i).AsStringView());
642 RegisterFaces(pFontStream, wsFaceName);
643 }
644
645 return !m_InstalledFonts.empty();
646}
647
649 return EnumFontsFromFontMapper();
650}
651
652RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicodeImpl(
653 wchar_t wUnicode,
654 uint32_t dwFontStyles,
655 const wchar_t* pszFontFamily,
656 uint32_t dwHash,
657 FX_CodePage wCodePage,
658 uint16_t /* wBitField*/) {
659 if (!pdfium::Contains(m_Hash2CandidateList, dwHash)) {
660 m_Hash2CandidateList[dwHash] =
661 MatchFonts(wCodePage, dwFontStyles, pszFontFamily, wUnicode);
662 }
663 for (const auto& info : m_Hash2CandidateList[dwHash]) {
664 CFGAS_FontDescriptor* pDesc = info.pFont;
665 if (!VerifyUnicodeForFontDescriptor(pDesc, wUnicode))
666 continue;
667 RetainPtr<CFGAS_GEFont> pFont =
668 LoadFontInternal(pDesc->m_wsFaceName, pDesc->m_nFaceIndex);
669 if (!pFont)
670 continue;
671 pFont->SetLogicalFontStyle(dwFontStyles);
672 m_Hash2Fonts[dwHash].push_back(pFont);
673 return pFont;
674 }
675 if (!pszFontFamily)
676 m_FailedUnicodesSet.insert(wUnicode);
677 return nullptr;
678}
679
680RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFontInternal(
681 const WideString& wsFaceName,
682 int32_t iFaceIndex) {
683 RetainPtr<IFX_SeekableReadStream> pFontStream =
684 CreateFontStream(wsFaceName.ToUTF8());
685 if (!pFontStream)
686 return nullptr;
687
688 auto pInternalFont = std::make_unique<CFX_Font>();
689 if (!pInternalFont->LoadFile(std::move(pFontStream), iFaceIndex))
690 return nullptr;
691
692 return CFGAS_GEFont::LoadFont(std::move(pInternalFont));
693}
694
695std::vector<CFGAS_FontDescriptorInfo> CFGAS_FontMgr::MatchFonts(
696 FX_CodePage wCodePage,
697 uint32_t dwFontStyles,
698 const WideString& FontName,
699 wchar_t wcUnicode) {
700 std::vector<CFGAS_FontDescriptorInfo> matched_fonts;
701 for (const auto& pFont : m_InstalledFonts) {
702 int32_t nPenalty =
703 CalcPenalty(pFont.get(), wCodePage, dwFontStyles, FontName, wcUnicode);
704 if (nPenalty >= 0xffff)
705 continue;
706 matched_fonts.push_back({pFont.get(), nPenalty});
707 if (matched_fonts.size() == 0xffff)
708 break;
709 }
710 std::stable_sort(matched_fonts.begin(), matched_fonts.end());
711 return matched_fonts;
712}
713
714void CFGAS_FontMgr::RegisterFace(RetainPtr<CFX_Face> pFace,
715 const WideString& wsFaceName) {
716 if (!pFace->IsScalable()) {
717 return;
718 }
719
720 auto pFont = std::make_unique<CFGAS_FontDescriptor>();
721 pFont->m_dwFontStyles |= GetFlags(pFace);
722
723 // TODO(crbug.com/pdfium/2085): Use make_span() in fewer places after updating
724 // pdfium::span.
725 absl::optional<std::array<uint32_t, 4>> unicode_range =
726 pFace->GetOs2UnicodeRange();
727 auto usb_span = pdfium::make_span(pFont->m_dwUsb);
728 if (unicode_range.has_value()) {
729 fxcrt::spancpy(usb_span, pdfium::make_span(unicode_range.value()));
730 } else {
731 fxcrt::spanclr(usb_span);
732 }
733
734 absl::optional<std::array<uint32_t, 2>> code_page_range =
735 pFace->GetOs2CodePageRange();
736 auto csb_span = pdfium::make_span(pFont->m_dwCsb);
737 if (code_page_range.has_value()) {
738 fxcrt::spancpy(csb_span, pdfium::make_span(code_page_range.value()));
739 } else {
740 fxcrt::spanclr(csb_span);
741 }
742
743 static constexpr uint32_t kNameTag =
744 CFX_FontMapper::MakeTag('n', 'a', 'm', 'e');
745
746 DataVector<uint8_t> table;
747 size_t table_size = pFace->GetSfntTable(kNameTag, table);
748 if (table_size) {
749 table.resize(table_size);
750 if (!pFace->GetSfntTable(kNameTag, table)) {
751 table.clear();
752 }
753 }
754 pFont->m_wsFamilyNames = GetNames(table);
755 pFont->m_wsFamilyNames.push_back(
756 WideString::FromUTF8(pFace->GetRec()->family_name));
757 pFont->m_wsFaceName = wsFaceName;
758 pFont->m_nFaceIndex =
759 pdfium::base::checked_cast<int32_t>(pFace->GetRec()->face_index);
760 m_InstalledFonts.push_back(std::move(pFont));
761}
762
763void CFGAS_FontMgr::RegisterFaces(
764 const RetainPtr<IFX_SeekableReadStream>& pFontStream,
765 const WideString& wsFaceName) {
766 int32_t index = 0;
767 int32_t num_faces = 0;
768 do {
769 RetainPtr<CFX_Face> pFace = LoadFace(pFontStream, index++);
770 if (!pFace)
771 continue;
772 // All faces keep number of faces. It can be retrieved from any one face.
773 if (num_faces == 0) {
774 num_faces =
775 pdfium::base::checked_cast<int32_t>(pFace->GetRec()->num_faces);
776 }
777 RegisterFace(pFace, wsFaceName);
778 pFace->ClearExternalStream();
779 } while (index < num_faces);
780}
781
782#endif // BUILDFLAG(IS_WIN)
783
785 FX_CodePage wCodePage,
786 uint32_t dwFontStyles,
787 const wchar_t* pszFontFamily) {
788 uint32_t dwHash = ShortFormHash(wCodePage, dwFontStyles, pszFontFamily);
789 auto* pFontVector = &m_Hash2Fonts[dwHash];
790 if (!pFontVector->empty()) {
791 for (auto iter = pFontVector->begin(); iter != pFontVector->end(); ++iter) {
792 if (*iter != nullptr)
793 return *iter;
794 }
795 return nullptr;
796 }
797
798#if BUILDFLAG(IS_WIN)
799 const FX_FONTDESCRIPTOR* pFD =
800 FindFont(pszFontFamily, dwFontStyles, true, wCodePage,
801 FGAS_FONTUSB::kNoBitField, 0);
802 if (!pFD) {
803 pFD = FindFont(nullptr, dwFontStyles, true, wCodePage,
804 FGAS_FONTUSB::kNoBitField, 0);
805 }
806 if (!pFD) {
807 pFD = FindFont(nullptr, dwFontStyles, false, wCodePage,
808 FGAS_FONTUSB::kNoBitField, 0);
809 }
810 if (!pFD)
811 return nullptr;
812
813 RetainPtr<CFGAS_GEFont> pFont =
814 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage);
815#else // BUILDFLAG(IS_WIN)
816 if (!pdfium::Contains(m_Hash2CandidateList, dwHash)) {
817 m_Hash2CandidateList[dwHash] =
818 MatchFonts(wCodePage, dwFontStyles, WideString(pszFontFamily), 0);
819 }
820 if (m_Hash2CandidateList[dwHash].empty())
821 return nullptr;
822
823 CFGAS_FontDescriptor* pDesc = m_Hash2CandidateList[dwHash].front().pFont;
824 RetainPtr<CFGAS_GEFont> pFont =
825 LoadFontInternal(pDesc->m_wsFaceName, pDesc->m_nFaceIndex);
826#endif // BUILDFLAG(IS_WIN)
827
828 if (!pFont)
829 return nullptr;
830
831 pFont->SetLogicalFontStyle(dwFontStyles);
832 pFontVector->push_back(pFont);
833 return pFont;
834}
835
837 wchar_t wUnicode,
838 uint32_t dwFontStyles,
839 const wchar_t* pszFontFamily) {
840 if (pdfium::Contains(m_FailedUnicodesSet, wUnicode))
841 return nullptr;
842
843 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode);
845 uint16_t wBitField = x ? x->wBitField : FGAS_FONTUSB::kNoBitField;
846 uint32_t dwHash =
847 wCodePage == FX_CodePage::kFailure
848 ? LongFormHash(wCodePage, wBitField, dwFontStyles, pszFontFamily)
849 : ShortFormHash(wCodePage, dwFontStyles, pszFontFamily);
850 for (auto& pFont : m_Hash2Fonts[dwHash]) {
851 if (VerifyUnicode(pFont, wUnicode))
852 return pFont;
853 }
854 return GetFontByUnicodeImpl(wUnicode, dwFontStyles, pszFontFamily, dwHash,
855 wCodePage, wBitField);
856}
857
858RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont(const wchar_t* pszFontFamily,
859 uint32_t dwFontStyles,
860 FX_CodePage wCodePage) {
861#if BUILDFLAG(IS_WIN)
862 uint32_t dwHash = ShortFormHash(wCodePage, dwFontStyles, pszFontFamily);
863 std::vector<RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash];
864 if (!pFontArray->empty())
865 return pFontArray->front();
866
867 const FX_FONTDESCRIPTOR* pFD =
868 FindFont(pszFontFamily, dwFontStyles, true, wCodePage,
869 FGAS_FONTUSB::kNoBitField, 0);
870 if (!pFD) {
871 pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage,
872 FGAS_FONTUSB::kNoBitField, 0);
873 }
874 if (!pFD)
875 return nullptr;
876
877 RetainPtr<CFGAS_GEFont> pFont =
878 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage);
879 if (!pFont)
880 return nullptr;
881
882 pFont->SetLogicalFontStyle(dwFontStyles);
883 pFontArray->push_back(pFont);
884 return pFont;
885#else // BUILDFLAG(IS_WIN)
886 return GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
887#endif // BUILDFLAG(IS_WIN)
888}
RetainPtr< CFGAS_GEFont > GetFontByCodePage(FX_CodePage wCodePage, uint32_t dwFontStyles, const wchar_t *pszFontFamily)
RetainPtr< CFGAS_GEFont > GetFontByUnicode(wchar_t wUnicode, uint32_t dwFontStyles, const wchar_t *pszFontFamily)
RetainPtr< CFGAS_GEFont > LoadFont(const wchar_t *pszFontFamily, uint32_t dwFontStyles, FX_CodePage wCodePage)
static constexpr uint32_t MakeTag(char c1, char c2, char c3, char c4)
FXFT_LibraryRec * GetFTLibrary() const
Definition cfx_fontmgr.h:73
CFX_FontMapper * GetBuiltinMapper() const
Definition cfx_fontmgr.h:71
static CFX_GEModule * Get()
CFX_FontMgr * GetFontMgr() const
virtual bool ReadBlockAtOffset(pdfium::span< uint8_t > buffer, FX_FILESIZE offset)=0
static ByteString Format(const char *pFormat,...)
static WideString FromUTF8(ByteStringView str)
WideString & operator+=(wchar_t ch)
static WideString FromDefANSI(ByteStringView str)
const FGAS_FONTUSB * FGAS_GetUnicodeBitField(wchar_t wUnicode)
FX_CodePage
Definition fx_codepage.h:18
@ kMSWin_EasternEuropean
@ kMSDOS_EasternEuropean
@ kMSDOS_FrenchCanadian
@ kMSWin_WesternEuropean
@ kMSDOS_WesternEuropean
bool FontStyleIsSerif(uint32_t style)
Definition fx_font.h:77
bool FontStyleIsFixedPitch(uint32_t style)
Definition fx_font.h:65
#define FXFONT_SERIF
Definition fx_font.h:29
#define FXFONT_ITALIC
Definition fx_font.h:33
bool FontStyleIsSymbolic(uint32_t style)
Definition fx_font.h:68
#define FXFONT_SYMBOLIC
Definition fx_font.h:30
bool FontStyleIsItalic(uint32_t style)
Definition fx_font.h:62
#define FXFONT_FORCE_BOLD
Definition fx_font.h:36
bool FontStyleIsForceBold(uint32_t style)
Definition fx_font.h:59
#define FXFONT_FIXED_PITCH
Definition fx_font.h:28
static constexpr uint16_t kNoBitField
uint16_t wBitField
FX_CodePage wCodePage