• 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 <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