xref: /aosp_15_r20/external/pdfium/core/fpdfapi/font/cpdf_type3font.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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_type3font.h"
8 
9 #include <algorithm>
10 #include <iterator>
11 #include <type_traits>
12 #include <utility>
13 
14 #include "core/fpdfapi/font/cpdf_type3char.h"
15 #include "core/fpdfapi/parser/cpdf_array.h"
16 #include "core/fpdfapi/parser/cpdf_dictionary.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fxcrt/autorestorer.h"
19 #include "core/fxcrt/fx_system.h"
20 #include "third_party/base/check.h"
21 
22 namespace {
23 
24 constexpr int kMaxType3FormLevel = 4;
25 
26 }  // namespace
27 
CPDF_Type3Font(CPDF_Document * pDocument,RetainPtr<CPDF_Dictionary> pFontDict,FormFactoryIface * pFormFactory)28 CPDF_Type3Font::CPDF_Type3Font(CPDF_Document* pDocument,
29                                RetainPtr<CPDF_Dictionary> pFontDict,
30                                FormFactoryIface* pFormFactory)
31     : CPDF_SimpleFont(pDocument, std::move(pFontDict)),
32       m_pFormFactory(pFormFactory) {
33   DCHECK(GetDocument());
34 }
35 
36 CPDF_Type3Font::~CPDF_Type3Font() = default;
37 
IsType3Font() const38 bool CPDF_Type3Font::IsType3Font() const {
39   return true;
40 }
41 
AsType3Font() const42 const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const {
43   return this;
44 }
45 
AsType3Font()46 CPDF_Type3Font* CPDF_Type3Font::AsType3Font() {
47   return this;
48 }
49 
WillBeDestroyed()50 void CPDF_Type3Font::WillBeDestroyed() {
51   // Last reference to |this| may be through one of its CPDF_Type3Chars.
52   RetainPtr<CPDF_Font> protector(this);
53   for (const auto& item : m_CacheMap) {
54     if (item.second)
55       item.second->WillBeDestroyed();
56   }
57 }
58 
Load()59 bool CPDF_Type3Font::Load() {
60   m_pFontResources = m_pFontDict->GetMutableDictFor("Resources");
61   RetainPtr<const CPDF_Array> pMatrix = m_pFontDict->GetArrayFor("FontMatrix");
62   float xscale = 1.0f;
63   float yscale = 1.0f;
64   if (pMatrix) {
65     m_FontMatrix = pMatrix->GetMatrix();
66     xscale = m_FontMatrix.a;
67     yscale = m_FontMatrix.d;
68   }
69 
70   RetainPtr<const CPDF_Array> pBBox = m_pFontDict->GetArrayFor("FontBBox");
71   if (pBBox) {
72     CFX_FloatRect box(
73         pBBox->GetFloatAt(0) * xscale, pBBox->GetFloatAt(1) * yscale,
74         pBBox->GetFloatAt(2) * xscale, pBBox->GetFloatAt(3) * yscale);
75     CPDF_Type3Char::TextUnitRectToGlyphUnitRect(&box);
76     m_FontBBox = box.ToFxRect();
77   }
78 
79   static constexpr size_t kCharLimit = std::extent<decltype(m_CharWidthL)>();
80   int StartChar = m_pFontDict->GetIntegerFor("FirstChar");
81   if (StartChar >= 0 && static_cast<size_t>(StartChar) < kCharLimit) {
82     RetainPtr<const CPDF_Array> pWidthArray =
83         m_pFontDict->GetArrayFor("Widths");
84     if (pWidthArray) {
85       size_t count = std::min(pWidthArray->size(), kCharLimit);
86       count = std::min(count, kCharLimit - StartChar);
87       for (size_t i = 0; i < count; i++) {
88         m_CharWidthL[StartChar + i] =
89             FXSYS_roundf(CPDF_Type3Char::TextUnitToGlyphUnit(
90                 pWidthArray->GetFloatAt(i) * xscale));
91       }
92     }
93   }
94   m_pCharProcs = m_pFontDict->GetMutableDictFor("CharProcs");
95   if (m_pFontDict->GetDirectObjectFor("Encoding"))
96     LoadPDFEncoding(false, false);
97   return true;
98 }
99 
LoadGlyphMap()100 void CPDF_Type3Font::LoadGlyphMap() {}
101 
CheckType3FontMetrics()102 void CPDF_Type3Font::CheckType3FontMetrics() {
103   CheckFontMetrics();
104 }
105 
LoadChar(uint32_t charcode)106 CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) {
107   if (m_CharLoadingDepth >= kMaxType3FormLevel)
108     return nullptr;
109 
110   auto it = m_CacheMap.find(charcode);
111   if (it != m_CacheMap.end())
112     return it->second.get();
113 
114   const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
115   if (!name)
116     return nullptr;
117 
118   if (!m_pCharProcs)
119     return nullptr;
120 
121   RetainPtr<CPDF_Stream> pStream =
122       ToStream(m_pCharProcs->GetMutableDirectObjectFor(name));
123   if (!pStream)
124     return nullptr;
125 
126   std::unique_ptr<CPDF_Font::FormIface> pForm = m_pFormFactory->CreateForm(
127       m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources,
128       pStream);
129 
130   auto pNewChar = std::make_unique<CPDF_Type3Char>();
131 
132   // This can trigger recursion into this method. The content of |m_CacheMap|
133   // can change as a result. Thus after it returns, check the cache again for
134   // a cache hit.
135   {
136     AutoRestorer<int> restorer(&m_CharLoadingDepth);
137     m_CharLoadingDepth++;
138     pForm->ParseContentForType3Char(pNewChar.get());
139   }
140   it = m_CacheMap.find(charcode);
141   if (it != m_CacheMap.end())
142     return it->second.get();
143 
144   pNewChar->Transform(pForm.get(), m_FontMatrix);
145   if (pForm->HasPageObjects())
146     pNewChar->SetForm(std::move(pForm));
147 
148   CPDF_Type3Char* pCachedChar = pNewChar.get();
149   m_CacheMap[charcode] = std::move(pNewChar);
150   return pCachedChar;
151 }
152 
GetCharWidthF(uint32_t charcode)153 int CPDF_Type3Font::GetCharWidthF(uint32_t charcode) {
154   if (charcode >= std::size(m_CharWidthL))
155     charcode = 0;
156 
157   if (m_CharWidthL[charcode])
158     return m_CharWidthL[charcode];
159 
160   const CPDF_Type3Char* pChar = LoadChar(charcode);
161   return pChar ? pChar->width() : 0;
162 }
163 
GetCharBBox(uint32_t charcode)164 FX_RECT CPDF_Type3Font::GetCharBBox(uint32_t charcode) {
165   FX_RECT ret;
166   const CPDF_Type3Char* pChar = LoadChar(charcode);
167   if (pChar)
168     ret = pChar->bbox();
169   return ret;
170 }
171