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