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_font.cpp
Go to the documentation of this file.
1// Copyright 2016 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/fpdfapi/font/cpdf_font.h"
8
9#include <algorithm>
10#include <memory>
11#include <utility>
12#include <vector>
13
14#include "build/build_config.h"
15#include "constants/font_encodings.h"
16#include "core/fpdfapi/font/cpdf_cidfont.h"
17#include "core/fpdfapi/font/cpdf_fontencoding.h"
18#include "core/fpdfapi/font/cpdf_fontglobals.h"
19#include "core/fpdfapi/font/cpdf_tounicodemap.h"
20#include "core/fpdfapi/font/cpdf_truetypefont.h"
21#include "core/fpdfapi/font/cpdf_type1font.h"
22#include "core/fpdfapi/font/cpdf_type3font.h"
23#include "core/fpdfapi/parser/cpdf_array.h"
24#include "core/fpdfapi/parser/cpdf_dictionary.h"
25#include "core/fpdfapi/parser/cpdf_document.h"
26#include "core/fpdfapi/parser/cpdf_name.h"
27#include "core/fpdfapi/parser/cpdf_stream.h"
28#include "core/fpdfapi/parser/cpdf_stream_acc.h"
29#include "core/fxcrt/fx_codepage.h"
30#include "core/fxcrt/fx_safe_types.h"
31#include "core/fxcrt/stl_util.h"
32#include "core/fxge/cfx_fontmapper.h"
33#include "core/fxge/cfx_substfont.h"
34#include "core/fxge/freetype/fx_freetype.h"
35#include "core/fxge/fx_font.h"
36#include "third_party/base/check.h"
37#include "third_party/base/numerics/clamped_math.h"
38#include "third_party/base/numerics/safe_conversions.h"
39
40namespace {
41
42constexpr size_t kChineseFontNameSize = 4;
43const uint8_t kChineseFontNames[][kChineseFontNameSize] = {
44 {0xCB, 0xCE, 0xCC, 0xE5},
45 {0xBF, 0xAC, 0xCC, 0xE5},
46 {0xBA, 0xDA, 0xCC, 0xE5},
47 {0xB7, 0xC2, 0xCB, 0xCE},
48 {0xD0, 0xC2, 0xCB, 0xCE}};
49
50} // namespace
51
53 RetainPtr<CPDF_Dictionary> pFontDict)
57
59 if (m_pFontFile)
60 m_pDocument->MaybePurgeFontFileStreamAcc(std::move(m_pFontFile));
61}
62
63bool CPDF_Font::IsType1Font() const {
64 return false;
65}
66
68 return false;
69}
70
71bool CPDF_Font::IsType3Font() const {
72 return false;
73}
74
75bool CPDF_Font::IsCIDFont() const {
76 return false;
77}
78
79const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
80 return nullptr;
81}
82
83CPDF_Type1Font* CPDF_Font::AsType1Font() {
84 return nullptr;
85}
86
87const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
88 return nullptr;
89}
90
91CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
92 return nullptr;
93}
94
95const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
96 return nullptr;
97}
98
99CPDF_Type3Font* CPDF_Font::AsType3Font() {
100 return nullptr;
101}
102
103const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
104 return nullptr;
105}
106
107CPDF_CIDFont* CPDF_Font::AsCIDFont() {
108 return nullptr;
109}
110
111size_t CPDF_Font::CountChar(ByteStringView pString) const {
112 return pString.GetLength();
113}
114
115#if BUILDFLAG(IS_APPLE)
116int CPDF_Font::GlyphFromCharCodeExt(uint32_t charcode) {
117 return GlyphFromCharCode(charcode, nullptr);
118}
119#endif
120
122
124 const CPDF_CIDFont* pCIDFont = AsCIDFont();
125 return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
126}
127
128int CPDF_Font::AppendChar(char* buf, uint32_t charcode) const {
129 *buf = static_cast<char>(charcode);
130 return 1;
131}
132
133void CPDF_Font::AppendChar(ByteString* str, uint32_t charcode) const {
134 char buf[4];
135 int len = AppendChar(buf, charcode);
136 *str += ByteStringView(buf, len);
137}
138
139WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
142
143 return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : WideString();
144}
145
146uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const {
149
150 return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
151}
152
154 return true;
155}
156
157void CPDF_Font::LoadFontDescriptor(const CPDF_Dictionary* pFontDesc) {
159 int ItalicAngle = 0;
160 bool bExistItalicAngle = false;
161 if (pFontDesc->KeyExist("ItalicAngle")) {
162 ItalicAngle = pFontDesc->GetIntegerFor("ItalicAngle");
163 bExistItalicAngle = true;
164 }
165 if (ItalicAngle < 0) {
167 m_ItalicAngle = ItalicAngle;
168 }
169 bool bExistStemV = false;
170 if (pFontDesc->KeyExist("StemV")) {
171 m_StemV = pFontDesc->GetIntegerFor("StemV");
172 bExistStemV = true;
173 }
174 bool bExistAscent = false;
175 if (pFontDesc->KeyExist("Ascent")) {
176 m_Ascent = pFontDesc->GetIntegerFor("Ascent");
177 bExistAscent = true;
178 }
179 bool bExistDescent = false;
180 if (pFontDesc->KeyExist("Descent")) {
181 m_Descent = pFontDesc->GetIntegerFor("Descent");
182 bExistDescent = true;
183 }
184 bool bExistCapHeight = false;
185 if (pFontDesc->KeyExist("CapHeight"))
186 bExistCapHeight = true;
187 if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
188 bExistStemV) {
190 }
191 if (m_Descent > 10)
193 RetainPtr<const CPDF_Array> pBBox = pFontDesc->GetArrayFor("FontBBox");
194 if (pBBox) {
195 m_FontBBox.left = pBBox->GetIntegerAt(0);
196 m_FontBBox.bottom = pBBox->GetIntegerAt(1);
197 m_FontBBox.right = pBBox->GetIntegerAt(2);
198 m_FontBBox.top = pBBox->GetIntegerAt(3);
199 }
200
201 RetainPtr<const CPDF_Stream> pFontFile = pFontDesc->GetStreamFor("FontFile");
202 if (!pFontFile)
203 pFontFile = pFontDesc->GetStreamFor("FontFile2");
204 if (!pFontFile)
205 pFontFile = pFontDesc->GetStreamFor("FontFile3");
206 if (!pFontFile)
207 return;
208
209 const uint64_t key = pFontFile->KeyForCache();
210 m_pFontFile = m_pDocument->GetFontFileStreamAcc(std::move(pFontFile));
211 if (!m_pFontFile)
212 return;
213
214 if (!m_Font.LoadEmbedded(m_pFontFile->GetSpan(), IsVertWriting(), key))
215 m_pDocument->MaybePurgeFontFileStreamAcc(std::move(m_pFontFile));
216}
217
219 if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
220 m_FontBBox.right == 0) {
221 RetainPtr<CFX_Face> face = m_Font.GetFace();
222 if (face) {
223 // Note that `m_FontBBox` is deliberately flipped.
224 const FX_RECT raw_bbox = face->GetBBox();
225 m_FontBBox.left = TT2PDF(raw_bbox.left, face);
226 m_FontBBox.bottom = TT2PDF(raw_bbox.top, face);
227 m_FontBBox.right = TT2PDF(raw_bbox.right, face);
228 m_FontBBox.top = TT2PDF(raw_bbox.bottom, face);
229 m_Ascent = TT2PDF(face->GetAscender(), face);
230 m_Descent = TT2PDF(face->GetDescender(), face);
231 } else {
232 bool bFirst = true;
233 for (int i = 0; i < 256; i++) {
234 FX_RECT rect = GetCharBBox(i);
235 if (rect.left == rect.right) {
236 continue;
237 }
238 if (bFirst) {
239 m_FontBBox = rect;
240 bFirst = false;
241 } else {
246 }
247 }
248 }
249 }
250 if (m_Ascent == 0 && m_Descent == 0) {
251 FX_RECT rect = GetCharBBox('A');
252 m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
253 rect = GetCharBBox('g');
254 m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
255 }
256}
257
259 m_bToUnicodeLoaded = true;
260 RetainPtr<const CPDF_Stream> pStream = m_pFontDict->GetStreamFor("ToUnicode");
261 if (!pStream)
262 return;
263
264 m_pToUnicodeMap = std::make_unique<CPDF_ToUnicodeMap>(std::move(pStream));
265}
266
267int CPDF_Font::GetStringWidth(ByteStringView pString) {
268 size_t offset = 0;
269 int width = 0;
270 while (offset < pString.GetLength())
271 width += GetCharWidthF(GetNextChar(pString, &offset));
272 return width;
273}
274
275// static
277 ByteStringView name) {
278 ByteString fontname(name);
279 absl::optional<CFX_FontMapper::StandardFont> font_id =
280 CFX_FontMapper::GetStandardFontName(&fontname);
281 if (!font_id.has_value())
282 return nullptr;
283
284 auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
285 RetainPtr<CPDF_Font> pFont = pFontGlobals->Find(pDoc, font_id.value());
286 if (pFont)
287 return pFont;
288
289 auto pDict = pDoc->New<CPDF_Dictionary>();
290 pDict->SetNewFor<CPDF_Name>("Type", "Font");
291 pDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
292 pDict->SetNewFor<CPDF_Name>("BaseFont", fontname);
293 pDict->SetNewFor<CPDF_Name>("Encoding",
295 pFont = CPDF_Font::Create(nullptr, std::move(pDict), nullptr);
296 pFontGlobals->Set(pDoc, font_id.value(), pFont);
297 return pFont;
298}
299
300// static
302 RetainPtr<CPDF_Dictionary> pFontDict,
303 FormFactoryIface* pFactory) {
304 ByteString type = pFontDict->GetByteStringFor("Subtype");
305 RetainPtr<CPDF_Font> pFont;
306 if (type == "TrueType") {
307 ByteString tag = pFontDict->GetByteStringFor("BaseFont").First(4);
308 for (size_t i = 0; i < std::size(kChineseFontNames); ++i) {
309 if (tag == ByteString(kChineseFontNames[i], kChineseFontNameSize)) {
310 RetainPtr<const CPDF_Dictionary> pFontDesc =
311 pFontDict->GetDictFor("FontDescriptor");
312 if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
313 pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, std::move(pFontDict));
314 break;
315 }
316 }
317 if (!pFont)
318 pFont = pdfium::MakeRetain<CPDF_TrueTypeFont>(pDoc, std::move(pFontDict));
319 } else if (type == "Type3") {
320 pFont = pdfium::MakeRetain<CPDF_Type3Font>(pDoc, std::move(pFontDict),
321 pFactory);
322 } else if (type == "Type0") {
323 pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, std::move(pFontDict));
324 } else {
325 pFont = pdfium::MakeRetain<CPDF_Type1Font>(pDoc, std::move(pFontDict));
326 }
327 if (!pFont->Load())
328 return nullptr;
329
330 return pFont;
331}
332
333uint32_t CPDF_Font::GetNextChar(ByteStringView pString, size_t* pOffset) const {
334 if (pString.IsEmpty())
335 return 0;
336
337 size_t& offset = *pOffset;
338 return offset < pString.GetLength() ? pString[offset++] : pString.Back();
339}
340
342 if (!IsType1Font())
343 return false;
344 if (m_pFontFile)
345 return false;
347}
348
350 CFX_SubstFont* pFont = m_Font.GetSubstFont();
351 if (!pFont)
352 return absl::nullopt;
353 return pFont->m_Charset;
354}
355
356// static
357const char* CPDF_Font::GetAdobeCharName(
358 FontEncoding base_encoding,
359 const std::vector<ByteString>& charnames,
360 uint32_t charcode) {
361 if (charcode >= 256)
362 return nullptr;
363
364 if (!charnames.empty() && !charnames[charcode].IsEmpty())
365 return charnames[charcode].c_str();
366
367 const char* name = nullptr;
368 if (base_encoding != FontEncoding::kBuiltin)
369 name = CharNameFromPredefinedCharSet(base_encoding, charcode);
370 if (!name)
371 return nullptr;
372
373 DCHECK(name[0]);
374 return name;
375}
376
377uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) {
378 if (m_FontFallbacks.empty()) {
379 m_FontFallbacks.push_back(std::make_unique<CFX_Font>());
380 FX_SAFE_INT32 safeWeight = m_StemV;
381 safeWeight *= 5;
382 m_FontFallbacks[0]->LoadSubst("Arial", IsTrueTypeFont(), m_Flags,
383 safeWeight.ValueOrDefault(FXFONT_FW_NORMAL),
384 m_ItalicAngle, FX_CodePage::kDefANSI,
385 IsVertWriting());
386 }
387 return 0;
388}
389
390int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) {
391 if (!fxcrt::IndexInBounds(m_FontFallbacks, fallbackFont))
392 return -1;
393
394 WideString str = UnicodeFromCharCode(charcode);
395 uint32_t unicode = !str.IsEmpty() ? str[0] : charcode;
396 int glyph = m_FontFallbacks[fallbackFont]->GetFace()->GetCharIndex(unicode);
397 if (glyph == 0)
398 return -1;
399
400 return glyph;
401}
402
404 if (position < 0 || static_cast<size_t>(position) >= m_FontFallbacks.size())
405 return nullptr;
406 return m_FontFallbacks[position].get();
407}
408
409// static
410int CPDF_Font::TT2PDF(FT_Pos m, const RetainPtr<CFX_Face>& face) {
411 int upm = face->GetUnitsPerEm();
412 if (upm == 0)
413 return pdfium::base::saturated_cast<int>(m);
414
415 const double dm = (m * 1000.0 + upm / 2) / upm;
416 return pdfium::base::saturated_cast<int>(dm);
417}
418
419// static
421 FXFT_FaceRec* rec = face->GetRec();
422 pdfium::base::ClampedNumeric<FT_Pos> left = FXFT_Get_Glyph_HoriBearingX(rec);
423 pdfium::base::ClampedNumeric<FT_Pos> top = FXFT_Get_Glyph_HoriBearingY(rec);
424 return FX_RECT(TT2PDF(left, face), TT2PDF(top, face),
425 TT2PDF(left + FXFT_Get_Glyph_Width(rec), face),
426 TT2PDF(top - FXFT_Get_Glyph_Height(rec), face));
427}
428
429// static
430bool CPDF_Font::UseTTCharmap(const RetainPtr<CFX_Face>& face,
431 int platform_id,
432 int encoding_id) {
433 for (size_t i = 0; i < face->GetCharMapCount(); i++) {
434 if (face->GetCharMapPlatformIdByIndex(i) == platform_id &&
435 face->GetCharMapEncodingIdByIndex(i) == encoding_id) {
436 face->SetCharMapByIndex(i);
437 return true;
438 }
439 }
440 return false;
441}
442
444 FX_SAFE_INT32 safeStemV(m_StemV);
445 if (m_StemV < 140)
446 safeStemV *= 5;
447 else
448 safeStemV = safeStemV * 4 + 140;
449 return safeStemV.ValueOrDefault(FXFONT_FW_NORMAL);
450}
FX_Charset m_Charset
bool KeyExist(const ByteString &key) const
int GetIntegerFor(const ByteString &key) const
RetainPtr< const CPDF_Stream > GetStreamFor(const ByteString &key) const
int GetIntegerFor(const ByteString &key, int default_int) const
static CPDF_FontGlobals * GetInstance()
virtual FX_RECT GetCharBBox(uint32_t charcode)=0
virtual bool IsTrueTypeFont() const
Definition cpdf_font.cpp:67
virtual const CPDF_CIDFont * AsCIDFont() const
int m_ItalicAngle
Definition cpdf_font.h:182
virtual void WillBeDestroyed()
int FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode)
void LoadFontDescriptor(const CPDF_Dictionary *pFontDesc)
virtual CPDF_CIDFont * AsCIDFont()
absl::optional< FX_Charset > GetSubstFontCharset() const
virtual bool IsType1Font() const
Definition cpdf_font.cpp:63
virtual bool IsVertWriting() const
CPDF_Font(CPDF_Document *pDocument, RetainPtr< CPDF_Dictionary > pFontDict)
Definition cpdf_font.cpp:52
~CPDF_Font() override
Definition cpdf_font.cpp:58
void LoadUnicodeMap() const
static RetainPtr< CPDF_Font > Create(CPDF_Document *pDoc, RetainPtr< CPDF_Dictionary > pFontDict, FormFactoryIface *pFactory)
virtual uint32_t CharCodeFromUnicode(wchar_t Unicode) const
virtual const CPDF_TrueTypeFont * AsTrueTypeFont() const
Definition cpdf_font.cpp:87
virtual const CPDF_Type1Font * AsType1Font() const
Definition cpdf_font.cpp:79
int m_Flags
Definition cpdf_font.h:178
virtual bool IsCIDFont() const
Definition cpdf_font.cpp:75
int m_StemV
Definition cpdf_font.h:179
virtual WideString UnicodeFromCharCode(uint32_t charcode) const
virtual const CPDF_Type3Font * AsType3Font() const
Definition cpdf_font.cpp:95
static RetainPtr< CPDF_Font > GetStockFont(CPDF_Document *pDoc, ByteStringView fontname)
static bool UseTTCharmap(const RetainPtr< CFX_Face > &face, int platform_id, int encoding_id)
virtual size_t CountChar(ByteStringView pString) const
void AppendChar(ByteString *str, uint32_t charcode) const
int GetStringWidth(ByteStringView pString)
virtual CPDF_Type1Font * AsType1Font()
Definition cpdf_font.cpp:83
virtual bool HasFontWidths() const
virtual bool IsType3Font() const
Definition cpdf_font.cpp:71
virtual CPDF_Type3Font * AsType3Font()
Definition cpdf_font.cpp:99
virtual CPDF_TrueTypeFont * AsTrueTypeFont()
Definition cpdf_font.cpp:91
FX_RECT m_FontBBox
Definition cpdf_font.h:183
int GetFontWeight() const
virtual int AppendChar(char *buf, uint32_t charcode) const
int m_Ascent
Definition cpdf_font.h:180
int m_Descent
Definition cpdf_font.h:181
virtual uint32_t GetNextChar(ByteStringView pString, size_t *pOffset) const
bool m_bToUnicodeLoaded
Definition cpdf_font.h:177
uint32_t FallbackFontFromCharcode(uint32_t charcode)
bool IsStandardFont() const
static FX_RECT GetCharBBoxForFace(const RetainPtr< CFX_Face > &face)
void CheckFontMetrics()
CFX_Font * GetFontFallback(int position)
bool IsBase14Font() const
bool operator==(const ByteString &other) const
bool operator==(const char *ptr) const
CharType operator[](const size_t index) const
Definition widestring.h:146
bool IsEmpty() const
Definition widestring.h:118
const char * CharNameFromPredefinedCharSet(FontEncoding encoding, uint8_t charcode)
FontEncoding
#define FXFONT_USEEXTERNATTR
Definition fx_font.h:39
#define FXFONT_NONSYMBOLIC
Definition fx_font.h:32
#define FXFONT_FW_NORMAL
Definition fx_font.h:22
#define FXFONT_ITALIC
Definition fx_font.h:33
#define FXFT_Get_Glyph_Width(face)
Definition fx_freetype.h:58
#define FXFT_Get_Glyph_Height(face)
Definition fx_freetype.h:59
#define FXFT_Get_Glyph_HoriBearingX(face)
Definition fx_freetype.h:56
#define FXFT_Get_Glyph_HoriBearingY(face)
Definition fx_freetype.h:57
FX_RECT & operator=(const FX_RECT &that)=default
int32_t bottom
int32_t right
int32_t top
int32_t left