• 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/parser/cpdf_array.h"
8 
9 #include <set>
10 #include <utility>
11 
12 #include "core/fpdfapi/parser/cpdf_name.h"
13 #include "core/fpdfapi/parser/cpdf_number.h"
14 #include "core/fpdfapi/parser/cpdf_reference.h"
15 #include "core/fpdfapi/parser/cpdf_stream.h"
16 #include "core/fpdfapi/parser/cpdf_string.h"
17 #include "third_party/base/logging.h"
18 #include "third_party/base/stl_util.h"
19 
CPDF_Array()20 CPDF_Array::CPDF_Array() {}
21 
CPDF_Array(const CFX_WeakPtr<CFX_ByteStringPool> & pPool)22 CPDF_Array::CPDF_Array(const CFX_WeakPtr<CFX_ByteStringPool>& pPool)
23     : m_pPool(pPool) {}
24 
~CPDF_Array()25 CPDF_Array::~CPDF_Array() {
26   // Break cycles for cyclic references.
27   m_ObjNum = kInvalidObjNum;
28   for (auto& it : m_Objects) {
29     if (it && it->GetObjNum() == kInvalidObjNum)
30       it.release();
31   }
32 }
33 
GetType() const34 CPDF_Object::Type CPDF_Array::GetType() const {
35   return ARRAY;
36 }
37 
IsArray() const38 bool CPDF_Array::IsArray() const {
39   return true;
40 }
41 
AsArray()42 CPDF_Array* CPDF_Array::AsArray() {
43   return this;
44 }
45 
AsArray() const46 const CPDF_Array* CPDF_Array::AsArray() const {
47   return this;
48 }
49 
Clone() const50 std::unique_ptr<CPDF_Object> CPDF_Array::Clone() const {
51   return CloneObjectNonCyclic(false);
52 }
53 
CloneNonCyclic(bool bDirect,std::set<const CPDF_Object * > * pVisited) const54 std::unique_ptr<CPDF_Object> CPDF_Array::CloneNonCyclic(
55     bool bDirect,
56     std::set<const CPDF_Object*>* pVisited) const {
57   pVisited->insert(this);
58   auto pCopy = pdfium::MakeUnique<CPDF_Array>();
59   for (const auto& pValue : m_Objects) {
60     if (!pdfium::ContainsKey(*pVisited, pValue.get()))
61       pCopy->m_Objects.push_back(pValue->CloneNonCyclic(bDirect, pVisited));
62   }
63   return std::move(pCopy);
64 }
65 
GetRect()66 CFX_FloatRect CPDF_Array::GetRect() {
67   CFX_FloatRect rect;
68   if (!IsArray() || m_Objects.size() != 4)
69     return rect;
70 
71   rect.left = GetNumberAt(0);
72   rect.bottom = GetNumberAt(1);
73   rect.right = GetNumberAt(2);
74   rect.top = GetNumberAt(3);
75   return rect;
76 }
77 
GetMatrix()78 CFX_Matrix CPDF_Array::GetMatrix() {
79   CFX_Matrix matrix;
80   if (!IsArray() || m_Objects.size() != 6)
81     return CFX_Matrix();
82 
83   return CFX_Matrix(GetNumberAt(0), GetNumberAt(1), GetNumberAt(2),
84                     GetNumberAt(3), GetNumberAt(4), GetNumberAt(5));
85 }
86 
GetObjectAt(size_t i) const87 CPDF_Object* CPDF_Array::GetObjectAt(size_t i) const {
88   if (i >= m_Objects.size())
89     return nullptr;
90   return m_Objects[i].get();
91 }
92 
GetDirectObjectAt(size_t i) const93 CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t i) const {
94   if (i >= m_Objects.size())
95     return nullptr;
96   return m_Objects[i]->GetDirect();
97 }
98 
GetStringAt(size_t i) const99 CFX_ByteString CPDF_Array::GetStringAt(size_t i) const {
100   if (i >= m_Objects.size())
101     return CFX_ByteString();
102   return m_Objects[i]->GetString();
103 }
104 
GetIntegerAt(size_t i) const105 int CPDF_Array::GetIntegerAt(size_t i) const {
106   if (i >= m_Objects.size())
107     return 0;
108   return m_Objects[i]->GetInteger();
109 }
110 
GetNumberAt(size_t i) const111 FX_FLOAT CPDF_Array::GetNumberAt(size_t i) const {
112   if (i >= m_Objects.size())
113     return 0;
114   return m_Objects[i]->GetNumber();
115 }
116 
GetDictAt(size_t i) const117 CPDF_Dictionary* CPDF_Array::GetDictAt(size_t i) const {
118   CPDF_Object* p = GetDirectObjectAt(i);
119   if (!p)
120     return nullptr;
121   if (CPDF_Dictionary* pDict = p->AsDictionary())
122     return pDict;
123   if (CPDF_Stream* pStream = p->AsStream())
124     return pStream->GetDict();
125   return nullptr;
126 }
127 
GetStreamAt(size_t i) const128 CPDF_Stream* CPDF_Array::GetStreamAt(size_t i) const {
129   return ToStream(GetDirectObjectAt(i));
130 }
131 
GetArrayAt(size_t i) const132 CPDF_Array* CPDF_Array::GetArrayAt(size_t i) const {
133   return ToArray(GetDirectObjectAt(i));
134 }
135 
RemoveAt(size_t i,size_t nCount)136 void CPDF_Array::RemoveAt(size_t i, size_t nCount) {
137   if (i >= m_Objects.size())
138     return;
139 
140   if (nCount <= 0 || nCount > m_Objects.size() - i)
141     return;
142 
143   m_Objects.erase(m_Objects.begin() + i, m_Objects.begin() + i + nCount);
144 }
145 
ConvertToIndirectObjectAt(size_t i,CPDF_IndirectObjectHolder * pHolder)146 void CPDF_Array::ConvertToIndirectObjectAt(size_t i,
147                                            CPDF_IndirectObjectHolder* pHolder) {
148   if (i >= m_Objects.size())
149     return;
150 
151   if (!m_Objects[i] || m_Objects[i]->IsReference())
152     return;
153 
154   CPDF_Object* pNew = pHolder->AddIndirectObject(std::move(m_Objects[i]));
155   m_Objects[i] = pdfium::MakeUnique<CPDF_Reference>(pHolder, pNew->GetObjNum());
156 }
157 
SetAt(size_t i,std::unique_ptr<CPDF_Object> pObj)158 CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr<CPDF_Object> pObj) {
159   ASSERT(IsArray());
160   ASSERT(!pObj || pObj->IsInline());
161   if (i >= m_Objects.size()) {
162     ASSERT(false);
163     return nullptr;
164   }
165   CPDF_Object* pRet = pObj.get();
166   m_Objects[i] = std::move(pObj);
167   return pRet;
168 }
169 
InsertAt(size_t index,std::unique_ptr<CPDF_Object> pObj)170 CPDF_Object* CPDF_Array::InsertAt(size_t index,
171                                   std::unique_ptr<CPDF_Object> pObj) {
172   ASSERT(IsArray());
173   CHECK(!pObj || pObj->IsInline());
174   CPDF_Object* pRet = pObj.get();
175   if (index >= m_Objects.size()) {
176     // Allocate space first.
177     m_Objects.resize(index + 1);
178     m_Objects[index] = std::move(pObj);
179   } else {
180     // Directly insert.
181     m_Objects.insert(m_Objects.begin() + index, std::move(pObj));
182   }
183   return pRet;
184 }
185 
Add(std::unique_ptr<CPDF_Object> pObj)186 CPDF_Object* CPDF_Array::Add(std::unique_ptr<CPDF_Object> pObj) {
187   ASSERT(IsArray());
188   CHECK(!pObj || pObj->IsInline());
189   CPDF_Object* pRet = pObj.get();
190   m_Objects.push_back(std::move(pObj));
191   return pRet;
192 }
193