1 // Copyright 2014 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/include/fpdfapi/fpdf_objects.h"
8
9 #include <algorithm>
10
11 #include "core/include/fpdfapi/fpdf_parser.h"
12 #include "core/include/fxcrt/fx_string.h"
13 #include "third_party/base/stl_util.h"
14
15 namespace {
16
17 const FX_DWORD kBlockSize = 1024;
18
19 } // namespace
20
21 // static
22 int CPDF_Object::s_nCurRefDepth = 0;
23
Release()24 void CPDF_Object::Release() {
25 if (m_ObjNum) {
26 return;
27 }
28 Destroy();
29 }
Destroy()30 void CPDF_Object::Destroy() {
31 switch (m_Type) {
32 case PDFOBJ_STRING:
33 delete AsString();
34 break;
35 case PDFOBJ_NAME:
36 delete AsName();
37 break;
38 case PDFOBJ_ARRAY:
39 delete AsArray();
40 break;
41 case PDFOBJ_DICTIONARY:
42 delete AsDictionary();
43 break;
44 case PDFOBJ_STREAM:
45 delete AsStream();
46 break;
47 default:
48 delete this;
49 }
50 }
GetString() const51 CFX_ByteString CPDF_Object::GetString() const {
52 switch (m_Type) {
53 case PDFOBJ_BOOLEAN:
54 return AsBoolean()->m_bValue ? "true" : "false";
55 case PDFOBJ_NUMBER:
56 return AsNumber()->GetString();
57 case PDFOBJ_STRING:
58 return AsString()->m_String;
59 case PDFOBJ_NAME:
60 return AsName()->m_Name;
61 case PDFOBJ_REFERENCE: {
62 const CPDF_Reference* pRef = AsReference();
63 if (!pRef->m_pObjList)
64 break;
65
66 CPDF_Object* pObj =
67 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
68 return pObj ? pObj->GetString() : CFX_ByteString();
69 }
70 }
71 return CFX_ByteString();
72 }
GetConstString() const73 CFX_ByteStringC CPDF_Object::GetConstString() const {
74 switch (m_Type) {
75 case PDFOBJ_STRING: {
76 CFX_ByteString str = AsString()->m_String;
77 return CFX_ByteStringC((const uint8_t*)str, str.GetLength());
78 }
79 case PDFOBJ_NAME: {
80 CFX_ByteString name = AsName()->m_Name;
81 return CFX_ByteStringC((const uint8_t*)name, name.GetLength());
82 }
83 case PDFOBJ_REFERENCE: {
84 const CPDF_Reference* pRef = AsReference();
85 if (!pRef->m_pObjList)
86 break;
87
88 CPDF_Object* pObj =
89 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
90 return pObj ? pObj->GetConstString() : CFX_ByteStringC();
91 }
92 }
93 return CFX_ByteStringC();
94 }
95
GetNumber() const96 FX_FLOAT CPDF_Object::GetNumber() const {
97 switch (m_Type) {
98 case PDFOBJ_NUMBER:
99 return AsNumber()->GetNumber();
100 case PDFOBJ_REFERENCE: {
101 const CPDF_Reference* pRef = AsReference();
102 if (!pRef->m_pObjList)
103 break;
104
105 CPDF_Object* pObj =
106 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
107 return pObj ? pObj->GetNumber() : 0;
108 }
109 }
110 return 0;
111 }
112
GetNumber16() const113 FX_FLOAT CPDF_Object::GetNumber16() const {
114 return GetNumber();
115 }
116
GetInteger() const117 int CPDF_Object::GetInteger() const {
118 CFX_AutoRestorer<int> restorer(&s_nCurRefDepth);
119 if (++s_nCurRefDepth > kObjectRefMaxDepth)
120 return 0;
121
122 switch (m_Type) {
123 case PDFOBJ_BOOLEAN:
124 return AsBoolean()->m_bValue;
125 case PDFOBJ_NUMBER:
126 return AsNumber()->GetInteger();
127 case PDFOBJ_REFERENCE: {
128 const CPDF_Reference* pRef = AsReference();
129 PARSE_CONTEXT context;
130 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
131 if (!pRef->m_pObjList)
132 return 0;
133
134 CPDF_Object* pObj =
135 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), &context);
136 return pObj ? pObj->GetInteger() : 0;
137 }
138 }
139 return 0;
140 }
141
GetDict() const142 CPDF_Dictionary* CPDF_Object::GetDict() const {
143 switch (m_Type) {
144 case PDFOBJ_DICTIONARY:
145 // The method should be made non-const if we want to not be const.
146 // See bug #234.
147 return const_cast<CPDF_Dictionary*>(AsDictionary());
148 case PDFOBJ_STREAM:
149 return AsStream()->GetDict();
150 case PDFOBJ_REFERENCE: {
151 const CPDF_Reference* pRef = AsReference();
152 CPDF_IndirectObjectHolder* pIndirect = pRef->GetObjList();
153 if (!pIndirect)
154 return nullptr;
155 CPDF_Object* pObj =
156 pIndirect->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
157 if (!pObj || (pObj == this))
158 return nullptr;
159 return pObj->GetDict();
160 }
161 default:
162 return nullptr;
163 }
164 }
165
GetArray() const166 CPDF_Array* CPDF_Object::GetArray() const {
167 // The method should be made non-const if we want to not be const.
168 // See bug #234.
169 return const_cast<CPDF_Array*>(AsArray());
170 }
171
SetString(const CFX_ByteString & str)172 void CPDF_Object::SetString(const CFX_ByteString& str) {
173 switch (m_Type) {
174 case PDFOBJ_BOOLEAN:
175 AsBoolean()->m_bValue = (str == "true");
176 return;
177 case PDFOBJ_NUMBER:
178 AsNumber()->SetString(str);
179 return;
180 case PDFOBJ_STRING:
181 AsString()->m_String = str;
182 return;
183 case PDFOBJ_NAME:
184 AsName()->m_Name = str;
185 return;
186 }
187 ASSERT(FALSE);
188 }
GetDirectType() const189 int CPDF_Object::GetDirectType() const {
190 const CPDF_Reference* pRef = AsReference();
191 if (!pRef)
192 return m_Type;
193 return pRef->m_pObjList->GetIndirectType(pRef->GetRefObjNum());
194 }
IsIdentical(CPDF_Object * pOther) const195 FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const {
196 if (this == pOther)
197 return TRUE;
198 if (!pOther)
199 return FALSE;
200 if (pOther->m_Type != m_Type) {
201 if (IsReference() && GetDirect())
202 return GetDirect()->IsIdentical(pOther);
203 if (pOther->IsReference())
204 return IsIdentical(pOther->GetDirect());
205 return FALSE;
206 }
207 switch (m_Type) {
208 case PDFOBJ_BOOLEAN:
209 return AsBoolean()->Identical(pOther->AsBoolean());
210 case PDFOBJ_NUMBER:
211 return AsNumber()->Identical(pOther->AsNumber());
212 case PDFOBJ_STRING:
213 return AsString()->Identical(pOther->AsString());
214 case PDFOBJ_NAME:
215 return AsName()->Identical(pOther->AsName());
216 case PDFOBJ_ARRAY:
217 return AsArray()->Identical(pOther->AsArray());
218 case PDFOBJ_DICTIONARY:
219 return AsDictionary()->Identical(pOther->AsDictionary());
220 case PDFOBJ_NULL:
221 return TRUE;
222 case PDFOBJ_STREAM:
223 return AsStream()->Identical(pOther->AsStream());
224 case PDFOBJ_REFERENCE:
225 return AsReference()->Identical(pOther->AsReference());
226 }
227 return FALSE;
228 }
229
GetDirect() const230 CPDF_Object* CPDF_Object::GetDirect() const {
231 const CPDF_Reference* pRef = AsReference();
232 if (!pRef)
233 return const_cast<CPDF_Object*>(this);
234 if (!pRef->m_pObjList)
235 return nullptr;
236 return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr);
237 }
238
Clone(FX_BOOL bDirect) const239 CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const {
240 std::set<FX_DWORD> visited;
241 return CloneInternal(bDirect, &visited);
242 }
CloneInternal(FX_BOOL bDirect,std::set<FX_DWORD> * visited) const243 CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect,
244 std::set<FX_DWORD>* visited) const {
245 switch (m_Type) {
246 case PDFOBJ_BOOLEAN:
247 return new CPDF_Boolean(AsBoolean()->m_bValue);
248 case PDFOBJ_NUMBER: {
249 const CPDF_Number* pThis = AsNumber();
250 return new CPDF_Number(pThis->m_bInteger ? pThis->m_Integer
251 : pThis->m_Float);
252 }
253 case PDFOBJ_STRING: {
254 const CPDF_String* pString = AsString();
255 return new CPDF_String(pString->m_String, pString->IsHex());
256 }
257 case PDFOBJ_NAME:
258 return new CPDF_Name(AsName()->m_Name);
259 case PDFOBJ_ARRAY: {
260 CPDF_Array* pCopy = new CPDF_Array();
261 const CPDF_Array* pThis = AsArray();
262 int n = pThis->GetCount();
263 for (int i = 0; i < n; i++) {
264 CPDF_Object* value = pThis->m_Objects.GetAt(i);
265 pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
266 }
267 return pCopy;
268 }
269 case PDFOBJ_DICTIONARY: {
270 CPDF_Dictionary* pCopy = new CPDF_Dictionary();
271 const CPDF_Dictionary* pThis = AsDictionary();
272 for (const auto& it : *pThis) {
273 pCopy->m_Map.insert(std::make_pair(
274 it.first, it.second->CloneInternal(bDirect, visited)));
275 }
276 return pCopy;
277 }
278 case PDFOBJ_NULL: {
279 return new CPDF_Null;
280 }
281 case PDFOBJ_STREAM: {
282 const CPDF_Stream* pThis = AsStream();
283 CPDF_StreamAcc acc;
284 acc.LoadAllData(pThis, TRUE);
285 FX_DWORD streamSize = acc.GetSize();
286 CPDF_Dictionary* pDict = pThis->GetDict();
287 if (pDict) {
288 pDict = ToDictionary(pDict->CloneInternal(bDirect, visited));
289 }
290 return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
291 }
292 case PDFOBJ_REFERENCE: {
293 const CPDF_Reference* pRef = AsReference();
294 FX_DWORD obj_num = pRef->GetRefObjNum();
295 if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) {
296 visited->insert(obj_num);
297 auto* pDirect = pRef->GetDirect();
298 return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr;
299 }
300 return new CPDF_Reference(pRef->m_pObjList, obj_num);
301 }
302 }
303 return NULL;
304 }
CloneRef(CPDF_IndirectObjectHolder * pDoc) const305 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const {
306 if (m_ObjNum) {
307 return new CPDF_Reference(pDoc, m_ObjNum);
308 }
309 return Clone();
310 }
GetUnicodeText(CFX_CharMap * pCharMap) const311 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const {
312 if (const CPDF_String* pString = AsString())
313 return PDF_DecodeText(pString->m_String, pCharMap);
314
315 if (const CPDF_Stream* pStream = AsStream()) {
316 CPDF_StreamAcc stream;
317 stream.LoadAllData(pStream, FALSE);
318 CFX_WideString result =
319 PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
320 return result;
321 }
322 if (const CPDF_Name* pName = AsName())
323 return PDF_DecodeText(pName->m_Name, pCharMap);
324 return CFX_WideString();
325 }
SetUnicodeText(const FX_WCHAR * pUnicodes,int len)326 void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) {
327 if (CPDF_String* pString = AsString()) {
328 pString->m_String = PDF_EncodeText(pUnicodes, len);
329 } else if (CPDF_Stream* pStream = AsStream()) {
330 CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
331 pStream->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE,
332 FALSE);
333 }
334 }
335
AsArray()336 CPDF_Array* CPDF_Object::AsArray() {
337 return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr;
338 }
339
AsArray() const340 const CPDF_Array* CPDF_Object::AsArray() const {
341 return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr;
342 }
343
AsBoolean()344 CPDF_Boolean* CPDF_Object::AsBoolean() {
345 return IsBoolean() ? static_cast<CPDF_Boolean*>(this) : nullptr;
346 }
347
AsBoolean() const348 const CPDF_Boolean* CPDF_Object::AsBoolean() const {
349 return IsBoolean() ? static_cast<const CPDF_Boolean*>(this) : nullptr;
350 }
351
AsDictionary()352 CPDF_Dictionary* CPDF_Object::AsDictionary() {
353 return IsDictionary() ? static_cast<CPDF_Dictionary*>(this) : nullptr;
354 }
355
AsDictionary() const356 const CPDF_Dictionary* CPDF_Object::AsDictionary() const {
357 return IsDictionary() ? static_cast<const CPDF_Dictionary*>(this) : nullptr;
358 }
359
AsName()360 CPDF_Name* CPDF_Object::AsName() {
361 return IsName() ? static_cast<CPDF_Name*>(this) : nullptr;
362 }
363
AsName() const364 const CPDF_Name* CPDF_Object::AsName() const {
365 return IsName() ? static_cast<const CPDF_Name*>(this) : nullptr;
366 }
367
AsNumber()368 CPDF_Number* CPDF_Object::AsNumber() {
369 return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr;
370 }
371
AsNumber() const372 const CPDF_Number* CPDF_Object::AsNumber() const {
373 return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr;
374 }
375
AsReference()376 CPDF_Reference* CPDF_Object::AsReference() {
377 return IsReference() ? static_cast<CPDF_Reference*>(this) : nullptr;
378 }
379
AsReference() const380 const CPDF_Reference* CPDF_Object::AsReference() const {
381 return IsReference() ? static_cast<const CPDF_Reference*>(this) : nullptr;
382 }
383
AsStream()384 CPDF_Stream* CPDF_Object::AsStream() {
385 return IsStream() ? static_cast<CPDF_Stream*>(this) : nullptr;
386 }
387
AsStream() const388 const CPDF_Stream* CPDF_Object::AsStream() const {
389 return IsStream() ? static_cast<const CPDF_Stream*>(this) : nullptr;
390 }
391
AsString()392 CPDF_String* CPDF_Object::AsString() {
393 return IsString() ? static_cast<CPDF_String*>(this) : nullptr;
394 }
395
AsString() const396 const CPDF_String* CPDF_Object::AsString() const {
397 return IsString() ? static_cast<const CPDF_String*>(this) : nullptr;
398 }
399
CPDF_Number(int value)400 CPDF_Number::CPDF_Number(int value)
401 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {}
402
CPDF_Number(FX_FLOAT value)403 CPDF_Number::CPDF_Number(FX_FLOAT value)
404 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(FALSE), m_Float(value) {}
405
CPDF_Number(const CFX_ByteStringC & str)406 CPDF_Number::CPDF_Number(const CFX_ByteStringC& str)
407 : CPDF_Object(PDFOBJ_NUMBER) {
408 FX_atonum(str, m_bInteger, &m_Integer);
409 }
410
SetString(const CFX_ByteStringC & str)411 void CPDF_Number::SetString(const CFX_ByteStringC& str) {
412 FX_atonum(str, m_bInteger, &m_Integer);
413 }
Identical(CPDF_Number * pOther) const414 FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const {
415 return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
416 }
GetString() const417 CFX_ByteString CPDF_Number::GetString() const {
418 return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED)
419 : CFX_ByteString::FormatFloat(m_Float);
420 }
SetNumber(FX_FLOAT value)421 void CPDF_Number::SetNumber(FX_FLOAT value) {
422 m_bInteger = FALSE;
423 m_Float = value;
424 }
CPDF_String(const CFX_WideString & str)425 CPDF_String::CPDF_String(const CFX_WideString& str)
426 : CPDF_Object(PDFOBJ_STRING), m_bHex(FALSE) {
427 m_String = PDF_EncodeText(str);
428 }
~CPDF_Array()429 CPDF_Array::~CPDF_Array() {
430 int size = m_Objects.GetSize();
431 CPDF_Object** pList = m_Objects.GetData();
432 for (int i = 0; i < size; i++) {
433 if (pList[i])
434 pList[i]->Release();
435 }
436 }
GetRect()437 CFX_FloatRect CPDF_Array::GetRect() {
438 CFX_FloatRect rect;
439 if (!IsArray() || m_Objects.GetSize() != 4)
440 return rect;
441
442 rect.left = GetNumber(0);
443 rect.bottom = GetNumber(1);
444 rect.right = GetNumber(2);
445 rect.top = GetNumber(3);
446 return rect;
447 }
GetMatrix()448 CFX_Matrix CPDF_Array::GetMatrix() {
449 CFX_Matrix matrix;
450 if (!IsArray() || m_Objects.GetSize() != 6)
451 return matrix;
452
453 matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3),
454 GetNumber(4), GetNumber(5));
455 return matrix;
456 }
GetElement(FX_DWORD i) const457 CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const {
458 if (i >= (FX_DWORD)m_Objects.GetSize())
459 return nullptr;
460 return m_Objects.GetAt(i);
461 }
GetElementValue(FX_DWORD i) const462 CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const {
463 if (i >= (FX_DWORD)m_Objects.GetSize())
464 return nullptr;
465 return m_Objects.GetAt(i)->GetDirect();
466 }
GetString(FX_DWORD i) const467 CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const {
468 if (i >= (FX_DWORD)m_Objects.GetSize())
469 return CFX_ByteString();
470 return m_Objects.GetAt(i)->GetString();
471 }
GetConstString(FX_DWORD i) const472 CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const {
473 if (i >= (FX_DWORD)m_Objects.GetSize())
474 return CFX_ByteStringC();
475 return m_Objects.GetAt(i)->GetConstString();
476 }
GetInteger(FX_DWORD i) const477 int CPDF_Array::GetInteger(FX_DWORD i) const {
478 if (i >= (FX_DWORD)m_Objects.GetSize())
479 return 0;
480 return m_Objects.GetAt(i)->GetInteger();
481 }
GetNumber(FX_DWORD i) const482 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const {
483 if (i >= (FX_DWORD)m_Objects.GetSize())
484 return 0;
485 return m_Objects.GetAt(i)->GetNumber();
486 }
GetDict(FX_DWORD i) const487 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const {
488 CPDF_Object* p = GetElementValue(i);
489 if (!p)
490 return NULL;
491 if (CPDF_Dictionary* pDict = p->AsDictionary())
492 return pDict;
493 if (CPDF_Stream* pStream = p->AsStream())
494 return pStream->GetDict();
495 return NULL;
496 }
GetStream(FX_DWORD i) const497 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const {
498 return ToStream(GetElementValue(i));
499 }
GetArray(FX_DWORD i) const500 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const {
501 return ToArray(GetElementValue(i));
502 }
RemoveAt(FX_DWORD i,int nCount)503 void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) {
504 if (i >= (FX_DWORD)m_Objects.GetSize())
505 return;
506
507 if (nCount <= 0 || nCount > m_Objects.GetSize() - i)
508 return;
509
510 for (int j = 0; j < nCount; ++j) {
511 if (CPDF_Object* p = m_Objects.GetAt(i + j))
512 p->Release();
513 }
514 m_Objects.RemoveAt(i, nCount);
515 }
SetAt(FX_DWORD i,CPDF_Object * pObj,CPDF_IndirectObjectHolder * pObjs)516 void CPDF_Array::SetAt(FX_DWORD i,
517 CPDF_Object* pObj,
518 CPDF_IndirectObjectHolder* pObjs) {
519 ASSERT(IsArray());
520 ASSERT(i < (FX_DWORD)m_Objects.GetSize());
521 if (i >= (FX_DWORD)m_Objects.GetSize())
522 return;
523 if (CPDF_Object* pOld = m_Objects.GetAt(i))
524 pOld->Release();
525 if (pObj->GetObjNum()) {
526 ASSERT(pObjs);
527 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
528 }
529 m_Objects.SetAt(i, pObj);
530 }
InsertAt(FX_DWORD index,CPDF_Object * pObj,CPDF_IndirectObjectHolder * pObjs)531 void CPDF_Array::InsertAt(FX_DWORD index,
532 CPDF_Object* pObj,
533 CPDF_IndirectObjectHolder* pObjs) {
534 if (pObj->GetObjNum()) {
535 ASSERT(pObjs);
536 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
537 }
538 m_Objects.InsertAt(index, pObj);
539 }
Add(CPDF_Object * pObj,CPDF_IndirectObjectHolder * pObjs)540 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) {
541 if (pObj->GetObjNum()) {
542 ASSERT(pObjs);
543 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
544 }
545 m_Objects.Add(pObj);
546 }
AddName(const CFX_ByteString & str)547 void CPDF_Array::AddName(const CFX_ByteString& str) {
548 ASSERT(IsArray());
549 Add(new CPDF_Name(str));
550 }
AddString(const CFX_ByteString & str)551 void CPDF_Array::AddString(const CFX_ByteString& str) {
552 ASSERT(IsArray());
553 Add(new CPDF_String(str, FALSE));
554 }
AddInteger(int i)555 void CPDF_Array::AddInteger(int i) {
556 ASSERT(IsArray());
557 Add(new CPDF_Number(i));
558 }
AddNumber(FX_FLOAT f)559 void CPDF_Array::AddNumber(FX_FLOAT f) {
560 ASSERT(IsArray());
561 CPDF_Number* pNumber = new CPDF_Number;
562 pNumber->SetNumber(f);
563 Add(pNumber);
564 }
AddReference(CPDF_IndirectObjectHolder * pDoc,FX_DWORD objnum)565 void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
566 FX_DWORD objnum) {
567 ASSERT(IsArray());
568 Add(new CPDF_Reference(pDoc, objnum));
569 }
Identical(CPDF_Array * pOther) const570 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const {
571 if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
572 return FALSE;
573 }
574 for (int i = 0; i < m_Objects.GetSize(); i++) {
575 if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i]))
576 return FALSE;
577 }
578 return TRUE;
579 }
~CPDF_Dictionary()580 CPDF_Dictionary::~CPDF_Dictionary() {
581 for (const auto& it : m_Map) {
582 it.second->Release();
583 }
584 }
GetElement(const CFX_ByteStringC & key) const585 CPDF_Object* CPDF_Dictionary::GetElement(const CFX_ByteStringC& key) const {
586 auto it = m_Map.find(key);
587 if (it == m_Map.end())
588 return nullptr;
589 return it->second;
590 }
GetElementValue(const CFX_ByteStringC & key) const591 CPDF_Object* CPDF_Dictionary::GetElementValue(
592 const CFX_ByteStringC& key) const {
593 CPDF_Object* p = GetElement(key);
594 return p ? p->GetDirect() : nullptr;
595 }
GetString(const CFX_ByteStringC & key) const596 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key) const {
597 CPDF_Object* p = GetElement(key);
598 if (p) {
599 return p->GetString();
600 }
601 return CFX_ByteString();
602 }
GetConstString(const CFX_ByteStringC & key) const603 CFX_ByteStringC CPDF_Dictionary::GetConstString(
604 const CFX_ByteStringC& key) const {
605 CPDF_Object* p = GetElement(key);
606 if (p) {
607 return p->GetConstString();
608 }
609 return CFX_ByteStringC();
610 }
GetUnicodeText(const CFX_ByteStringC & key,CFX_CharMap * pCharMap) const611 CFX_WideString CPDF_Dictionary::GetUnicodeText(const CFX_ByteStringC& key,
612 CFX_CharMap* pCharMap) const {
613 CPDF_Object* p = GetElement(key);
614 if (CPDF_Reference* pRef = ToReference(p))
615 p = pRef->GetDirect();
616 return p ? p->GetUnicodeText(pCharMap) : CFX_WideString();
617 }
GetString(const CFX_ByteStringC & key,const CFX_ByteStringC & def) const618 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key,
619 const CFX_ByteStringC& def) const {
620 CPDF_Object* p = GetElement(key);
621 if (p) {
622 return p->GetString();
623 }
624 return CFX_ByteString(def);
625 }
GetConstString(const CFX_ByteStringC & key,const CFX_ByteStringC & def) const626 CFX_ByteStringC CPDF_Dictionary::GetConstString(
627 const CFX_ByteStringC& key,
628 const CFX_ByteStringC& def) const {
629 CPDF_Object* p = GetElement(key);
630 if (p) {
631 return p->GetConstString();
632 }
633 return CFX_ByteStringC(def);
634 }
GetInteger(const CFX_ByteStringC & key) const635 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key) const {
636 CPDF_Object* p = GetElement(key);
637 if (p) {
638 return p->GetInteger();
639 }
640 return 0;
641 }
GetInteger(const CFX_ByteStringC & key,int def) const642 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key, int def) const {
643 CPDF_Object* p = GetElement(key);
644 if (p) {
645 return p->GetInteger();
646 }
647 return def;
648 }
GetNumber(const CFX_ByteStringC & key) const649 FX_FLOAT CPDF_Dictionary::GetNumber(const CFX_ByteStringC& key) const {
650 CPDF_Object* p = GetElement(key);
651 if (p) {
652 return p->GetNumber();
653 }
654 return 0;
655 }
GetBoolean(const CFX_ByteStringC & key,FX_BOOL bDefault) const656 FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key,
657 FX_BOOL bDefault) const {
658 CPDF_Object* p = GetElement(key);
659 if (ToBoolean(p))
660 return p->GetInteger();
661 return bDefault;
662 }
GetDict(const CFX_ByteStringC & key) const663 CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const {
664 CPDF_Object* p = GetElementValue(key);
665 if (!p)
666 return nullptr;
667 if (CPDF_Dictionary* pDict = p->AsDictionary())
668 return pDict;
669 if (CPDF_Stream* pStream = p->AsStream())
670 return pStream->GetDict();
671 return nullptr;
672 }
GetArray(const CFX_ByteStringC & key) const673 CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const {
674 return ToArray(GetElementValue(key));
675 }
GetStream(const CFX_ByteStringC & key) const676 CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const {
677 return ToStream(GetElementValue(key));
678 }
GetRect(const CFX_ByteStringC & key) const679 CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const {
680 CFX_FloatRect rect;
681 CPDF_Array* pArray = GetArray(key);
682 if (pArray)
683 rect = pArray->GetRect();
684 return rect;
685 }
GetMatrix(const CFX_ByteStringC & key) const686 CFX_Matrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const {
687 CFX_Matrix matrix;
688 CPDF_Array* pArray = GetArray(key);
689 if (pArray)
690 matrix = pArray->GetMatrix();
691 return matrix;
692 }
KeyExist(const CFX_ByteStringC & key) const693 FX_BOOL CPDF_Dictionary::KeyExist(const CFX_ByteStringC& key) const {
694 return pdfium::ContainsKey(m_Map, key);
695 }
696
SetAt(const CFX_ByteStringC & key,CPDF_Object * pObj)697 void CPDF_Dictionary::SetAt(const CFX_ByteStringC& key, CPDF_Object* pObj) {
698 ASSERT(IsDictionary());
699 // Avoid 2 constructions of CFX_ByteString.
700 CFX_ByteString key_bytestring = key;
701 auto it = m_Map.find(key_bytestring);
702 if (it == m_Map.end()) {
703 if (pObj) {
704 m_Map.insert(std::make_pair(key_bytestring, pObj));
705 }
706 return;
707 }
708
709 if (it->second == pObj)
710 return;
711 it->second->Release();
712
713 if (pObj)
714 it->second = pObj;
715 else
716 m_Map.erase(it);
717 }
RemoveAt(const CFX_ByteStringC & key)718 void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) {
719 ASSERT(m_Type == PDFOBJ_DICTIONARY);
720 auto it = m_Map.find(key);
721 if (it == m_Map.end())
722 return;
723
724 it->second->Release();
725 m_Map.erase(it);
726 }
ReplaceKey(const CFX_ByteStringC & oldkey,const CFX_ByteStringC & newkey)727 void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey,
728 const CFX_ByteStringC& newkey) {
729 ASSERT(m_Type == PDFOBJ_DICTIONARY);
730 auto old_it = m_Map.find(oldkey);
731 if (old_it == m_Map.end())
732 return;
733
734 // Avoid 2 constructions of CFX_ByteString.
735 CFX_ByteString newkey_bytestring = newkey;
736 auto new_it = m_Map.find(newkey_bytestring);
737 if (new_it == old_it)
738 return;
739
740 if (new_it != m_Map.end()) {
741 new_it->second->Release();
742 new_it->second = old_it->second;
743 } else {
744 m_Map.insert(std::make_pair(newkey_bytestring, old_it->second));
745 }
746 m_Map.erase(old_it);
747 }
Identical(CPDF_Dictionary * pOther) const748 FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const {
749 if (!pOther) {
750 return FALSE;
751 }
752 if (m_Map.size() != pOther->m_Map.size()) {
753 return FALSE;
754 }
755 for (const auto& it : m_Map) {
756 const CFX_ByteString& key = it.first;
757 if (!it.second->IsIdentical(pOther->GetElement(key)))
758 return FALSE;
759 }
760 return TRUE;
761 }
SetAtInteger(const CFX_ByteStringC & key,int i)762 void CPDF_Dictionary::SetAtInteger(const CFX_ByteStringC& key, int i) {
763 SetAt(key, new CPDF_Number(i));
764 }
SetAtName(const CFX_ByteStringC & key,const CFX_ByteString & name)765 void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key,
766 const CFX_ByteString& name) {
767 SetAt(key, new CPDF_Name(name));
768 }
SetAtString(const CFX_ByteStringC & key,const CFX_ByteString & str)769 void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key,
770 const CFX_ByteString& str) {
771 SetAt(key, new CPDF_String(str, FALSE));
772 }
SetAtReference(const CFX_ByteStringC & key,CPDF_IndirectObjectHolder * pDoc,FX_DWORD objnum)773 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key,
774 CPDF_IndirectObjectHolder* pDoc,
775 FX_DWORD objnum) {
776 SetAt(key, new CPDF_Reference(pDoc, objnum));
777 }
AddReference(const CFX_ByteStringC & key,CPDF_IndirectObjectHolder * pDoc,FX_DWORD objnum)778 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key,
779 CPDF_IndirectObjectHolder* pDoc,
780 FX_DWORD objnum) {
781 SetAt(key, new CPDF_Reference(pDoc, objnum));
782 }
SetAtNumber(const CFX_ByteStringC & key,FX_FLOAT f)783 void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) {
784 CPDF_Number* pNumber = new CPDF_Number;
785 pNumber->SetNumber(f);
786 SetAt(key, pNumber);
787 }
SetAtBoolean(const CFX_ByteStringC & key,FX_BOOL bValue)788 void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) {
789 SetAt(key, new CPDF_Boolean(bValue));
790 }
SetAtRect(const CFX_ByteStringC & key,const CFX_FloatRect & rect)791 void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key,
792 const CFX_FloatRect& rect) {
793 CPDF_Array* pArray = new CPDF_Array;
794 pArray->AddNumber(rect.left);
795 pArray->AddNumber(rect.bottom);
796 pArray->AddNumber(rect.right);
797 pArray->AddNumber(rect.top);
798 SetAt(key, pArray);
799 }
SetAtMatrix(const CFX_ByteStringC & key,const CFX_Matrix & matrix)800 void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key,
801 const CFX_Matrix& matrix) {
802 CPDF_Array* pArray = new CPDF_Array;
803 pArray->AddNumber16(matrix.a);
804 pArray->AddNumber16(matrix.b);
805 pArray->AddNumber16(matrix.c);
806 pArray->AddNumber16(matrix.d);
807 pArray->AddNumber(matrix.e);
808 pArray->AddNumber(matrix.f);
809 SetAt(key, pArray);
810 }
CPDF_Stream(uint8_t * pData,FX_DWORD size,CPDF_Dictionary * pDict)811 CPDF_Stream::CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict)
812 : CPDF_Object(PDFOBJ_STREAM),
813 m_pDict(pDict),
814 m_dwSize(size),
815 m_GenNum(kMemoryBasedGenNum),
816 m_pDataBuf(pData) {}
817
~CPDF_Stream()818 CPDF_Stream::~CPDF_Stream() {
819 if (IsMemoryBased())
820 FX_Free(m_pDataBuf);
821
822 if (m_pDict)
823 m_pDict->Release();
824 }
825
InitStreamInternal(CPDF_Dictionary * pDict)826 void CPDF_Stream::InitStreamInternal(CPDF_Dictionary* pDict) {
827 if (pDict) {
828 if (m_pDict)
829 m_pDict->Release();
830 m_pDict = pDict;
831 }
832 if (IsMemoryBased())
833 FX_Free(m_pDataBuf);
834
835 m_GenNum = 0;
836 m_pFile = nullptr;
837 }
838
InitStream(uint8_t * pData,FX_DWORD size,CPDF_Dictionary * pDict)839 void CPDF_Stream::InitStream(uint8_t* pData,
840 FX_DWORD size,
841 CPDF_Dictionary* pDict) {
842 InitStreamInternal(pDict);
843 m_GenNum = kMemoryBasedGenNum;
844 m_pDataBuf = FX_Alloc(uint8_t, size);
845 if (pData) {
846 FXSYS_memcpy(m_pDataBuf, pData, size);
847 }
848 m_dwSize = size;
849 if (m_pDict) {
850 m_pDict->SetAtInteger("Length", size);
851 }
852 }
SetData(const uint8_t * pData,FX_DWORD size,FX_BOOL bCompressed,FX_BOOL bKeepBuf)853 void CPDF_Stream::SetData(const uint8_t* pData,
854 FX_DWORD size,
855 FX_BOOL bCompressed,
856 FX_BOOL bKeepBuf) {
857 if (IsMemoryBased())
858 FX_Free(m_pDataBuf);
859 m_GenNum = kMemoryBasedGenNum;
860
861 if (bKeepBuf) {
862 m_pDataBuf = (uint8_t*)pData;
863 } else {
864 m_pDataBuf = FX_Alloc(uint8_t, size);
865 if (pData) {
866 FXSYS_memcpy(m_pDataBuf, pData, size);
867 }
868 }
869 m_dwSize = size;
870 if (!m_pDict)
871 m_pDict = new CPDF_Dictionary;
872 m_pDict->SetAtInteger("Length", size);
873 if (!bCompressed) {
874 m_pDict->RemoveAt("Filter");
875 m_pDict->RemoveAt("DecodeParms");
876 }
877 }
ReadRawData(FX_FILESIZE offset,uint8_t * buf,FX_DWORD size) const878 FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset,
879 uint8_t* buf,
880 FX_DWORD size) const {
881 if (!IsMemoryBased() && m_pFile)
882 return m_pFile->ReadBlock(buf, offset, size);
883
884 if (m_pDataBuf)
885 FXSYS_memcpy(buf, m_pDataBuf + offset, size);
886 return TRUE;
887 }
InitStreamFromFile(IFX_FileRead * pFile,CPDF_Dictionary * pDict)888 void CPDF_Stream::InitStreamFromFile(IFX_FileRead* pFile,
889 CPDF_Dictionary* pDict) {
890 InitStreamInternal(pDict);
891 m_pFile = pFile;
892 m_dwSize = (FX_DWORD)pFile->GetSize();
893 if (m_pDict) {
894 m_pDict->SetAtInteger("Length", m_dwSize);
895 }
896 }
897
Identical(CPDF_Stream * pOther) const898 FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const {
899 if (!m_pDict)
900 return !pOther->m_pDict;
901
902 if (!m_pDict->Identical(pOther->m_pDict))
903 return FALSE;
904
905 if (m_dwSize != pOther->m_dwSize)
906 return FALSE;
907
908 if (!IsMemoryBased() && !pOther->IsMemoryBased()) {
909 if (m_pFile == pOther->m_pFile && !m_pFile)
910 return TRUE;
911
912 if (!m_pFile || !pOther->m_pFile)
913 return FALSE;
914
915 uint8_t srcBuf[kBlockSize];
916 uint8_t destBuf[kBlockSize];
917 FX_DWORD size = m_dwSize;
918 if (m_pFile == pOther->m_pFile)
919 return TRUE;
920
921 FX_DWORD offset = 0;
922 while (size > 0) {
923 FX_DWORD actualSize = std::min(size, kBlockSize);
924 m_pFile->ReadBlock(srcBuf, offset, actualSize);
925 pOther->m_pFile->ReadBlock(destBuf, offset, actualSize);
926 if (FXSYS_memcmp(srcBuf, destBuf, actualSize) != 0)
927 return FALSE;
928
929 size -= actualSize;
930 offset += actualSize;
931 }
932 return TRUE;
933 }
934
935 if (!IsMemoryBased() || !pOther->IsMemoryBased()) {
936 IFX_FileRead* pFile = nullptr;
937 uint8_t* pBuf = nullptr;
938 if (!pOther->IsMemoryBased()) {
939 pFile = pOther->m_pFile;
940 pBuf = m_pDataBuf;
941 } else if (!IsMemoryBased()) {
942 pFile = m_pFile;
943 pBuf = pOther->m_pDataBuf;
944 }
945 if (!pBuf)
946 return FALSE;
947
948 uint8_t srcBuf[kBlockSize];
949 FX_DWORD size = m_dwSize;
950 FX_DWORD offset = 0;
951 while (size > 0) {
952 FX_DWORD actualSize = std::min(size, kBlockSize);
953 pFile->ReadBlock(srcBuf, offset, actualSize);
954 if (FXSYS_memcmp(srcBuf, pBuf, actualSize) != 0)
955 return FALSE;
956
957 pBuf += actualSize;
958 size -= actualSize;
959 offset += actualSize;
960 }
961 return TRUE;
962 }
963 return FXSYS_memcmp(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
964 }
965
CPDF_StreamAcc()966 CPDF_StreamAcc::CPDF_StreamAcc() {
967 m_bNewBuf = FALSE;
968 m_pData = NULL;
969 m_dwSize = 0;
970 m_pImageParam = NULL;
971 m_pStream = NULL;
972 m_pSrcData = NULL;
973 }
LoadAllData(const CPDF_Stream * pStream,FX_BOOL bRawAccess,FX_DWORD estimated_size,FX_BOOL bImageAcc)974 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
975 FX_BOOL bRawAccess,
976 FX_DWORD estimated_size,
977 FX_BOOL bImageAcc) {
978 if (!pStream)
979 return;
980
981 m_pStream = pStream;
982 if (pStream->IsMemoryBased() &&
983 (!pStream->GetDict()->KeyExist("Filter") || bRawAccess)) {
984 m_dwSize = pStream->m_dwSize;
985 m_pData = (uint8_t*)pStream->m_pDataBuf;
986 return;
987 }
988 uint8_t* pSrcData;
989 FX_DWORD dwSrcSize = pStream->m_dwSize;
990 if (dwSrcSize == 0)
991 return;
992
993 if (!pStream->IsMemoryBased()) {
994 pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize);
995 if (!pStream->ReadRawData(0, pSrcData, dwSrcSize))
996 return;
997 } else {
998 pSrcData = pStream->m_pDataBuf;
999 }
1000 uint8_t* pDecryptedData = pSrcData;
1001 FX_DWORD dwDecryptedSize = dwSrcSize;
1002 if (!pStream->GetDict()->KeyExist("Filter") || bRawAccess) {
1003 m_pData = pDecryptedData;
1004 m_dwSize = dwDecryptedSize;
1005 } else {
1006 FX_BOOL bRet = PDF_DataDecode(
1007 pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), m_pData,
1008 m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc);
1009 if (!bRet) {
1010 m_pData = pDecryptedData;
1011 m_dwSize = dwDecryptedSize;
1012 }
1013 }
1014 if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
1015 FX_Free(pSrcData);
1016 }
1017 if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
1018 FX_Free(pDecryptedData);
1019 }
1020 m_pSrcData = NULL;
1021 m_bNewBuf = m_pData != pStream->m_pDataBuf;
1022 }
~CPDF_StreamAcc()1023 CPDF_StreamAcc::~CPDF_StreamAcc() {
1024 if (m_bNewBuf) {
1025 FX_Free(m_pData);
1026 }
1027 FX_Free(m_pSrcData);
1028 }
GetData() const1029 const uint8_t* CPDF_StreamAcc::GetData() const {
1030 if (m_bNewBuf) {
1031 return m_pData;
1032 }
1033 if (!m_pStream) {
1034 return NULL;
1035 }
1036 return m_pStream->m_pDataBuf;
1037 }
GetSize() const1038 FX_DWORD CPDF_StreamAcc::GetSize() const {
1039 if (m_bNewBuf) {
1040 return m_dwSize;
1041 }
1042 if (!m_pStream) {
1043 return 0;
1044 }
1045 return m_pStream->m_dwSize;
1046 }
DetachData()1047 uint8_t* CPDF_StreamAcc::DetachData() {
1048 if (m_bNewBuf) {
1049 uint8_t* p = m_pData;
1050 m_pData = NULL;
1051 m_dwSize = 0;
1052 return p;
1053 }
1054 uint8_t* p = FX_Alloc(uint8_t, m_dwSize);
1055 FXSYS_memcpy(p, m_pData, m_dwSize);
1056 return p;
1057 }
SetRef(CPDF_IndirectObjectHolder * pDoc,FX_DWORD objnum)1058 void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) {
1059 m_pObjList = pDoc;
1060 m_RefObjNum = objnum;
1061 }
CPDF_IndirectObjectHolder(CPDF_Parser * pParser)1062 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser)
1063 : m_pParser(pParser), m_LastObjNum(0) {
1064 if (pParser)
1065 m_LastObjNum = m_pParser->GetLastObjNum();
1066 }
~CPDF_IndirectObjectHolder()1067 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
1068 for (const auto& pair : m_IndirectObjs) {
1069 pair.second->Destroy();
1070 }
1071 }
GetIndirectObject(FX_DWORD objnum,PARSE_CONTEXT * pContext)1072 CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
1073 FX_DWORD objnum,
1074 PARSE_CONTEXT* pContext) {
1075 if (objnum == 0)
1076 return nullptr;
1077
1078 auto it = m_IndirectObjs.find(objnum);
1079 if (it != m_IndirectObjs.end())
1080 return it->second->GetObjNum() != -1 ? it->second : nullptr;
1081
1082 if (!m_pParser)
1083 return nullptr;
1084
1085 CPDF_Object* pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
1086 if (!pObj)
1087 return nullptr;
1088
1089 pObj->m_ObjNum = objnum;
1090 m_LastObjNum = std::max(m_LastObjNum, objnum);
1091 if (m_IndirectObjs[objnum])
1092 m_IndirectObjs[objnum]->Destroy();
1093
1094 m_IndirectObjs[objnum] = pObj;
1095 return pObj;
1096 }
GetIndirectType(FX_DWORD objnum)1097 int CPDF_IndirectObjectHolder::GetIndirectType(FX_DWORD objnum) {
1098 auto it = m_IndirectObjs.find(objnum);
1099 if (it != m_IndirectObjs.end())
1100 return it->second->GetType();
1101
1102 if (!m_pParser)
1103 return 0;
1104
1105 PARSE_CONTEXT context;
1106 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
1107 context.m_Flags = PDFPARSE_TYPEONLY;
1108 return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, &context);
1109 }
AddIndirectObject(CPDF_Object * pObj)1110 FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) {
1111 if (pObj->m_ObjNum) {
1112 return pObj->m_ObjNum;
1113 }
1114 m_LastObjNum++;
1115 m_IndirectObjs[m_LastObjNum] = pObj;
1116 pObj->m_ObjNum = m_LastObjNum;
1117 return m_LastObjNum;
1118 }
ReleaseIndirectObject(FX_DWORD objnum)1119 void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) {
1120 auto it = m_IndirectObjs.find(objnum);
1121 if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1)
1122 return;
1123 it->second->Destroy();
1124 m_IndirectObjs.erase(it);
1125 }
InsertIndirectObject(FX_DWORD objnum,CPDF_Object * pObj)1126 FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum,
1127 CPDF_Object* pObj) {
1128 if (!objnum || !pObj)
1129 return FALSE;
1130 auto it = m_IndirectObjs.find(objnum);
1131 if (it != m_IndirectObjs.end()) {
1132 if (pObj->GetGenNum() <= it->second->GetGenNum()) {
1133 pObj->Destroy();
1134 return FALSE;
1135 }
1136 it->second->Destroy();
1137 }
1138 pObj->m_ObjNum = objnum;
1139 m_IndirectObjs[objnum] = pObj;
1140 m_LastObjNum = std::max(m_LastObjNum, objnum);
1141 return TRUE;
1142 }
1143