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/safe_conversions.h"
38
39 namespace {
40
41 constexpr size_t kChineseFontNameSize = 4;
42 const uint8_t kChineseFontNames[][kChineseFontNameSize] = {
43 {0xCB, 0xCE, 0xCC, 0xE5},
44 {0xBF, 0xAC, 0xCC, 0xE5},
45 {0xBA, 0xDA, 0xCC, 0xE5},
46 {0xB7, 0xC2, 0xCB, 0xCE},
47 {0xD0, 0xC2, 0xCB, 0xCE}};
48
49 } // namespace
50
CPDF_Font(CPDF_Document * pDocument,RetainPtr<CPDF_Dictionary> pFontDict)51 CPDF_Font::CPDF_Font(CPDF_Document* pDocument,
52 RetainPtr<CPDF_Dictionary> pFontDict)
53 : m_pDocument(pDocument),
54 m_pFontDict(std::move(pFontDict)),
55 m_BaseFontName(m_pFontDict->GetByteStringFor("BaseFont")) {}
56
~CPDF_Font()57 CPDF_Font::~CPDF_Font() {
58 if (m_pFontFile)
59 m_pDocument->MaybePurgeFontFileStreamAcc(std::move(m_pFontFile));
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
IsVertWriting() const122 bool CPDF_Font::IsVertWriting() const {
123 const CPDF_CIDFont* pCIDFont = AsCIDFont();
124 return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
125 }
126
AppendChar(char * buf,uint32_t charcode) const127 int CPDF_Font::AppendChar(char* buf, uint32_t charcode) const {
128 *buf = static_cast<char>(charcode);
129 return 1;
130 }
131
AppendChar(ByteString * str,uint32_t charcode) const132 void CPDF_Font::AppendChar(ByteString* str, uint32_t charcode) const {
133 char buf[4];
134 int len = AppendChar(buf, charcode);
135 *str += ByteStringView(buf, len);
136 }
137
UnicodeFromCharCode(uint32_t charcode) const138 WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
139 if (!m_bToUnicodeLoaded)
140 LoadUnicodeMap();
141
142 return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : WideString();
143 }
144
CharCodeFromUnicode(wchar_t unicode) const145 uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const {
146 if (!m_bToUnicodeLoaded)
147 LoadUnicodeMap();
148
149 return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
150 }
151
HasFontWidths() const152 bool CPDF_Font::HasFontWidths() const {
153 return true;
154 }
155
LoadFontDescriptor(const CPDF_Dictionary * pFontDesc)156 void CPDF_Font::LoadFontDescriptor(const CPDF_Dictionary* pFontDesc) {
157 m_Flags = pFontDesc->GetIntegerFor("Flags", FXFONT_NONSYMBOLIC);
158 int ItalicAngle = 0;
159 bool bExistItalicAngle = false;
160 if (pFontDesc->KeyExist("ItalicAngle")) {
161 ItalicAngle = pFontDesc->GetIntegerFor("ItalicAngle");
162 bExistItalicAngle = true;
163 }
164 if (ItalicAngle < 0) {
165 m_Flags |= FXFONT_ITALIC;
166 m_ItalicAngle = ItalicAngle;
167 }
168 bool bExistStemV = false;
169 if (pFontDesc->KeyExist("StemV")) {
170 m_StemV = pFontDesc->GetIntegerFor("StemV");
171 bExistStemV = true;
172 }
173 bool bExistAscent = false;
174 if (pFontDesc->KeyExist("Ascent")) {
175 m_Ascent = pFontDesc->GetIntegerFor("Ascent");
176 bExistAscent = true;
177 }
178 bool bExistDescent = false;
179 if (pFontDesc->KeyExist("Descent")) {
180 m_Descent = pFontDesc->GetIntegerFor("Descent");
181 bExistDescent = true;
182 }
183 bool bExistCapHeight = false;
184 if (pFontDesc->KeyExist("CapHeight"))
185 bExistCapHeight = true;
186 if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
187 bExistStemV) {
188 m_Flags |= FXFONT_USEEXTERNATTR;
189 }
190 if (m_Descent > 10)
191 m_Descent = -m_Descent;
192 RetainPtr<const CPDF_Array> pBBox = pFontDesc->GetArrayFor("FontBBox");
193 if (pBBox) {
194 m_FontBBox.left = pBBox->GetIntegerAt(0);
195 m_FontBBox.bottom = pBBox->GetIntegerAt(1);
196 m_FontBBox.right = pBBox->GetIntegerAt(2);
197 m_FontBBox.top = pBBox->GetIntegerAt(3);
198 }
199
200 RetainPtr<const CPDF_Stream> pFontFile = pFontDesc->GetStreamFor("FontFile");
201 if (!pFontFile)
202 pFontFile = pFontDesc->GetStreamFor("FontFile2");
203 if (!pFontFile)
204 pFontFile = pFontDesc->GetStreamFor("FontFile3");
205 if (!pFontFile)
206 return;
207
208 const uint64_t key = pFontFile->KeyForCache();
209 m_pFontFile = m_pDocument->GetFontFileStreamAcc(std::move(pFontFile));
210 if (!m_pFontFile)
211 return;
212
213 if (!m_Font.LoadEmbedded(m_pFontFile->GetSpan(), IsVertWriting(), key))
214 m_pDocument->MaybePurgeFontFileStreamAcc(std::move(m_pFontFile));
215 }
216
CheckFontMetrics()217 void CPDF_Font::CheckFontMetrics() {
218 if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
219 m_FontBBox.right == 0) {
220 FXFT_FaceRec* face = m_Font.GetFaceRec();
221 if (face) {
222 m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
223 m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
224 m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
225 m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
226 m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
227 m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
228 } else {
229 bool bFirst = true;
230 for (int i = 0; i < 256; i++) {
231 FX_RECT rect = GetCharBBox(i);
232 if (rect.left == rect.right) {
233 continue;
234 }
235 if (bFirst) {
236 m_FontBBox = rect;
237 bFirst = false;
238 } else {
239 m_FontBBox.left = std::min(m_FontBBox.left, rect.left);
240 m_FontBBox.top = std::max(m_FontBBox.top, rect.top);
241 m_FontBBox.right = std::max(m_FontBBox.right, rect.right);
242 m_FontBBox.bottom = std::min(m_FontBBox.bottom, rect.bottom);
243 }
244 }
245 }
246 }
247 if (m_Ascent == 0 && m_Descent == 0) {
248 FX_RECT rect = GetCharBBox('A');
249 m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
250 rect = GetCharBBox('g');
251 m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
252 }
253 }
254
LoadUnicodeMap() const255 void CPDF_Font::LoadUnicodeMap() const {
256 m_bToUnicodeLoaded = true;
257 RetainPtr<const CPDF_Stream> pStream = m_pFontDict->GetStreamFor("ToUnicode");
258 if (!pStream)
259 return;
260
261 m_pToUnicodeMap = std::make_unique<CPDF_ToUnicodeMap>(std::move(pStream));
262 }
263
GetStringWidth(ByteStringView pString)264 int CPDF_Font::GetStringWidth(ByteStringView pString) {
265 size_t offset = 0;
266 int width = 0;
267 while (offset < pString.GetLength())
268 width += GetCharWidthF(GetNextChar(pString, &offset));
269 return width;
270 }
271
272 // static
GetStockFont(CPDF_Document * pDoc,ByteStringView name)273 RetainPtr<CPDF_Font> CPDF_Font::GetStockFont(CPDF_Document* pDoc,
274 ByteStringView name) {
275 ByteString fontname(name);
276 absl::optional<CFX_FontMapper::StandardFont> font_id =
277 CFX_FontMapper::GetStandardFontName(&fontname);
278 if (!font_id.has_value())
279 return nullptr;
280
281 auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
282 RetainPtr<CPDF_Font> pFont = pFontGlobals->Find(pDoc, font_id.value());
283 if (pFont)
284 return pFont;
285
286 auto pDict = pDoc->New<CPDF_Dictionary>();
287 pDict->SetNewFor<CPDF_Name>("Type", "Font");
288 pDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
289 pDict->SetNewFor<CPDF_Name>("BaseFont", fontname);
290 pDict->SetNewFor<CPDF_Name>("Encoding",
291 pdfium::font_encodings::kWinAnsiEncoding);
292 pFont = CPDF_Font::Create(nullptr, std::move(pDict), nullptr);
293 pFontGlobals->Set(pDoc, font_id.value(), pFont);
294 return pFont;
295 }
296
297 // static
Create(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pFontDict,FormFactoryIface * pFactory)298 RetainPtr<CPDF_Font> CPDF_Font::Create(CPDF_Document* pDoc,
299 RetainPtr<CPDF_Dictionary> pFontDict,
300 FormFactoryIface* pFactory) {
301 ByteString type = pFontDict->GetByteStringFor("Subtype");
302 RetainPtr<CPDF_Font> pFont;
303 if (type == "TrueType") {
304 ByteString tag = pFontDict->GetByteStringFor("BaseFont").First(4);
305 for (size_t i = 0; i < std::size(kChineseFontNames); ++i) {
306 if (tag == ByteString(kChineseFontNames[i], kChineseFontNameSize)) {
307 RetainPtr<const CPDF_Dictionary> pFontDesc =
308 pFontDict->GetDictFor("FontDescriptor");
309 if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
310 pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, std::move(pFontDict));
311 break;
312 }
313 }
314 if (!pFont)
315 pFont = pdfium::MakeRetain<CPDF_TrueTypeFont>(pDoc, std::move(pFontDict));
316 } else if (type == "Type3") {
317 pFont = pdfium::MakeRetain<CPDF_Type3Font>(pDoc, std::move(pFontDict),
318 pFactory);
319 } else if (type == "Type0") {
320 pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, std::move(pFontDict));
321 } else {
322 pFont = pdfium::MakeRetain<CPDF_Type1Font>(pDoc, std::move(pFontDict));
323 }
324 if (!pFont->Load())
325 return nullptr;
326
327 return pFont;
328 }
329
GetNextChar(ByteStringView pString,size_t * pOffset) const330 uint32_t CPDF_Font::GetNextChar(ByteStringView pString, size_t* pOffset) const {
331 if (pString.IsEmpty())
332 return 0;
333
334 size_t& offset = *pOffset;
335 return offset < pString.GetLength() ? pString[offset++] : pString.Back();
336 }
337
IsStandardFont() const338 bool CPDF_Font::IsStandardFont() const {
339 if (!IsType1Font())
340 return false;
341 if (m_pFontFile)
342 return false;
343 return AsType1Font()->IsBase14Font();
344 }
345
GetSubstFontCharset() const346 absl::optional<FX_Charset> CPDF_Font::GetSubstFontCharset() const {
347 CFX_SubstFont* pFont = m_Font.GetSubstFont();
348 if (!pFont)
349 return absl::nullopt;
350 return pFont->m_Charset;
351 }
352
353 // static
GetAdobeCharName(FontEncoding base_encoding,const std::vector<ByteString> & charnames,uint32_t charcode)354 const char* CPDF_Font::GetAdobeCharName(
355 FontEncoding base_encoding,
356 const std::vector<ByteString>& charnames,
357 uint32_t charcode) {
358 if (charcode >= 256)
359 return nullptr;
360
361 if (!charnames.empty() && !charnames[charcode].IsEmpty())
362 return charnames[charcode].c_str();
363
364 const char* name = nullptr;
365 if (base_encoding != FontEncoding::kBuiltin)
366 name = CharNameFromPredefinedCharSet(base_encoding, charcode);
367 if (!name)
368 return nullptr;
369
370 DCHECK(name[0]);
371 return name;
372 }
373
FallbackFontFromCharcode(uint32_t charcode)374 uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) {
375 if (m_FontFallbacks.empty()) {
376 m_FontFallbacks.push_back(std::make_unique<CFX_Font>());
377 FX_SAFE_INT32 safeWeight = m_StemV;
378 safeWeight *= 5;
379 m_FontFallbacks[0]->LoadSubst("Arial", IsTrueTypeFont(), m_Flags,
380 safeWeight.ValueOrDefault(FXFONT_FW_NORMAL),
381 m_ItalicAngle, FX_CodePage::kDefANSI,
382 IsVertWriting());
383 }
384 return 0;
385 }
386
FallbackGlyphFromCharcode(int fallbackFont,uint32_t charcode)387 int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) {
388 if (!fxcrt::IndexInBounds(m_FontFallbacks, fallbackFont))
389 return -1;
390
391 WideString str = UnicodeFromCharCode(charcode);
392 uint32_t unicode = !str.IsEmpty() ? str[0] : charcode;
393 int glyph =
394 FT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFaceRec(), unicode);
395 if (glyph == 0)
396 return -1;
397
398 return glyph;
399 }
400
GetFontFallback(int position)401 CFX_Font* CPDF_Font::GetFontFallback(int position) {
402 if (position < 0 || static_cast<size_t>(position) >= m_FontFallbacks.size())
403 return nullptr;
404 return m_FontFallbacks[position].get();
405 }
406
407 // static
TT2PDF(FT_Pos m,FXFT_FaceRec * face)408 int CPDF_Font::TT2PDF(FT_Pos m, FXFT_FaceRec* face) {
409 int upm = FXFT_Get_Face_UnitsPerEM(face);
410 if (upm == 0)
411 return pdfium::base::saturated_cast<int>(m);
412
413 const double dm = (m * 1000.0 + upm / 2) / upm;
414 return pdfium::base::saturated_cast<int>(dm);
415 }
416
417 // static
UseTTCharmap(FXFT_FaceRec * face,int platform_id,int encoding_id)418 bool CPDF_Font::UseTTCharmap(FXFT_FaceRec* face,
419 int platform_id,
420 int encoding_id) {
421 for (int i = 0; i < face->num_charmaps; i++) {
422 if (FXFT_Get_Charmap_PlatformID(face->charmaps[i]) == platform_id &&
423 FXFT_Get_Charmap_EncodingID(face->charmaps[i]) == encoding_id) {
424 FT_Set_Charmap(face, face->charmaps[i]);
425 return true;
426 }
427 }
428 return false;
429 }
430
GetFontWeight() const431 int CPDF_Font::GetFontWeight() const {
432 FX_SAFE_INT32 safeStemV(m_StemV);
433 if (m_StemV < 140)
434 safeStemV *= 5;
435 else
436 safeStemV = safeStemV * 4 + 140;
437 return safeStemV.ValueOrDefault(FXFONT_FW_NORMAL);
438 }
439