• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_type3font.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fpdfapi/font/cpdf_type3char.h"
13 #include "core/fpdfapi/page/cpdf_form.h"
14 #include "core/fpdfapi/parser/cpdf_array.h"
15 #include "core/fpdfapi/parser/cpdf_dictionary.h"
16 #include "core/fpdfapi/parser/cpdf_stream.h"
17 #include "core/fxcrt/fx_system.h"
18 #include "third_party/base/stl_util.h"
19 
20 namespace {
21 
22 constexpr int kMaxType3FormLevel = 4;
23 
24 }  // namespace
25 
CPDF_Type3Font()26 CPDF_Type3Font::CPDF_Type3Font() {
27   memset(m_CharWidthL, 0, sizeof(m_CharWidthL));
28 }
29 
~CPDF_Type3Font()30 CPDF_Type3Font::~CPDF_Type3Font() {}
31 
IsType3Font() const32 bool CPDF_Type3Font::IsType3Font() const {
33   return true;
34 }
35 
AsType3Font() const36 const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const {
37   return this;
38 }
39 
AsType3Font()40 CPDF_Type3Font* CPDF_Type3Font::AsType3Font() {
41   return this;
42 }
43 
Load()44 bool CPDF_Type3Font::Load() {
45   m_pFontResources = m_pFontDict->GetDictFor("Resources");
46   CPDF_Array* pMatrix = m_pFontDict->GetArrayFor("FontMatrix");
47   float xscale = 1.0f;
48   float yscale = 1.0f;
49   if (pMatrix) {
50     m_FontMatrix = pMatrix->GetMatrix();
51     xscale = m_FontMatrix.a;
52     yscale = m_FontMatrix.d;
53   }
54 
55   CPDF_Array* pBBox = m_pFontDict->GetArrayFor("FontBBox");
56   if (pBBox) {
57     CFX_FloatRect box(
58         pBBox->GetNumberAt(0) * xscale, pBBox->GetNumberAt(1) * yscale,
59         pBBox->GetNumberAt(2) * xscale, pBBox->GetNumberAt(3) * yscale);
60     CPDF_Type3Char::TextUnitRectToGlyphUnitRect(&box);
61     m_FontBBox = box.ToFxRect();
62   }
63 
64   static constexpr size_t kCharLimit = FX_ArraySize(m_CharWidthL);
65   int StartChar = m_pFontDict->GetIntegerFor("FirstChar");
66   if (StartChar >= 0 && static_cast<size_t>(StartChar) < kCharLimit) {
67     CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths");
68     if (pWidthArray) {
69       size_t count = std::min(pWidthArray->GetCount(), kCharLimit);
70       count = std::min(count, kCharLimit - StartChar);
71       for (size_t i = 0; i < count; i++) {
72         m_CharWidthL[StartChar + i] =
73             FXSYS_round(CPDF_Type3Char::TextUnitToGlyphUnit(
74                 pWidthArray->GetNumberAt(i) * xscale));
75       }
76     }
77   }
78   m_pCharProcs = m_pFontDict->GetDictFor("CharProcs");
79   CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectFor("Encoding");
80   if (pEncoding)
81     LoadPDFEncoding(pEncoding, m_BaseEncoding, &m_CharNames, false, false);
82   return true;
83 }
84 
LoadGlyphMap()85 void CPDF_Type3Font::LoadGlyphMap() {}
86 
CheckType3FontMetrics()87 void CPDF_Type3Font::CheckType3FontMetrics() {
88   CheckFontMetrics();
89 }
90 
LoadChar(uint32_t charcode)91 CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) {
92   if (m_CharLoadingDepth >= kMaxType3FormLevel)
93     return nullptr;
94 
95   auto it = m_CacheMap.find(charcode);
96   if (it != m_CacheMap.end())
97     return it->second.get();
98 
99   const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
100   if (!name)
101     return nullptr;
102 
103   CPDF_Stream* pStream =
104       ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectFor(name) : nullptr);
105   if (!pStream)
106     return nullptr;
107 
108   auto pNewChar =
109       pdfium::MakeUnique<CPDF_Type3Char>(pdfium::MakeUnique<CPDF_Form>(
110           m_pDocument.Get(),
111           m_pFontResources ? m_pFontResources.Get() : m_pPageResources.Get(),
112           pStream, nullptr));
113 
114   // This can trigger recursion into this method. The content of |m_CacheMap|
115   // can change as a result. Thus after it returns, check the cache again for
116   // a cache hit.
117   m_CharLoadingDepth++;
118   pNewChar->form()->ParseContentWithParams(nullptr, nullptr, pNewChar.get(), 0);
119   m_CharLoadingDepth--;
120   it = m_CacheMap.find(charcode);
121   if (it != m_CacheMap.end())
122     return it->second.get();
123 
124   pNewChar->Transform(m_FontMatrix);
125   m_CacheMap[charcode] = std::move(pNewChar);
126   CPDF_Type3Char* pCachedChar = m_CacheMap[charcode].get();
127   if (pCachedChar->form()->GetPageObjectList()->empty())
128     pCachedChar->ResetForm();
129   return pCachedChar;
130 }
131 
GetCharWidthF(uint32_t charcode)132 int CPDF_Type3Font::GetCharWidthF(uint32_t charcode) {
133   if (charcode >= FX_ArraySize(m_CharWidthL))
134     charcode = 0;
135 
136   if (m_CharWidthL[charcode])
137     return m_CharWidthL[charcode];
138 
139   const CPDF_Type3Char* pChar = LoadChar(charcode);
140   return pChar ? pChar->width() : 0;
141 }
142 
GetCharBBox(uint32_t charcode)143 FX_RECT CPDF_Type3Font::GetCharBBox(uint32_t charcode) {
144   FX_RECT ret;
145   const CPDF_Type3Char* pChar = LoadChar(charcode);
146   if (pChar)
147     ret = pChar->bbox();
148   return ret;
149 }
150