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
cpdf_bafontmap.cpp
Go to the documentation of this file.
1// Copyright 2014 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 "core/fpdfdoc/cpdf_bafontmap.h"
8
9#include <memory>
10#include <utility>
11
12#include "constants/annotation_common.h"
13#include "core/fpdfapi/font/cpdf_font.h"
14#include "core/fpdfapi/font/cpdf_fontencoding.h"
15#include "core/fpdfapi/page/cpdf_docpagedata.h"
16#include "core/fpdfapi/page/cpdf_page.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_document.h"
19#include "core/fpdfapi/parser/cpdf_parser.h"
20#include "core/fpdfapi/parser/cpdf_reference.h"
21#include "core/fpdfapi/parser/cpdf_stream.h"
22#include "core/fpdfapi/parser/fpdf_parser_utility.h"
23#include "core/fpdfdoc/cpdf_defaultappearance.h"
24#include "core/fpdfdoc/cpdf_formfield.h"
25#include "core/fpdfdoc/ipvt_fontmap.h"
26#include "core/fxcrt/fx_codepage.h"
27#include "core/fxcrt/stl_util.h"
28#include "core/fxge/cfx_fontmapper.h"
29#include "core/fxge/cfx_fontmgr.h"
30#include "core/fxge/cfx_gemodule.h"
31
32namespace {
33
34bool FindNativeTrueTypeFont(ByteStringView sFontFaceName) {
36 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper();
37 pFontMapper->LoadInstalledFonts();
38 return pFontMapper->HasInstalledFont(sFontFaceName) ||
39 pFontMapper->HasLocalizedFont(sFontFaceName);
40}
41
42RetainPtr<CPDF_Font> AddNativeTrueTypeFontToPDF(CPDF_Document* pDoc,
43 ByteString sFontFaceName,
44 FX_Charset nCharset) {
45 if (!pDoc)
46 return nullptr;
47
48 auto pFXFont = std::make_unique<CFX_Font>();
49 pFXFont->LoadSubst(sFontFaceName, true, 0, 0, 0,
50 FX_GetCodePageFromCharset(nCharset), false);
51
52 auto* pDocPageData = CPDF_DocPageData::FromDocument(pDoc);
53 return pDocPageData->AddFont(std::move(pFXFont), nCharset);
54}
55
56ByteString EncodeFontAlias(ByteString sFontName, FX_Charset nCharset) {
57 sFontName.Remove(' ');
58 sFontName += ByteString::Format("_%02X", nCharset);
59 return sFontName;
60}
61
62} // namespace
63
64CPDF_BAFontMap::Data::Data() = default;
65
66CPDF_BAFontMap::Data::~Data() = default;
67
68CPDF_BAFontMap::CPDF_BAFontMap(CPDF_Document* pDocument,
69 RetainPtr<CPDF_Dictionary> pAnnotDict,
70 const ByteString& sAPType)
75 m_pDefaultFont = GetAnnotDefaultFont(&m_sDefaultFontName);
76 if (m_pDefaultFont) {
77 auto maybe_charset = m_pDefaultFont->GetSubstFontCharset();
78 if (maybe_charset.has_value()) {
79 nCharset = maybe_charset.value();
80 } else if (m_sDefaultFontName == "Wingdings" ||
81 m_sDefaultFontName == "Wingdings2" ||
82 m_sDefaultFontName == "Wingdings3" ||
83 m_sDefaultFontName == "Webdings") {
84 nCharset = FX_Charset::kSymbol;
85 } else {
86 nCharset = FX_Charset::kANSI;
87 }
88 AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
89 AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName);
90 }
91
92 if (nCharset != FX_Charset::kANSI)
94}
95
96CPDF_BAFontMap::~CPDF_BAFontMap() = default;
97
98RetainPtr<CPDF_Font> CPDF_BAFontMap::GetPDFFont(int32_t nFontIndex) {
99 if (fxcrt::IndexInBounds(m_Data, nFontIndex))
100 return m_Data[nFontIndex]->pFont;
101 return nullptr;
102}
103
104ByteString CPDF_BAFontMap::GetPDFFontAlias(int32_t nFontIndex) {
105 if (fxcrt::IndexInBounds(m_Data, nFontIndex))
106 return m_Data[nFontIndex]->sFontName;
107 return ByteString();
108}
109
110int32_t CPDF_BAFontMap::GetWordFontIndex(uint16_t word,
111 FX_Charset nCharset,
112 int32_t nFontIndex) {
113 if (nFontIndex > 0) {
114 if (KnowWord(nFontIndex, word))
115 return nFontIndex;
116 } else {
117 if (!m_Data.empty()) {
118 const Data* pData = m_Data.front().get();
119 if (nCharset == FX_Charset::kDefault ||
120 pData->nCharset == FX_Charset::kSymbol ||
121 nCharset == pData->nCharset) {
122 if (KnowWord(0, word))
123 return 0;
124 }
125 }
126 }
127
128 int32_t nNewFontIndex =
129 GetFontIndex(GetCachedNativeFontName(nCharset), nCharset, true);
130 if (nNewFontIndex >= 0) {
131 if (KnowWord(nNewFontIndex, word))
132 return nNewFontIndex;
133 }
134 nNewFontIndex = GetFontIndex(CFX_Font::kUniversalDefaultFontName,
135 FX_Charset::kDefault, false);
136 if (nNewFontIndex >= 0) {
137 if (KnowWord(nNewFontIndex, word))
138 return nNewFontIndex;
139 }
140 return -1;
141}
142
143int32_t CPDF_BAFontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) {
144 if (!fxcrt::IndexInBounds(m_Data, nFontIndex))
145 return -1;
146
147 Data* pData = m_Data[nFontIndex].get();
148 if (!pData->pFont)
149 return -1;
150
151 if (pData->pFont->IsUnicodeCompatible())
152 return pData->pFont->CharCodeFromUnicode(word);
153
154 return word < 0xFF ? word : -1;
155}
156
157FX_Charset CPDF_BAFontMap::CharSetFromUnicode(uint16_t word,
158 FX_Charset nOldCharset) {
159 // to avoid CJK Font to show ASCII
160 if (word < 0x7F)
161 return FX_Charset::kANSI;
162
163 // follow the old charset
164 if (nOldCharset != FX_Charset::kDefault)
165 return nOldCharset;
166
168}
169
173
174RetainPtr<CPDF_Font> CPDF_BAFontMap::FindFontSameCharset(ByteString* sFontAlias,
175 FX_Charset nCharset) {
176 if (m_pAnnotDict->GetNameFor(pdfium::annotation::kSubtype) != "Widget")
177 return nullptr;
178
179 const CPDF_Dictionary* pRootDict = m_pDocument->GetRoot();
180 if (!pRootDict)
181 return nullptr;
182
183 RetainPtr<const CPDF_Dictionary> pAcroFormDict =
184 pRootDict->GetDictFor("AcroForm");
185 if (!pAcroFormDict)
186 return nullptr;
187
188 RetainPtr<const CPDF_Dictionary> pDRDict = pAcroFormDict->GetDictFor("DR");
189 if (!pDRDict)
190 return nullptr;
191
192 return FindResFontSameCharset(pDRDict.Get(), sFontAlias, nCharset);
193}
194
195RetainPtr<CPDF_Font> CPDF_BAFontMap::FindResFontSameCharset(
196 const CPDF_Dictionary* pResDict,
197 ByteString* sFontAlias,
198 FX_Charset nCharset) {
199 if (!pResDict)
200 return nullptr;
201
202 RetainPtr<const CPDF_Dictionary> pFonts = pResDict->GetDictFor("Font");
203 if (!pFonts)
204 return nullptr;
205
206 RetainPtr<CPDF_Font> pFind;
207 CPDF_DictionaryLocker locker(pFonts);
208 for (const auto& it : locker) {
209 const ByteString& csKey = it.first;
210 RetainPtr<CPDF_Dictionary> pElement =
211 ToDictionary(it.second->GetMutableDirect());
212 if (!ValidateDictType(pElement.Get(), "Font"))
213 continue;
214
215 auto* pData = CPDF_DocPageData::FromDocument(m_pDocument);
216 RetainPtr<CPDF_Font> pFont = pData->GetFont(std::move(pElement));
217 if (!pFont)
218 continue;
219
220 auto maybe_charset = pFont->GetSubstFontCharset();
221 if (maybe_charset.has_value() && maybe_charset.value() == nCharset) {
222 *sFontAlias = csKey;
223 pFind = std::move(pFont);
224 }
225 }
226 return pFind;
227}
228
229RetainPtr<CPDF_Font> CPDF_BAFontMap::GetAnnotDefaultFont(ByteString* sAlias) {
230 RetainPtr<CPDF_Dictionary> pAcroFormDict;
231 const bool bWidget =
232 (m_pAnnotDict->GetNameFor(pdfium::annotation::kSubtype) == "Widget");
233 if (bWidget) {
234 RetainPtr<CPDF_Dictionary> pRootDict = m_pDocument->GetMutableRoot();
235 if (pRootDict)
236 pAcroFormDict = pRootDict->GetMutableDictFor("AcroForm");
237 }
238
239 ByteString sDA;
240 RetainPtr<const CPDF_Object> pObj =
241 CPDF_FormField::GetFieldAttrForDict(m_pAnnotDict.Get(), "DA");
242 if (pObj)
243 sDA = pObj->GetString();
244
245 if (bWidget) {
246 if (sDA.IsEmpty()) {
247 pObj = CPDF_FormField::GetFieldAttrForDict(pAcroFormDict.Get(), "DA");
248 sDA = pObj ? pObj->GetString() : ByteString();
249 }
250 }
251 if (sDA.IsEmpty())
252 return nullptr;
253
254 CPDF_DefaultAppearance appearance(sDA);
255 float font_size;
256 std::optional<ByteString> font = appearance.GetFont(&font_size);
257 *sAlias = font.value_or(ByteString());
258
259 RetainPtr<CPDF_Dictionary> pFontDict;
260 if (RetainPtr<CPDF_Dictionary> pAPDict =
261 m_pAnnotDict->GetMutableDictFor(pdfium::annotation::kAP)) {
262 if (RetainPtr<CPDF_Dictionary> pNormalDict =
263 pAPDict->GetMutableDictFor("N")) {
264 if (RetainPtr<CPDF_Dictionary> pNormalResDict =
265 pNormalDict->GetMutableDictFor("Resources")) {
266 if (RetainPtr<CPDF_Dictionary> pResFontDict =
267 pNormalResDict->GetMutableDictFor("Font")) {
268 pFontDict = pResFontDict->GetMutableDictFor(*sAlias);
269 }
270 }
271 }
272 }
273 if (bWidget && !pFontDict && pAcroFormDict) {
274 if (RetainPtr<CPDF_Dictionary> pDRDict =
275 pAcroFormDict->GetMutableDictFor("DR")) {
276 if (RetainPtr<CPDF_Dictionary> pDRFontDict =
277 pDRDict->GetMutableDictFor("Font")) {
278 pFontDict = pDRFontDict->GetMutableDictFor(*sAlias);
279 }
280 }
281 }
282 if (!pFontDict)
283 return nullptr;
284
285 return CPDF_DocPageData::FromDocument(m_pDocument)->GetFont(pFontDict);
286}
287
288void CPDF_BAFontMap::AddFontToAnnotDict(const RetainPtr<CPDF_Font>& pFont,
289 const ByteString& sAlias) {
290 if (!pFont)
291 return;
292
293 RetainPtr<CPDF_Dictionary> pAPDict =
294 m_pAnnotDict->GetOrCreateDictFor(pdfium::annotation::kAP);
295
296 // to avoid checkbox and radiobutton
297 if (ToDictionary(pAPDict->GetObjectFor(m_sAPType)))
298 return;
299
300 RetainPtr<CPDF_Stream> stream = pAPDict->GetMutableStreamFor(m_sAPType);
301 if (!stream) {
302 stream = m_pDocument->NewIndirect<CPDF_Stream>(
303 m_pDocument->New<CPDF_Dictionary>());
304 pAPDict->SetNewFor<CPDF_Reference>(m_sAPType, m_pDocument,
305 stream->GetObjNum());
306 }
307
308 RetainPtr<CPDF_Dictionary> pStreamResList =
309 stream->GetMutableDict()->GetOrCreateDictFor("Resources");
310 RetainPtr<CPDF_Dictionary> pStreamResFontList =
311 pStreamResList->GetMutableDictFor("Font");
312 if (!pStreamResFontList) {
313 pStreamResFontList = m_pDocument->NewIndirect<CPDF_Dictionary>();
314 pStreamResList->SetNewFor<CPDF_Reference>("Font", m_pDocument,
315 pStreamResFontList->GetObjNum());
316 }
317 if (!pStreamResFontList->KeyExist(sAlias)) {
318 RetainPtr<const CPDF_Dictionary> pFontDict = pFont->GetFontDict();
319 RetainPtr<CPDF_Object> pObject =
320 pFontDict->IsInline() ? pFontDict->Clone()
321 : pFontDict->MakeReference(m_pDocument);
322 pStreamResFontList->SetFor(sAlias, std::move(pObject));
323 }
324}
325
326bool CPDF_BAFontMap::KnowWord(int32_t nFontIndex, uint16_t word) {
327 return fxcrt::IndexInBounds(m_Data, nFontIndex) &&
328 CharCodeFromUnicode(nFontIndex, word) >= 0;
329}
330
331int32_t CPDF_BAFontMap::GetFontIndex(const ByteString& sFontName,
332 FX_Charset nCharset,
333 bool bFind) {
334 int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset);
335 if (nFontIndex >= 0)
336 return nFontIndex;
337
338 ByteString sAlias;
339 RetainPtr<CPDF_Font> pFont =
340 bFind ? FindFontSameCharset(&sAlias, nCharset) : nullptr;
341 if (!pFont) {
342 pFont = AddFontToDocument(sFontName, nCharset);
343 sAlias = EncodeFontAlias(sFontName, nCharset);
344 }
345 AddFontToAnnotDict(pFont, sAlias);
346 return AddFontData(pFont, sAlias, nCharset);
347}
348
349int32_t CPDF_BAFontMap::AddFontData(const RetainPtr<CPDF_Font>& pFont,
350 const ByteString& sFontAlias,
351 FX_Charset nCharset) {
352 auto pNewData = std::make_unique<Data>();
353 pNewData->pFont = pFont;
354 pNewData->sFontName = sFontAlias;
355 pNewData->nCharset = nCharset;
356 m_Data.push_back(std::move(pNewData));
357 return fxcrt::CollectionSize<int32_t>(m_Data) - 1;
358}
359
360int32_t CPDF_BAFontMap::FindFont(const ByteString& sFontName,
361 FX_Charset nCharset) {
362 int32_t i = 0;
363 for (const auto& pData : m_Data) {
364 if ((nCharset == FX_Charset::kDefault || nCharset == pData->nCharset) &&
365 (sFontName.IsEmpty() || pData->sFontName == sFontName)) {
366 return i;
367 }
368 ++i;
369 }
370 return -1;
371}
372
373ByteString CPDF_BAFontMap::GetNativeFontName(FX_Charset nCharset) {
374 if (nCharset == FX_Charset::kDefault)
375 nCharset = GetNativeCharset();
376
378 if (!FindNativeTrueTypeFont(sFontName.AsStringView()))
379 return ByteString();
380
381 return sFontName;
382}
383
384ByteString CPDF_BAFontMap::GetCachedNativeFontName(FX_Charset nCharset) {
385 for (const auto& pData : m_NativeFont) {
386 if (pData && pData->nCharset == nCharset)
387 return pData->sFontName;
388 }
389
390 ByteString sNew = GetNativeFontName(nCharset);
391 if (sNew.IsEmpty())
392 return ByteString();
393
394 auto pNewData = std::make_unique<Native>();
395 pNewData->nCharset = nCharset;
396 pNewData->sFontName = sNew;
397 m_NativeFont.push_back(std::move(pNewData));
398 return sNew;
399}
400
401RetainPtr<CPDF_Font> CPDF_BAFontMap::AddFontToDocument(ByteString sFontName,
402 FX_Charset nCharset) {
404 return AddStandardFont(sFontName);
405
406 return AddSystemFont(sFontName, nCharset);
407}
408
409RetainPtr<CPDF_Font> CPDF_BAFontMap::AddStandardFont(ByteString sFontName) {
410 auto* pPageData = CPDF_DocPageData::FromDocument(m_pDocument);
411 if (sFontName == "ZapfDingbats")
412 return pPageData->AddStandardFont(sFontName, nullptr);
413
415 return pPageData->AddStandardFont(sFontName, &fe);
416}
417
418RetainPtr<CPDF_Font> CPDF_BAFontMap::AddSystemFont(ByteString sFontName,
419 FX_Charset nCharset) {
420 if (sFontName.IsEmpty())
421 sFontName = GetNativeFontName(nCharset);
422
423 if (nCharset == FX_Charset::kDefault)
424 nCharset = GetNativeCharset();
425
426 return AddNativeTrueTypeFontToPDF(m_pDocument, sFontName, nCharset);
427}
fxcrt::ByteString ByteString
Definition bytestring.h:180
bool HasLocalizedFont(ByteStringView name) const
bool HasInstalledFont(ByteStringView name) const
static bool IsStandardFontName(const ByteString &name)
CFX_FontMapper * GetBuiltinMapper() const
Definition cfx_fontmgr.h:72
static ByteString GetDefaultFontNameByCharset(FX_Charset nCharset)
Definition cfx_font.cpp:116
static const char kDefaultAnsiFontName[]
Definition cfx_font.h:54
static const char kUniversalDefaultFontName[]
Definition cfx_font.h:55
static FX_Charset GetCharSetFromUnicode(uint16_t word)
Definition cfx_font.cpp:126
static CFX_GEModule * Get()
CFX_FontMgr * GetFontMgr() const
int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override
FX_Charset CharSetFromUnicode(uint16_t word, FX_Charset nOldCharset) override
RetainPtr< CPDF_Font > GetPDFFont(int32_t nFontIndex) override
~CPDF_BAFontMap() override
static FX_Charset GetNativeCharset()
CPDF_BAFontMap(CPDF_Document *pDocument, RetainPtr< CPDF_Dictionary > pAnnotDict, const ByteString &sAPType)
int32_t GetWordFontIndex(uint16_t word, FX_Charset nCharset, int32_t nFontIndex) override
ByteString GetPDFFontAlias(int32_t nFontIndex) override
CPDF_DefaultAppearance(const ByteString &csDA)
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
CPDF_FontEncoding(FontEncoding predefined_encoding)
static RetainPtr< const CPDF_Object > GetFieldAttrForDict(const CPDF_Dictionary *pFieldDict, const ByteString &name)
static ByteString Format(const char *pFormat,...)
ByteString & operator+=(const ByteString &str)
ByteString()=default
bool operator==(const char *ptr) const
ByteString & operator=(ByteString &&that) noexcept
FontEncoding
FX_CodePage FX_GetCodePageFromCharset(FX_Charset charset)
FX_Charset
Definition fx_codepage.h:71
FX_Charset FX_GetCharsetFromCodePage(FX_CodePage codepage)
FX_CodePage FX_GetACP()
fxcrt::ByteStringView ByteStringView