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