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/fpdf_font/include/cpdf_font.h"
8 
9 #include "core/fpdfapi/fpdf_font/cpdf_truetypefont.h"
10 #include "core/fpdfapi/fpdf_font/cpdf_type1font.h"
11 #include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
12 #include "core/fpdfapi/fpdf_font/font_int.h"
13 #include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
14 #include "core/fpdfapi/fpdf_page/cpdf_pagemodule.h"
15 #include "core/fpdfapi/fpdf_page/pageint.h"
16 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
17 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
18 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
19 #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
20 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
21 #include "core/fpdfapi/include/cpdf_modulemgr.h"
22 #include "core/fxge/include/fx_freetype.h"
23 
24 namespace {
25 
26 const uint8_t ChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00},
27                                        {0xBF, 0xAC, 0xCC, 0xE5, 0x00},
28                                        {0xBA, 0xDA, 0xCC, 0xE5, 0x00},
29                                        {0xB7, 0xC2, 0xCB, 0xCE, 0x00},
30                                        {0xD0, 0xC2, 0xCB, 0xCE, 0x00}};
31 
GetPredefinedEncoding(int & basemap,const CFX_ByteString & value)32 FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value) {
33   if (value == "WinAnsiEncoding")
34     basemap = PDFFONT_ENCODING_WINANSI;
35   else if (value == "MacRomanEncoding")
36     basemap = PDFFONT_ENCODING_MACROMAN;
37   else if (value == "MacExpertEncoding")
38     basemap = PDFFONT_ENCODING_MACEXPERT;
39   else if (value == "PDFDocEncoding")
40     basemap = PDFFONT_ENCODING_PDFDOC;
41   else
42     return FALSE;
43   return TRUE;
44 }
45 
46 }  // namespace
47 
CPDF_Font()48 CPDF_Font::CPDF_Font()
49     : m_pFontFile(nullptr),
50       m_pFontDict(nullptr),
51       m_bToUnicodeLoaded(FALSE),
52       m_Flags(0),
53       m_StemV(0),
54       m_Ascent(0),
55       m_Descent(0),
56       m_ItalicAngle(0) {}
57 
~CPDF_Font()58 CPDF_Font::~CPDF_Font() {
59   if (m_pFontFile) {
60     m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
61         const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
62   }
63 }
64 
IsType1Font() const65 bool CPDF_Font::IsType1Font() const {
66   return false;
67 }
68 
IsTrueTypeFont() const69 bool CPDF_Font::IsTrueTypeFont() const {
70   return false;
71 }
72 
IsType3Font() const73 bool CPDF_Font::IsType3Font() const {
74   return false;
75 }
76 
IsCIDFont() const77 bool CPDF_Font::IsCIDFont() const {
78   return false;
79 }
80 
AsType1Font() const81 const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
82   return nullptr;
83 }
84 
AsType1Font()85 CPDF_Type1Font* CPDF_Font::AsType1Font() {
86   return nullptr;
87 }
88 
AsTrueTypeFont() const89 const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
90   return nullptr;
91 }
92 
AsTrueTypeFont()93 CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
94   return nullptr;
95 }
96 
AsType3Font() const97 const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
98   return nullptr;
99 }
100 
AsType3Font()101 CPDF_Type3Font* CPDF_Font::AsType3Font() {
102   return nullptr;
103 }
104 
AsCIDFont() const105 const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
106   return nullptr;
107 }
108 
AsCIDFont()109 CPDF_CIDFont* CPDF_Font::AsCIDFont() {
110   return nullptr;
111 }
112 
IsUnicodeCompatible() const113 FX_BOOL CPDF_Font::IsUnicodeCompatible() const {
114   return FALSE;
115 }
116 
CountChar(const FX_CHAR * pString,int size) const117 int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const {
118   return size;
119 }
120 
GetCharSize(uint32_t charcode) const121 int CPDF_Font::GetCharSize(uint32_t charcode) const {
122   return 1;
123 }
124 
GlyphFromCharCodeExt(uint32_t charcode)125 int CPDF_Font::GlyphFromCharCodeExt(uint32_t charcode) {
126   return GlyphFromCharCode(charcode, nullptr);
127 }
128 
IsVertWriting() const129 FX_BOOL CPDF_Font::IsVertWriting() const {
130   const CPDF_CIDFont* pCIDFont = AsCIDFont();
131   return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
132 }
133 
AppendChar(FX_CHAR * buf,uint32_t charcode) const134 int CPDF_Font::AppendChar(FX_CHAR* buf, uint32_t charcode) const {
135   *buf = static_cast<FX_CHAR>(charcode);
136   return 1;
137 }
138 
AppendChar(CFX_ByteString & str,uint32_t charcode) const139 void CPDF_Font::AppendChar(CFX_ByteString& str, uint32_t charcode) const {
140   char buf[4];
141   int len = AppendChar(buf, charcode);
142   if (len == 1) {
143     str += buf[0];
144   } else {
145     str += CFX_ByteString(buf, len);
146   }
147 }
148 
UnicodeFromCharCode(uint32_t charcode) const149 CFX_WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
150   if (!m_bToUnicodeLoaded)
151     LoadUnicodeMap();
152 
153   return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : CFX_WideString();
154 }
155 
CharCodeFromUnicode(FX_WCHAR unicode) const156 uint32_t CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const {
157   if (!m_bToUnicodeLoaded)
158     LoadUnicodeMap();
159 
160   return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
161 }
162 
LoadFontDescriptor(CPDF_Dictionary * pFontDesc)163 void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) {
164   m_Flags = pFontDesc->GetIntegerBy("Flags", PDFFONT_NONSYMBOLIC);
165   int ItalicAngle = 0;
166   FX_BOOL bExistItalicAngle = FALSE;
167   if (pFontDesc->KeyExist("ItalicAngle")) {
168     ItalicAngle = pFontDesc->GetIntegerBy("ItalicAngle");
169     bExistItalicAngle = TRUE;
170   }
171   if (ItalicAngle < 0) {
172     m_Flags |= PDFFONT_ITALIC;
173     m_ItalicAngle = ItalicAngle;
174   }
175   FX_BOOL bExistStemV = FALSE;
176   if (pFontDesc->KeyExist("StemV")) {
177     m_StemV = pFontDesc->GetIntegerBy("StemV");
178     bExistStemV = TRUE;
179   }
180   FX_BOOL bExistAscent = FALSE;
181   if (pFontDesc->KeyExist("Ascent")) {
182     m_Ascent = pFontDesc->GetIntegerBy("Ascent");
183     bExistAscent = TRUE;
184   }
185   FX_BOOL bExistDescent = FALSE;
186   if (pFontDesc->KeyExist("Descent")) {
187     m_Descent = pFontDesc->GetIntegerBy("Descent");
188     bExistDescent = TRUE;
189   }
190   FX_BOOL bExistCapHeight = FALSE;
191   if (pFontDesc->KeyExist("CapHeight")) {
192     bExistCapHeight = TRUE;
193   }
194   if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
195       bExistStemV) {
196     m_Flags |= PDFFONT_USEEXTERNATTR;
197   }
198   if (m_Descent > 10) {
199     m_Descent = -m_Descent;
200   }
201   CPDF_Array* pBBox = pFontDesc->GetArrayBy("FontBBox");
202   if (pBBox) {
203     m_FontBBox.left = pBBox->GetIntegerAt(0);
204     m_FontBBox.bottom = pBBox->GetIntegerAt(1);
205     m_FontBBox.right = pBBox->GetIntegerAt(2);
206     m_FontBBox.top = pBBox->GetIntegerAt(3);
207   }
208 
209   CPDF_Stream* pFontFile = pFontDesc->GetStreamBy("FontFile");
210   if (!pFontFile)
211     pFontFile = pFontDesc->GetStreamBy("FontFile2");
212   if (!pFontFile)
213     pFontFile = pFontDesc->GetStreamBy("FontFile3");
214   if (!pFontFile)
215     return;
216 
217   m_pFontFile = m_pDocument->LoadFontFile(pFontFile);
218   if (!m_pFontFile)
219     return;
220 
221   const uint8_t* pFontData = m_pFontFile->GetData();
222   uint32_t dwFontSize = m_pFontFile->GetSize();
223   if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) {
224     m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
225         const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
226     m_pFontFile = nullptr;
227   }
228 }
229 
CheckFontMetrics()230 void CPDF_Font::CheckFontMetrics() {
231   if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
232       m_FontBBox.right == 0) {
233     FXFT_Face face = m_Font.GetFace();
234     if (face) {
235       m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
236       m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
237       m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
238       m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
239       m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
240       m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
241     } else {
242       FX_BOOL bFirst = TRUE;
243       for (int i = 0; i < 256; i++) {
244         FX_RECT rect = GetCharBBox(i);
245         if (rect.left == rect.right) {
246           continue;
247         }
248         if (bFirst) {
249           m_FontBBox = rect;
250           bFirst = FALSE;
251         } else {
252           if (m_FontBBox.top < rect.top) {
253             m_FontBBox.top = rect.top;
254           }
255           if (m_FontBBox.right < rect.right) {
256             m_FontBBox.right = rect.right;
257           }
258           if (m_FontBBox.left > rect.left) {
259             m_FontBBox.left = rect.left;
260           }
261           if (m_FontBBox.bottom > rect.bottom) {
262             m_FontBBox.bottom = rect.bottom;
263           }
264         }
265       }
266     }
267   }
268   if (m_Ascent == 0 && m_Descent == 0) {
269     FX_RECT rect = GetCharBBox('A');
270     m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
271     rect = GetCharBBox('g');
272     m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
273   }
274 }
275 
LoadUnicodeMap() const276 void CPDF_Font::LoadUnicodeMap() const {
277   m_bToUnicodeLoaded = TRUE;
278   CPDF_Stream* pStream = m_pFontDict->GetStreamBy("ToUnicode");
279   if (!pStream) {
280     return;
281   }
282   m_pToUnicodeMap.reset(new CPDF_ToUnicodeMap);
283   m_pToUnicodeMap->Load(pStream);
284 }
285 
GetStringWidth(const FX_CHAR * pString,int size)286 int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) {
287   int offset = 0;
288   int width = 0;
289   while (offset < size) {
290     uint32_t charcode = GetNextChar(pString, size, offset);
291     width += GetCharWidthF(charcode);
292   }
293   return width;
294 }
295 
GetStockFont(CPDF_Document * pDoc,const CFX_ByteStringC & name)296 CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc,
297                                    const CFX_ByteStringC& name) {
298   CFX_ByteString fontname(name);
299   int font_id = PDF_GetStandardFontName(&fontname);
300   if (font_id < 0) {
301     return nullptr;
302   }
303   CPDF_FontGlobals* pFontGlobals =
304       CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
305   CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
306   if (pFont) {
307     return pFont;
308   }
309   CPDF_Dictionary* pDict = new CPDF_Dictionary;
310   pDict->SetAtName("Type", "Font");
311   pDict->SetAtName("Subtype", "Type1");
312   pDict->SetAtName("BaseFont", fontname);
313   pDict->SetAtName("Encoding", "WinAnsiEncoding");
314   pFont = CPDF_Font::CreateFontF(nullptr, pDict);
315   pFontGlobals->Set(pDoc, font_id, pFont);
316   return pFont;
317 }
318 
CreateFontF(CPDF_Document * pDoc,CPDF_Dictionary * pFontDict)319 CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc,
320                                   CPDF_Dictionary* pFontDict) {
321   CFX_ByteString type = pFontDict->GetStringBy("Subtype");
322   std::unique_ptr<CPDF_Font> pFont;
323   if (type == "TrueType") {
324     CFX_ByteString tag = pFontDict->GetStringBy("BaseFont").Left(4);
325     for (size_t i = 0; i < FX_ArraySize(ChineseFontNames); ++i) {
326       if (tag == CFX_ByteString(ChineseFontNames[i], 4)) {
327         CPDF_Dictionary* pFontDesc = pFontDict->GetDictBy("FontDescriptor");
328         if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
329           pFont.reset(new CPDF_CIDFont);
330         break;
331       }
332     }
333     if (!pFont)
334       pFont.reset(new CPDF_TrueTypeFont);
335   } else if (type == "Type3") {
336     pFont.reset(new CPDF_Type3Font);
337   } else if (type == "Type0") {
338     pFont.reset(new CPDF_CIDFont);
339   } else {
340     pFont.reset(new CPDF_Type1Font);
341   }
342   pFont->m_pFontDict = pFontDict;
343   pFont->m_pDocument = pDoc;
344   pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
345   return pFont->Load() ? pFont.release() : nullptr;
346 }
347 
GetNextChar(const FX_CHAR * pString,int nStrLen,int & offset) const348 uint32_t CPDF_Font::GetNextChar(const FX_CHAR* pString,
349                                 int nStrLen,
350                                 int& offset) const {
351   if (offset < 0 || nStrLen < 1) {
352     return 0;
353   }
354   uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1];
355   return static_cast<uint32_t>(ch);
356 }
357 
LoadPDFEncoding(CPDF_Object * pEncoding,int & iBaseEncoding,CFX_ByteString * & pCharNames,FX_BOOL bEmbedded,FX_BOOL bTrueType)358 void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding,
359                                 int& iBaseEncoding,
360                                 CFX_ByteString*& pCharNames,
361                                 FX_BOOL bEmbedded,
362                                 FX_BOOL bTrueType) {
363   if (!pEncoding) {
364     if (m_BaseFont == "Symbol") {
365       iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL
366                                 : PDFFONT_ENCODING_ADOBE_SYMBOL;
367     } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
368       iBaseEncoding = PDFFONT_ENCODING_WINANSI;
369     }
370     return;
371   }
372   if (pEncoding->IsName()) {
373     if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL ||
374         iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {
375       return;
376     }
377     if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == "Symbol") {
378       if (!bTrueType) {
379         iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
380       }
381       return;
382     }
383     CFX_ByteString bsEncoding = pEncoding->GetString();
384     if (bsEncoding.Compare("MacExpertEncoding") == 0) {
385       bsEncoding = "WinAnsiEncoding";
386     }
387     GetPredefinedEncoding(iBaseEncoding, bsEncoding);
388     return;
389   }
390 
391   CPDF_Dictionary* pDict = pEncoding->AsDictionary();
392   if (!pDict)
393     return;
394 
395   if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
396       iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {
397     CFX_ByteString bsEncoding = pDict->GetStringBy("BaseEncoding");
398     if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) {
399       bsEncoding = "WinAnsiEncoding";
400     }
401     GetPredefinedEncoding(iBaseEncoding, bsEncoding);
402   }
403   if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
404     iBaseEncoding = PDFFONT_ENCODING_STANDARD;
405   }
406   CPDF_Array* pDiffs = pDict->GetArrayBy("Differences");
407   if (!pDiffs) {
408     return;
409   }
410   pCharNames = new CFX_ByteString[256];
411   uint32_t cur_code = 0;
412   for (uint32_t i = 0; i < pDiffs->GetCount(); i++) {
413     CPDF_Object* pElement = pDiffs->GetDirectObjectAt(i);
414     if (!pElement)
415       continue;
416 
417     if (CPDF_Name* pName = pElement->AsName()) {
418       if (cur_code < 256)
419         pCharNames[cur_code] = pName->GetString();
420       cur_code++;
421     } else {
422       cur_code = pElement->GetInteger();
423     }
424   }
425 }
426 
IsStandardFont() const427 FX_BOOL CPDF_Font::IsStandardFont() const {
428   if (!IsType1Font())
429     return FALSE;
430   if (m_pFontFile)
431     return FALSE;
432   if (AsType1Font()->GetBase14Font() < 0)
433     return FALSE;
434   return TRUE;
435 }
436 
GetAdobeCharName(int iBaseEncoding,const CFX_ByteString * pCharNames,int charcode)437 const FX_CHAR* CPDF_Font::GetAdobeCharName(int iBaseEncoding,
438                                            const CFX_ByteString* pCharNames,
439                                            int charcode) {
440   if (charcode < 0 || charcode >= 256) {
441     ASSERT(false);
442     return nullptr;
443   }
444 
445   if (pCharNames && !pCharNames[charcode].IsEmpty())
446     return pCharNames[charcode].c_str();
447 
448   const FX_CHAR* name = nullptr;
449   if (iBaseEncoding)
450     name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
451   return name && name[0] ? name : nullptr;
452 }
453