1 // Copyright 2016 PDFium Authors. All rights reserved.
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 <limits>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "build/build_config.h"
15 #include "core/fpdfapi/font/cpdf_cidfont.h"
16 #include "core/fpdfapi/font/cpdf_fontencoding.h"
17 #include "core/fpdfapi/font/cpdf_fontglobals.h"
18 #include "core/fpdfapi/font/cpdf_tounicodemap.h"
19 #include "core/fpdfapi/font/cpdf_truetypefont.h"
20 #include "core/fpdfapi/font/cpdf_type1font.h"
21 #include "core/fpdfapi/font/cpdf_type3font.h"
22 #include "core/fpdfapi/parser/cpdf_array.h"
23 #include "core/fpdfapi/parser/cpdf_dictionary.h"
24 #include "core/fpdfapi/parser/cpdf_document.h"
25 #include "core/fpdfapi/parser/cpdf_name.h"
26 #include "core/fpdfapi/parser/cpdf_stream.h"
27 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
28 #include "core/fxcrt/fx_memory.h"
29 #include "core/fxge/cfx_fontmapper.h"
30 #include "core/fxge/fx_font.h"
31 #include "core/fxge/fx_freetype.h"
32 #include "third_party/base/logging.h"
33 #include "third_party/base/ptr_util.h"
34 #include "third_party/base/stl_util.h"
35 
36 namespace {
37 
38 constexpr size_t kChineseFontNameSize = 4;
39 const uint8_t kChineseFontNames[][kChineseFontNameSize] = {
40     {0xCB, 0xCE, 0xCC, 0xE5},
41     {0xBF, 0xAC, 0xCC, 0xE5},
42     {0xBA, 0xDA, 0xCC, 0xE5},
43     {0xB7, 0xC2, 0xCB, 0xCE},
44     {0xD0, 0xC2, 0xCB, 0xCE}};
45 
46 }  // namespace
47 
CPDF_Font(CPDF_Document * pDocument,CPDF_Dictionary * pFontDict)48 CPDF_Font::CPDF_Font(CPDF_Document* pDocument, CPDF_Dictionary* pFontDict)
49     : m_pDocument(pDocument),
50       m_pFontDict(pFontDict),
51       m_BaseFontName(pFontDict->GetStringFor("BaseFont")) {}
52 
~CPDF_Font()53 CPDF_Font::~CPDF_Font() {
54   if (m_pFontFile) {
55     auto* pPageData = m_pDocument->GetPageData();
56     if (pPageData) {
57       pPageData->MaybePurgeFontFileStreamAcc(
58           m_pFontFile->GetStream()->AsStream());
59     }
60   }
61 }
62 
IsType1Font() const63 bool CPDF_Font::IsType1Font() const {
64   return false;
65 }
66 
IsTrueTypeFont() const67 bool CPDF_Font::IsTrueTypeFont() const {
68   return false;
69 }
70 
IsType3Font() const71 bool CPDF_Font::IsType3Font() const {
72   return false;
73 }
74 
IsCIDFont() const75 bool CPDF_Font::IsCIDFont() const {
76   return false;
77 }
78 
AsType1Font() const79 const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
80   return nullptr;
81 }
82 
AsType1Font()83 CPDF_Type1Font* CPDF_Font::AsType1Font() {
84   return nullptr;
85 }
86 
AsTrueTypeFont() const87 const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
88   return nullptr;
89 }
90 
AsTrueTypeFont()91 CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
92   return nullptr;
93 }
94 
AsType3Font() const95 const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
96   return nullptr;
97 }
98 
AsType3Font()99 CPDF_Type3Font* CPDF_Font::AsType3Font() {
100   return nullptr;
101 }
102 
AsCIDFont() const103 const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
104   return nullptr;
105 }
106 
AsCIDFont()107 CPDF_CIDFont* CPDF_Font::AsCIDFont() {
108   return nullptr;
109 }
110 
IsUnicodeCompatible() const111 bool CPDF_Font::IsUnicodeCompatible() const {
112   return false;
113 }
114 
CountChar(ByteStringView pString) const115 size_t CPDF_Font::CountChar(ByteStringView pString) const {
116   return pString.GetLength();
117 }
118 
119 #if defined(OS_MACOSX)
GlyphFromCharCodeExt(uint32_t charcode)120 int CPDF_Font::GlyphFromCharCodeExt(uint32_t charcode) {
121   return GlyphFromCharCode(charcode, nullptr);
122 }
123 #endif
124 
WillBeDestroyed()125 void CPDF_Font::WillBeDestroyed() {}
126 
IsVertWriting() const127 bool CPDF_Font::IsVertWriting() const {
128   const CPDF_CIDFont* pCIDFont = AsCIDFont();
129   return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
130 }
131 
AppendChar(char * buf,uint32_t charcode) const132 int CPDF_Font::AppendChar(char* buf, uint32_t charcode) const {
133   *buf = static_cast<char>(charcode);
134   return 1;
135 }
136 
AppendChar(ByteString * str,uint32_t charcode) const137 void CPDF_Font::AppendChar(ByteString* str, uint32_t charcode) const {
138   char buf[4];
139   int len = AppendChar(buf, charcode);
140   *str += ByteStringView(buf, len);
141 }
142 
UnicodeFromCharCode(uint32_t charcode) const143 WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
144   if (!m_bToUnicodeLoaded)
145     LoadUnicodeMap();
146 
147   return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : WideString();
148 }
149 
CharCodeFromUnicode(wchar_t unicode) const150 uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const {
151   if (!m_bToUnicodeLoaded)
152     LoadUnicodeMap();
153 
154   return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
155 }
156 
HasFontWidths() const157 bool CPDF_Font::HasFontWidths() const {
158   return true;
159 }
160 
LoadFontDescriptor(const CPDF_Dictionary * pFontDesc)161 void CPDF_Font::LoadFontDescriptor(const CPDF_Dictionary* pFontDesc) {
162   m_Flags = pFontDesc->GetIntegerFor("Flags", FXFONT_NONSYMBOLIC);
163   int ItalicAngle = 0;
164   bool bExistItalicAngle = false;
165   if (pFontDesc->KeyExist("ItalicAngle")) {
166     ItalicAngle = pFontDesc->GetIntegerFor("ItalicAngle");
167     bExistItalicAngle = true;
168   }
169   if (ItalicAngle < 0) {
170     m_Flags |= FXFONT_ITALIC;
171     m_ItalicAngle = ItalicAngle;
172   }
173   bool bExistStemV = false;
174   if (pFontDesc->KeyExist("StemV")) {
175     m_StemV = pFontDesc->GetIntegerFor("StemV");
176     bExistStemV = true;
177   }
178   bool bExistAscent = false;
179   if (pFontDesc->KeyExist("Ascent")) {
180     m_Ascent = pFontDesc->GetIntegerFor("Ascent");
181     bExistAscent = true;
182   }
183   bool bExistDescent = false;
184   if (pFontDesc->KeyExist("Descent")) {
185     m_Descent = pFontDesc->GetIntegerFor("Descent");
186     bExistDescent = true;
187   }
188   bool bExistCapHeight = false;
189   if (pFontDesc->KeyExist("CapHeight"))
190     bExistCapHeight = true;
191   if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
192       bExistStemV) {
193     m_Flags |= FXFONT_USEEXTERNATTR;
194   }
195   if (m_Descent > 10)
196     m_Descent = -m_Descent;
197   const CPDF_Array* pBBox = pFontDesc->GetArrayFor("FontBBox");
198   if (pBBox) {
199     m_FontBBox.left = pBBox->GetIntegerAt(0);
200     m_FontBBox.bottom = pBBox->GetIntegerAt(1);
201     m_FontBBox.right = pBBox->GetIntegerAt(2);
202     m_FontBBox.top = pBBox->GetIntegerAt(3);
203   }
204 
205   const CPDF_Stream* pFontFile = pFontDesc->GetStreamFor("FontFile");
206   if (!pFontFile)
207     pFontFile = pFontDesc->GetStreamFor("FontFile2");
208   if (!pFontFile)
209     pFontFile = pFontDesc->GetStreamFor("FontFile3");
210   if (!pFontFile)
211     return;
212 
213   auto* pData = m_pDocument->GetPageData();
214   m_pFontFile = pData->GetFontFileStreamAcc(pFontFile);
215   if (!m_pFontFile)
216     return;
217 
218   if (!m_Font.LoadEmbedded(m_pFontFile->GetSpan(), IsVertWriting())) {
219     pData->MaybePurgeFontFileStreamAcc(m_pFontFile->GetStream()->AsStream());
220     m_pFontFile = nullptr;
221   }
222 }
223 
CheckFontMetrics()224 void CPDF_Font::CheckFontMetrics() {
225   if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
226       m_FontBBox.right == 0) {
227     FXFT_FaceRec* face = m_Font.GetFaceRec();
228     if (face) {
229       m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
230       m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
231       m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
232       m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
233       m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
234       m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
235     } else {
236       bool bFirst = true;
237       for (int i = 0; i < 256; i++) {
238         FX_RECT rect = GetCharBBox(i);
239         if (rect.left == rect.right) {
240           continue;
241         }
242         if (bFirst) {
243           m_FontBBox = rect;
244           bFirst = false;
245         } else {
246           if (m_FontBBox.top < rect.top) {
247             m_FontBBox.top = rect.top;
248           }
249           if (m_FontBBox.right < rect.right) {
250             m_FontBBox.right = rect.right;
251           }
252           if (m_FontBBox.left > rect.left) {
253             m_FontBBox.left = rect.left;
254           }
255           if (m_FontBBox.bottom > rect.bottom) {
256             m_FontBBox.bottom = rect.bottom;
257           }
258         }
259       }
260     }
261   }
262   if (m_Ascent == 0 && m_Descent == 0) {
263     FX_RECT rect = GetCharBBox('A');
264     m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
265     rect = GetCharBBox('g');
266     m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
267   }
268 }
269 
LoadUnicodeMap() const270 void CPDF_Font::LoadUnicodeMap() const {
271   m_bToUnicodeLoaded = true;
272   const CPDF_Stream* pStream = m_pFontDict->GetStreamFor("ToUnicode");
273   if (!pStream)
274     return;
275 
276   m_pToUnicodeMap = pdfium::MakeUnique<CPDF_ToUnicodeMap>(pStream);
277 }
278 
GetStringWidth(ByteStringView pString)279 uint32_t CPDF_Font::GetStringWidth(ByteStringView pString) {
280   size_t offset = 0;
281   uint32_t width = 0;
282   while (offset < pString.GetLength())
283     width += GetCharWidthF(GetNextChar(pString, &offset));
284   return width;
285 }
286 
287 // static
GetStockFont(CPDF_Document * pDoc,ByteStringView name)288 RetainPtr<CPDF_Font> CPDF_Font::GetStockFont(CPDF_Document* pDoc,
289                                              ByteStringView name) {
290   ByteString fontname(name);
291   Optional<CFX_FontMapper::StandardFont> font_id =
292       CFX_FontMapper::GetStandardFontName(&fontname);
293   if (!font_id.has_value())
294     return nullptr;
295 
296   auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
297   RetainPtr<CPDF_Font> pFont = pFontGlobals->Find(pDoc, font_id.value());
298   if (pFont)
299     return pFont;
300 
301   auto pDict = pDoc->New<CPDF_Dictionary>();
302   pDict->SetNewFor<CPDF_Name>("Type", "Font");
303   pDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
304   pDict->SetNewFor<CPDF_Name>("BaseFont", fontname);
305   pDict->SetNewFor<CPDF_Name>("Encoding", "WinAnsiEncoding");
306   pFont = CPDF_Font::Create(nullptr, pDict.Get(), nullptr);
307   pFontGlobals->Set(pDoc, font_id.value(), pFont);
308   return pFont;
309 }
310 
311 // static
Create(CPDF_Document * pDoc,CPDF_Dictionary * pFontDict,FormFactoryIface * pFactory)312 RetainPtr<CPDF_Font> CPDF_Font::Create(CPDF_Document* pDoc,
313                                        CPDF_Dictionary* pFontDict,
314                                        FormFactoryIface* pFactory) {
315   ByteString type = pFontDict->GetStringFor("Subtype");
316   RetainPtr<CPDF_Font> pFont;
317   if (type == "TrueType") {
318     ByteString tag = pFontDict->GetStringFor("BaseFont").First(4);
319     for (size_t i = 0; i < FX_ArraySize(kChineseFontNames); ++i) {
320       if (tag == ByteString(kChineseFontNames[i], kChineseFontNameSize)) {
321         const CPDF_Dictionary* pFontDesc =
322             pFontDict->GetDictFor("FontDescriptor");
323         if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
324           pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, pFontDict);
325         break;
326       }
327     }
328     if (!pFont)
329       pFont = pdfium::MakeRetain<CPDF_TrueTypeFont>(pDoc, pFontDict);
330   } else if (type == "Type3") {
331     pFont = pdfium::MakeRetain<CPDF_Type3Font>(pDoc, pFontDict, pFactory);
332   } else if (type == "Type0") {
333     pFont = pdfium::MakeRetain<CPDF_CIDFont>(pDoc, pFontDict);
334   } else {
335     pFont = pdfium::MakeRetain<CPDF_Type1Font>(pDoc, pFontDict);
336   }
337   if (!pFont->Load())
338     return nullptr;
339 
340   return pFont;
341 }
342 
GetNextChar(ByteStringView pString,size_t * pOffset) const343 uint32_t CPDF_Font::GetNextChar(ByteStringView pString, size_t* pOffset) const {
344   if (pString.IsEmpty())
345     return 0;
346 
347   size_t& offset = *pOffset;
348   return offset < pString.GetLength() ? pString[offset++] : pString.Back();
349 }
350 
IsStandardFont() const351 bool CPDF_Font::IsStandardFont() const {
352   if (!IsType1Font())
353     return false;
354   if (m_pFontFile)
355     return false;
356   return AsType1Font()->IsBase14Font();
357 }
358 
359 // static
GetAdobeCharName(int iBaseEncoding,const std::vector<ByteString> & charnames,uint32_t charcode)360 const char* CPDF_Font::GetAdobeCharName(
361     int iBaseEncoding,
362     const std::vector<ByteString>& charnames,
363     uint32_t charcode) {
364   if (charcode >= 256)
365     return nullptr;
366 
367   if (!charnames.empty() && !charnames[charcode].IsEmpty())
368     return charnames[charcode].c_str();
369 
370   const char* name = nullptr;
371   if (iBaseEncoding)
372     name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
373   if (!name)
374     return nullptr;
375 
376   ASSERT(name[0]);
377   return name;
378 }
379 
FallbackFontFromCharcode(uint32_t charcode)380 uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) {
381   if (m_FontFallbacks.empty()) {
382     m_FontFallbacks.push_back(pdfium::MakeUnique<CFX_Font>());
383     pdfium::base::CheckedNumeric<int> safeWeight = m_StemV;
384     safeWeight *= 5;
385     m_FontFallbacks[0]->LoadSubst("Arial", IsTrueTypeFont(), m_Flags,
386                                   safeWeight.ValueOrDefault(FXFONT_FW_NORMAL),
387                                   m_ItalicAngle, 0, IsVertWriting());
388   }
389   return 0;
390 }
391 
FallbackGlyphFromCharcode(int fallbackFont,uint32_t charcode)392 int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) {
393   if (!pdfium::IndexInBounds(m_FontFallbacks, fallbackFont))
394     return -1;
395 
396   WideString str = UnicodeFromCharCode(charcode);
397   uint32_t unicode = !str.IsEmpty() ? str[0] : charcode;
398   int glyph =
399       FT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFaceRec(), unicode);
400   if (glyph == 0)
401     return -1;
402 
403   return glyph;
404 }
405 
GetFontFallback(int position)406 CFX_Font* CPDF_Font::GetFontFallback(int position) {
407   if (position < 0 || static_cast<size_t>(position) >= m_FontFallbacks.size())
408     return nullptr;
409   return m_FontFallbacks[position].get();
410 }
411 
412 // static
TT2PDF(int m,FXFT_FaceRec * face)413 int CPDF_Font::TT2PDF(int m, FXFT_FaceRec* face) {
414   int upm = FXFT_Get_Face_UnitsPerEM(face);
415   if (upm == 0)
416     return m;
417 
418   return static_cast<int>(
419       pdfium::clamp((m * 1000.0 + upm / 2) / upm,
420                     static_cast<double>(std::numeric_limits<int>::min()),
421                     static_cast<double>(std::numeric_limits<int>::max())));
422 }
423 
424 // static
FT_UseTTCharmap(FXFT_FaceRec * face,int platform_id,int encoding_id)425 bool CPDF_Font::FT_UseTTCharmap(FXFT_FaceRec* face,
426                                 int platform_id,
427                                 int encoding_id) {
428   auto** pCharMap = FXFT_Get_Face_Charmaps(face);
429   for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
430     if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id &&
431         FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) {
432       FT_Set_Charmap(face, pCharMap[i]);
433       return true;
434     }
435   }
436   return false;
437 }
438 
GetFontWeight() const439 int CPDF_Font::GetFontWeight() const {
440   pdfium::base::CheckedNumeric<int> safeStemV(m_StemV);
441   if (m_StemV < 140)
442     safeStemV *= 5;
443   else
444     safeStemV = safeStemV * 4 + 140;
445   return safeStemV.ValueOrDefault(FXFONT_FW_NORMAL);
446 }
447