• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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