Remove a few unused variables, functions, and member variables.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_objects.cpp
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 "../../../include/fpdfapi/fpdf_parser.h"
8 void CPDF_Object::Release()
9 {
10     if (m_ObjNum) {
11         return;
12     }
13     Destroy();
14 }
15 void CPDF_Object::Destroy()
16 {
17     switch (m_Type) {
18         case PDFOBJ_STRING:
19             delete (CPDF_String*)this;
20             break;
21         case PDFOBJ_NAME:
22             delete (CPDF_Name*)this;
23             break;
24         case PDFOBJ_ARRAY:
25             delete (CPDF_Array*)this;
26             break;
27         case PDFOBJ_DICTIONARY:
28             delete (CPDF_Dictionary*)this;
29             break;
30         case PDFOBJ_STREAM:
31             delete (CPDF_Stream*)this;
32             break;
33         default:
34             delete this;
35     }
36 }
37 CFX_ByteString CPDF_Object::GetString() const
38 {
39     switch (m_Type) {
40         case PDFOBJ_BOOLEAN:
41             return ((CPDF_Boolean*)this)->m_bValue ? "true" : "false";
42         case PDFOBJ_NUMBER:
43             return ((CPDF_Number*)this)->GetString();
44         case PDFOBJ_STRING:
45             return ((CPDF_String*)this)->m_String;
46         case PDFOBJ_NAME:
47             return ((CPDF_Name*)this)->m_Name;
48         case PDFOBJ_REFERENCE: {
49                 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
50                 if (pRef->m_pObjList == NULL) {
51                     break;
52                 }
53                 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
54                 if (pObj == NULL) {
55                     return CFX_ByteString();
56                 }
57                 return pObj->GetString();
58             }
59     }
60     return CFX_ByteString();
61 }
62 CFX_ByteStringC CPDF_Object::GetConstString() const
63 {
64     switch (m_Type) {
65         case PDFOBJ_STRING:
66             return CFX_ByteStringC((FX_LPCBYTE)((CPDF_String*)this)->m_String, ((CPDF_String*)this)->m_String.GetLength());
67         case PDFOBJ_NAME:
68             return CFX_ByteStringC((FX_LPCBYTE)((CPDF_Name*)this)->m_Name, ((CPDF_Name*)this)->m_Name.GetLength());
69         case PDFOBJ_REFERENCE: {
70                 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
71                 if (pRef->m_pObjList == NULL) {
72                     break;
73                 }
74                 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
75                 if (pObj == NULL) {
76                     return CFX_ByteStringC();
77                 }
78                 return pObj->GetConstString();
79             }
80     }
81     return CFX_ByteStringC();
82 }
83 FX_FLOAT CPDF_Object::GetNumber() const
84 {
85     switch (m_Type) {
86         case PDFOBJ_NUMBER:
87             return ((CPDF_Number*)this)->GetNumber();
88         case PDFOBJ_REFERENCE: {
89                 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
90                 if (pRef->m_pObjList == NULL) {
91                     break;
92                 }
93                 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
94                 if (pObj == NULL) {
95                     return 0;
96                 }
97                 return pObj->GetNumber();
98             }
99     }
100     return 0;
101 }
102 FX_FLOAT CPDF_Object::GetNumber16() const
103 {
104     return GetNumber();
105 }
106 int CPDF_Object::GetInteger() const
107 {
108     switch (m_Type) {
109         case PDFOBJ_BOOLEAN:
110             return ((CPDF_Boolean*)this)->m_bValue;
111         case PDFOBJ_NUMBER:
112             return ((CPDF_Number*)this)->GetInteger();
113         case PDFOBJ_REFERENCE: {
114                 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
115                 PARSE_CONTEXT context;
116                 FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT));
117                 if (pRef->m_pObjList == NULL) {
118                     return 0;
119                 }
120                 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum, &context);
121                 if (pObj == NULL) {
122                     return 0;
123                 }
124                 return pObj->GetInteger();
125             }
126     }
127     return 0;
128 }
129 CPDF_Dictionary* CPDF_Object::GetDict() const
130 {
131     switch (m_Type) {
132         case PDFOBJ_DICTIONARY:
133             return (CPDF_Dictionary*)this;
134         case PDFOBJ_STREAM:
135             return ((CPDF_Stream*)this)->GetDict();
136         case PDFOBJ_REFERENCE: {
137                 CPDF_Reference* pRef = (CPDF_Reference*)this;
138                 if (pRef->m_pObjList == NULL) {
139                     break;
140                 }
141                 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
142                 if (pObj == NULL) {
143                     return NULL;
144                 }
145                 return pObj->GetDict();
146             }
147     }
148     return NULL;
149 }
150 CPDF_Array* CPDF_Object::GetArray() const
151 {
152     if (m_Type == PDFOBJ_ARRAY) 
153         return (CPDF_Array*)this;
154     else
155         return NULL;
156 }
157 void CPDF_Object::SetString(const CFX_ByteString& str)
158 {
159     ASSERT(this != NULL);
160     switch (m_Type) {
161         case PDFOBJ_BOOLEAN:
162             ((CPDF_Boolean*)this)->m_bValue = str == FX_BSTRC("true") ? 1 : 0;
163             return;
164         case PDFOBJ_NUMBER:
165             ((CPDF_Number*)this)->SetString(str);
166             return;
167         case PDFOBJ_STRING:
168             ((CPDF_String*)this)->m_String = str;
169             return;
170         case PDFOBJ_NAME:
171             ((CPDF_Name*)this)->m_Name = str;
172             return;
173     }
174     ASSERT(FALSE);
175 }
176 int CPDF_Object::GetDirectType() const
177 {
178     if (m_Type != PDFOBJ_REFERENCE) {
179         return m_Type;
180     }
181     CPDF_Reference* pRef = (CPDF_Reference*)this;
182     return pRef->m_pObjList->GetIndirectType(pRef->m_RefObjNum);
183 }
184 FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const
185 {
186     if (this == pOther) {
187         return TRUE;
188     }
189     if (pOther == NULL) {
190         return FALSE;
191     }
192     if (pOther->m_Type != m_Type) {
193         if (m_Type == PDFOBJ_REFERENCE && GetDirect()) {
194             return GetDirect()->IsIdentical(pOther);
195         } else if (pOther->m_Type == PDFOBJ_REFERENCE) {
196             return IsIdentical(pOther->GetDirect());
197         }
198         return FALSE;
199     }
200     switch (m_Type) {
201         case PDFOBJ_BOOLEAN:
202             return (((CPDF_Boolean*)this)->Identical((CPDF_Boolean*)pOther));
203         case PDFOBJ_NUMBER:
204             return (((CPDF_Number*)this)->Identical((CPDF_Number*)pOther));
205         case PDFOBJ_STRING:
206             return (((CPDF_String*)this)->Identical((CPDF_String*)pOther));
207         case PDFOBJ_NAME:
208             return (((CPDF_Name*)this)->Identical((CPDF_Name*)pOther));
209         case PDFOBJ_ARRAY:
210             return (((CPDF_Array*)this)->Identical((CPDF_Array*)pOther));
211         case PDFOBJ_DICTIONARY:
212             return (((CPDF_Dictionary*)this)->Identical((CPDF_Dictionary*)pOther));
213         case PDFOBJ_NULL:
214             return TRUE;
215         case PDFOBJ_STREAM:
216             return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther));
217         case PDFOBJ_REFERENCE:
218             return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther));
219     }
220     return FALSE;
221 }
222 CPDF_Object* CPDF_Object::GetDirect() const
223 {
224     if (m_Type != PDFOBJ_REFERENCE) {
225         return (CPDF_Object*)this;
226     }
227     CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
228     if (pRef->m_pObjList == NULL) {
229         return NULL;
230     }
231     return pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
232 }
233 CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const
234 {
235     CFX_MapPtrToPtr visited;
236     return CloneInternal(bDirect, &visited);
237 }
238 CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const
239 {
240     switch (m_Type) {
241         case PDFOBJ_BOOLEAN:
242             return FX_NEW CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue);
243         case PDFOBJ_NUMBER:
244             return FX_NEW CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer);
245         case PDFOBJ_STRING:
246             return FX_NEW CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex());
247         case PDFOBJ_NAME:
248             return FX_NEW CPDF_Name(((CPDF_Name*)this)->m_Name);
249         case PDFOBJ_ARRAY: {
250                 CPDF_Array* pCopy = FX_NEW CPDF_Array();
251                 CPDF_Array* pThis = (CPDF_Array*)this;
252                 int n = pThis->GetCount();
253                 for (int i = 0; i < n; i ++) {
254                     CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i);
255                     pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
256                 }
257                 return pCopy;
258             }
259         case PDFOBJ_DICTIONARY: {
260                 CPDF_Dictionary* pCopy = FX_NEW CPDF_Dictionary();
261                 CPDF_Dictionary* pThis = (CPDF_Dictionary*)this;
262                 FX_POSITION pos = pThis->m_Map.GetStartPosition();
263                 while (pos) {
264                     CFX_ByteString key;
265                     CPDF_Object* value;
266                     pThis->m_Map.GetNextAssoc(pos, key, (void*&)value);
267                     pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited));
268                 }
269                 return pCopy;
270             }
271         case PDFOBJ_NULL: {
272                 return FX_NEW CPDF_Null;
273             }
274         case PDFOBJ_STREAM: {
275                 CPDF_Stream* pThis = (CPDF_Stream*)this;
276                 CPDF_StreamAcc acc;
277                 acc.LoadAllData(pThis, TRUE);
278                 FX_DWORD streamSize = acc.GetSize();
279                 CPDF_Stream* pObj;
280                 if (pThis->GetDict())
281                     pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited));
282                 else
283                     pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, NULL);
284                 return pObj;
285             }
286         case PDFOBJ_REFERENCE: {
287                 CPDF_Reference* pRef = (CPDF_Reference*)this;
288                 FX_DWORD obj_num = pRef->m_RefObjNum;
289                 if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) {
290                     visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1);
291                     CPDF_Object* ret;
292                     if (pRef->GetDirect())
293                         ret = pRef->GetDirect()->CloneInternal(TRUE, visited);
294                     else
295                         ret = NULL;
296                     return ret;
297                 } else {
298                     return FX_NEW CPDF_Reference(pRef->m_pObjList, obj_num);
299                 }
300             }
301     }
302     return NULL;
303 }
304 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const
305 {
306     if (m_ObjNum) {
307         return FX_NEW CPDF_Reference(pDoc, m_ObjNum);
308     }
309     return Clone();
310 }
311 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const
312 {
313     if (m_Type == PDFOBJ_STRING) {
314         return PDF_DecodeText(((CPDF_String*)this)->m_String, pCharMap);
315     } else if (m_Type == PDFOBJ_STREAM) {
316         CPDF_StreamAcc stream;
317         stream.LoadAllData((CPDF_Stream*)this, FALSE);
318         CFX_WideString result = PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
319         return result;
320     } else if (m_Type == PDFOBJ_NAME) {
321         return PDF_DecodeText(((CPDF_Name*)this)->m_Name, pCharMap);
322     }
323     return CFX_WideString();
324 }
325 void CPDF_Object::SetUnicodeText(FX_LPCWSTR pUnicodes, int len)
326 {
327     if (m_Type == PDFOBJ_STRING) {
328         ((CPDF_String*)this)->m_String = PDF_EncodeText(pUnicodes, len);
329     } else if (m_Type == PDFOBJ_STREAM) {
330         CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
331         ((CPDF_Stream*)this)->SetData((FX_LPBYTE)(FX_LPCSTR)result, result.GetLength(), FALSE, FALSE);
332     }
333 }
334 CPDF_Number::CPDF_Number(int value)
335 {
336     m_Type = PDFOBJ_NUMBER;
337     m_bInteger = TRUE;
338     m_Integer = value;
339 }
340 CPDF_Number::CPDF_Number(FX_FLOAT value)
341 {
342     m_Type = PDFOBJ_NUMBER;
343     m_bInteger = FALSE;
344     m_Float = value;
345 }
346 CPDF_Number::CPDF_Number(FX_BOOL bInteger, void* pData)
347 {
348     m_Type = PDFOBJ_NUMBER;
349     m_bInteger = bInteger;
350     m_Integer = *(int*)pData;
351 }
352 extern void FX_atonum(FX_BSTR, FX_BOOL&, void*);
353 CPDF_Number::CPDF_Number(FX_BSTR str)
354 {
355     m_Type = PDFOBJ_NUMBER;
356     FX_atonum(str, m_bInteger, &m_Integer);
357 }
358 void CPDF_Number::SetString(FX_BSTR str)
359 {
360     FX_atonum(str, m_bInteger, &m_Integer);
361 }
362 FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const
363 {
364     return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
365 }
366 CFX_ByteString CPDF_Number::GetString() const
367 {
368     return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) : CFX_ByteString::FormatFloat(m_Float);
369 }
370 void CPDF_Number::SetNumber(FX_FLOAT value)
371 {
372     m_bInteger = FALSE;
373     m_Float = value;
374 }
375 CPDF_String::CPDF_String(const CFX_WideString& str)
376 {
377     m_Type = PDFOBJ_STRING;
378     m_String = PDF_EncodeText(str, str.GetLength());
379     m_bHex = FALSE;
380 }
381 CPDF_Array::~CPDF_Array()
382 {
383     int size = m_Objects.GetSize();
384     CPDF_Object** pList = (CPDF_Object**)m_Objects.GetData();
385     for (int i = 0; i < size; i ++) {
386         if (pList[i])
387             pList[i]->Release();
388     }
389 }
390 CFX_FloatRect CPDF_Array::GetRect()
391 {
392     CFX_FloatRect rect;
393     if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 4) {
394         return rect;
395     }
396     rect.left = GetNumber(0);
397     rect.bottom = GetNumber(1);
398     rect.right = GetNumber(2);
399     rect.top = GetNumber(3);
400     return rect;
401 }
402 CFX_AffineMatrix CPDF_Array::GetMatrix()
403 {
404     CFX_AffineMatrix matrix;
405     if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 6) {
406         return matrix;
407     }
408     matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3), GetNumber(4), GetNumber(5));
409     return matrix;
410 }
411 CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const
412 {
413     if (i >= (FX_DWORD)m_Objects.GetSize()) {
414         return NULL;
415     }
416     return (CPDF_Object*)m_Objects.GetAt(i);
417 }
418 CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const
419 {
420     if (i >= (FX_DWORD)m_Objects.GetSize()) {
421         return NULL;
422     }
423     return ((CPDF_Object*)m_Objects.GetAt(i))->GetDirect();
424 }
425 CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const
426 {
427     if (i < (FX_DWORD)m_Objects.GetSize()) {
428         CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
429         return p->GetString();
430     }
431     else
432         return CFX_ByteString();
433 }
434 CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const
435 {
436     if (i < (FX_DWORD)m_Objects.GetSize()) {
437         CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
438         return p->GetConstString();
439     }
440     else
441         return CFX_ByteStringC();
442 }
443 int CPDF_Array::GetInteger(FX_DWORD i) const
444 {
445     if (i >= (FX_DWORD)m_Objects.GetSize()) {
446         return 0;
447     }
448     CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
449     return p->GetInteger();
450 }
451 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const
452 {
453     if (i >= (FX_DWORD)m_Objects.GetSize()) {
454         return 0;
455     }
456     CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
457     return p->GetNumber();
458 }
459 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const
460 {
461     CPDF_Object* p = GetElementValue(i);
462     if (p == NULL) {
463         return NULL;
464     } else if (p->GetType() == PDFOBJ_DICTIONARY) {
465         return (CPDF_Dictionary*)p;
466     } else if (p->GetType() == PDFOBJ_STREAM) {
467         return ((CPDF_Stream*)p)->GetDict();
468     }
469     return NULL;
470 }
471 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const
472 {
473     CPDF_Object* p = GetElementValue(i);
474     if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
475         return NULL;
476     }
477     return (CPDF_Stream*)p;
478 }
479 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const
480 {
481     CPDF_Object* p = GetElementValue(i);
482     if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
483         return NULL;
484     }
485     return (CPDF_Array*)p;
486 }
487 void CPDF_Array::RemoveAt(FX_DWORD i)
488 {
489     ASSERT(m_Type == PDFOBJ_ARRAY);
490     if (i >= (FX_DWORD)m_Objects.GetSize()) {
491         return;
492     }
493     CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
494     if (p)
495         p->Release();
496     m_Objects.RemoveAt(i);
497 }
498 void CPDF_Array::SetAt(FX_DWORD i, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
499 {
500     ASSERT(m_Type == PDFOBJ_ARRAY);
501     ASSERT(i < (FX_DWORD)m_Objects.GetSize());
502     if (i >= (FX_DWORD)m_Objects.GetSize()) {
503         return;
504     }
505     CPDF_Object* pOld = (CPDF_Object*)m_Objects.GetAt(i);
506     if (pOld)
507         pOld->Release();
508     if (pObj->GetObjNum()) {
509         ASSERT(pObjs != NULL);
510         pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
511     }
512     m_Objects.SetAt(i, pObj);
513 }
514 void CPDF_Array::InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
515 {
516     ASSERT(pObj != NULL);
517     if (pObj->GetObjNum()) {
518         ASSERT(pObjs != NULL);
519         pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
520     }
521     m_Objects.InsertAt(index, pObj);
522 }
523 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
524 {
525     ASSERT(pObj != NULL);
526     if (pObj->GetObjNum()) {
527         ASSERT(pObjs != NULL);
528         pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
529     }
530     m_Objects.Add(pObj);
531 }
532 void CPDF_Array::AddName(const CFX_ByteString& str)
533 {
534     ASSERT(m_Type == PDFOBJ_ARRAY);
535     Add(FX_NEW CPDF_Name(str));
536 }
537 void CPDF_Array::AddString(const CFX_ByteString& str)
538 {
539     ASSERT(m_Type == PDFOBJ_ARRAY);
540     Add(FX_NEW CPDF_String(str));
541 }
542 void CPDF_Array::AddInteger(int i)
543 {
544     ASSERT(m_Type == PDFOBJ_ARRAY);
545     Add(FX_NEW CPDF_Number(i));
546 }
547 void CPDF_Array::AddNumber(FX_FLOAT f)
548 {
549     ASSERT(m_Type == PDFOBJ_ARRAY);
550     CPDF_Number* pNumber = FX_NEW CPDF_Number;
551     pNumber->SetNumber(f);
552     Add(pNumber);
553 }
554 void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
555 {
556     ASSERT(m_Type == PDFOBJ_ARRAY);
557     Add(FX_NEW CPDF_Reference(pDoc, objnum));
558 }
559 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const
560 {
561     if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
562         return FALSE;
563     }
564     for (int i = 0; i < m_Objects.GetSize(); i ++)
565         if (!((CPDF_Object*)m_Objects[i])->IsIdentical((CPDF_Object*)pOther->m_Objects[i])) {
566             return FALSE;
567         }
568     return TRUE;
569 }
570 CPDF_Dictionary::~CPDF_Dictionary()
571 {
572     FX_POSITION pos = m_Map.GetStartPosition();
573     while (pos) {
574         FX_LPVOID value = m_Map.GetNextValue(pos);
575         if (value)
576             ((CPDF_Object*)value)->Release();
577     }
578 }
579 FX_POSITION CPDF_Dictionary::GetStartPos() const
580 {
581     return m_Map.GetStartPosition();
582 }
583 CPDF_Object* CPDF_Dictionary::GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const
584 {
585     if (pos == NULL) {
586         return NULL;
587     }
588     CPDF_Object* p;
589     m_Map.GetNextAssoc(pos, key, (FX_LPVOID&)p);
590     return p;
591 }
592 CPDF_Object* CPDF_Dictionary::GetElement(FX_BSTR key) const
593 {
594     CPDF_Object* p = NULL;
595     m_Map.Lookup(key, (void*&)p);
596     return p;
597 }
598 CPDF_Object* CPDF_Dictionary::GetElementValue(FX_BSTR key) const
599 {
600     CPDF_Object* p = NULL;
601     m_Map.Lookup(key, (void*&)p);
602     return p ? p->GetDirect() : NULL;
603 }
604 CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key) const
605 {
606     CPDF_Object* p = NULL;
607     m_Map.Lookup(key, (void*&)p);
608     if (p)
609         return p->GetString();
610     else
611         return CFX_ByteString();
612 }
613 CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key) const
614 {
615     CPDF_Object* p = NULL;
616     m_Map.Lookup(key, (void*&)p);
617     if (p)
618         return p->GetConstString();
619     else
620         return CFX_ByteStringC();
621 }
622 CFX_WideString CPDF_Dictionary::GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap) const
623 {
624     CPDF_Object* p = NULL;
625     m_Map.Lookup(key, (void*&)p);
626     if (p) {
627         if(p->GetType() == PDFOBJ_REFERENCE) {
628             p = ((CPDF_Reference*)p)->GetDirect();
629             return p->GetUnicodeText(pCharMap);
630         } else {
631             return p->GetUnicodeText(pCharMap);
632         }
633     }
634     return CFX_WideString();
635 }
636 CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key, FX_BSTR def) const
637 {
638     CPDF_Object* p = NULL;
639     m_Map.Lookup(key, (void*&)p);
640     if (p) {
641         return p->GetString();
642     }
643     return CFX_ByteString(def);
644 }
645 CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key, FX_BSTR def) const
646 {
647     CPDF_Object* p = NULL;
648     m_Map.Lookup(key, (void*&)p);
649     if (p)
650         return p->GetConstString();
651     else
652         return CFX_ByteStringC(def);
653 }
654 int CPDF_Dictionary::GetInteger(FX_BSTR key) const
655 {
656     CPDF_Object* p = NULL;
657     m_Map.Lookup(key, (void*&)p);
658     if (p) {
659         return p->GetInteger();
660     }
661     return 0;
662 }
663 int CPDF_Dictionary::GetInteger(FX_BSTR key, int def) const
664 {
665     CPDF_Object* p = NULL;
666     m_Map.Lookup(key, (void*&)p);
667     if (p) {
668         return p->GetInteger();
669     }
670     return def;
671 }
672 FX_FLOAT CPDF_Dictionary::GetNumber(FX_BSTR key) const
673 {
674     CPDF_Object* p = NULL;
675     m_Map.Lookup(key, (void*&)p);
676     if (p) {
677         return p->GetNumber();
678     }
679     return 0;
680 }
681 FX_BOOL CPDF_Dictionary::GetBoolean(FX_BSTR key, FX_BOOL bDefault) const
682 {
683     CPDF_Object* p = NULL;
684     m_Map.Lookup(key, (void*&)p);
685     if (p && p->GetType() == PDFOBJ_BOOLEAN) {
686         return p->GetInteger();
687     }
688     return bDefault;
689 }
690 CPDF_Dictionary* CPDF_Dictionary::GetDict(FX_BSTR key) const
691 {
692     CPDF_Object* p = GetElementValue(key);
693     if (p == NULL) {
694         return NULL;
695     } else if (p->GetType() == PDFOBJ_DICTIONARY) {
696         return (CPDF_Dictionary*)p;
697     } else if (p->GetType() == PDFOBJ_STREAM) {
698         return ((CPDF_Stream*)p)->GetDict();
699     }
700     return NULL;
701 }
702 CPDF_Array* CPDF_Dictionary::GetArray(FX_BSTR key) const
703 {
704     CPDF_Object* p = GetElementValue(key);
705     if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
706         return NULL;
707     }
708     return (CPDF_Array*)p;
709 }
710 CPDF_Stream* CPDF_Dictionary::GetStream(FX_BSTR key) const
711 {
712     CPDF_Object* p = GetElementValue(key);
713     if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
714         return NULL;
715     }
716     return (CPDF_Stream*)p;
717 }
718 CFX_FloatRect CPDF_Dictionary::GetRect(FX_BSTR key) const
719 {
720     CFX_FloatRect rect;
721     CPDF_Array* pArray = GetArray(key);
722     if (pArray) {
723         rect = pArray->GetRect();
724     }
725     return rect;
726 }
727 CFX_AffineMatrix CPDF_Dictionary::GetMatrix(FX_BSTR key) const
728 {
729     CFX_AffineMatrix matrix;
730     CPDF_Array* pArray = GetArray(key);
731     if (pArray) {
732         matrix = pArray->GetMatrix();
733     }
734     return matrix;
735 }
736 FX_BOOL CPDF_Dictionary::KeyExist(FX_BSTR key) const
737 {
738     FX_LPVOID value;
739     return m_Map.Lookup(key, value);
740 }
741 void CPDF_Dictionary::SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
742 {
743     ASSERT(m_Type == PDFOBJ_DICTIONARY);
744     CPDF_Object* p = NULL;
745     m_Map.Lookup(key, (void*&)p);
746     if (p == pObj) {
747         return;
748     }
749     if (p)
750         p->Release();
751     if (pObj) {
752         if (pObj->GetObjNum()) {
753             ASSERT(pObjs != NULL);
754             pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
755         }
756         m_Map.SetAt(key, pObj);
757     } else {
758         m_Map.RemoveKey(key);
759     }
760 }
761 void CPDF_Dictionary::AddValue(FX_BSTR key, CPDF_Object* pObj)
762 {
763     ASSERT(m_Type == PDFOBJ_DICTIONARY);
764     m_Map.AddValue(key, pObj);
765 }
766 void CPDF_Dictionary::RemoveAt(FX_BSTR key)
767 {
768     ASSERT(m_Type == PDFOBJ_DICTIONARY);
769     CPDF_Object* p = NULL;
770     m_Map.Lookup(key, (void*&)p);
771     if (p == NULL) {
772         return;
773     }
774     p->Release();
775     m_Map.RemoveKey(key);
776 }
777 void CPDF_Dictionary::ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey)
778 {
779     ASSERT(m_Type == PDFOBJ_DICTIONARY);
780     CPDF_Object* p = NULL;
781     m_Map.Lookup(oldkey, (void*&)p);
782     if (p == NULL) {
783         return;
784     }
785     m_Map.RemoveKey(oldkey);
786     m_Map.SetAt(newkey, p);
787 }
788 FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const
789 {
790     if (pOther == NULL) {
791         return FALSE;
792     }
793     if (m_Map.GetCount() != pOther->m_Map.GetCount()) {
794         return FALSE;
795     }
796     FX_POSITION pos = m_Map.GetStartPosition();
797     while (pos) {
798         CFX_ByteString key;
799         FX_LPVOID value;
800         m_Map.GetNextAssoc(pos, key, value);
801         if (!value)
802             return FALSE;
803         if (!((CPDF_Object*)value)->IsIdentical(pOther->GetElement(key))) {
804             return FALSE;
805         }
806     }
807     return TRUE;
808 }
809 void CPDF_Dictionary::SetAtInteger(FX_BSTR key, int i)
810 {
811     SetAt(key, FX_NEW CPDF_Number(i));
812 }
813 void CPDF_Dictionary::SetAtName(FX_BSTR key, const CFX_ByteString& name)
814 {
815     SetAt(key, FX_NEW CPDF_Name(name));
816 }
817 void CPDF_Dictionary::SetAtString(FX_BSTR key, const CFX_ByteString& str)
818 {
819     SetAt(key, FX_NEW CPDF_String(str));
820 }
821 void CPDF_Dictionary::SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
822 {
823     SetAt(key, FX_NEW CPDF_Reference(pDoc, objnum));
824 }
825 void CPDF_Dictionary::AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
826 {
827     AddValue(key, FX_NEW CPDF_Reference(pDoc, objnum));
828 }
829 void CPDF_Dictionary::SetAtNumber(FX_BSTR key, FX_FLOAT f)
830 {
831     CPDF_Number* pNumber = FX_NEW CPDF_Number;
832     pNumber->SetNumber(f);
833     SetAt(key, pNumber);
834 }
835 void CPDF_Dictionary::SetAtBoolean(FX_BSTR key, FX_BOOL bValue)
836 {
837     SetAt(key, FX_NEW CPDF_Boolean(bValue));
838 }
839 void CPDF_Dictionary::SetAtRect(FX_BSTR key, const CFX_FloatRect& rect)
840 {
841     CPDF_Array* pArray = FX_NEW CPDF_Array;
842     pArray->AddNumber(rect.left);
843     pArray->AddNumber(rect.bottom);
844     pArray->AddNumber(rect.right);
845     pArray->AddNumber(rect.top);
846     SetAt(key, pArray);
847 }
848 void CPDF_Dictionary::SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix)
849 {
850     CPDF_Array* pArray = FX_NEW CPDF_Array;
851     pArray->AddNumber16(matrix.a);
852     pArray->AddNumber16(matrix.b);
853     pArray->AddNumber16(matrix.c);
854     pArray->AddNumber16(matrix.d);
855     pArray->AddNumber(matrix.e);
856     pArray->AddNumber(matrix.f);
857     SetAt(key, pArray);
858 }
859 CPDF_Stream::CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict)
860 {
861     m_Type = PDFOBJ_STREAM;
862     m_pDict = pDict;
863     m_dwSize = size;
864     m_GenNum = (FX_DWORD) - 1;
865     m_pDataBuf = pData;
866     m_pCryptoHandler = NULL;
867 }
868 CPDF_Stream::~CPDF_Stream()
869 {
870     if (m_GenNum == (FX_DWORD) - 1 && m_pDataBuf != NULL) {
871         FX_Free(m_pDataBuf);
872     }
873     if (m_pDict) {
874         m_pDict->Release();
875     }
876 }
877 void CPDF_Stream::InitStream(CPDF_Dictionary* pDict)
878 {
879     if (pDict) {
880         if (m_pDict) {
881             m_pDict->Release();
882         }
883         m_pDict = pDict;
884     }
885     if (m_GenNum == (FX_DWORD) - 1) {
886         if (m_pDataBuf) {
887             FX_Free(m_pDataBuf);
888         }
889     }
890     m_GenNum = 0;
891     m_pFile = NULL;
892     m_pCryptoHandler = NULL;
893     m_FileOffset = 0;
894 }
895 void CPDF_Stream::InitStream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict)
896 {
897     InitStream(pDict);
898     m_GenNum = (FX_DWORD) - 1;
899     m_pDataBuf = FX_Alloc(FX_BYTE, size);
900     if (pData) {
901         FXSYS_memcpy32(m_pDataBuf, pData, size);
902     }
903     m_dwSize = size;
904     if (m_pDict) {
905         m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
906     }
907 }
908 void CPDF_Stream::SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf)
909 {
910     if (m_GenNum == (FX_DWORD) - 1) {
911         if (m_pDataBuf) {
912             FX_Free(m_pDataBuf);
913         }
914     } else {
915         m_GenNum = (FX_DWORD) - 1;
916         m_pCryptoHandler = NULL;
917     }
918     if (bKeepBuf) {
919         m_pDataBuf = (FX_LPBYTE)pData;
920     } else {
921         m_pDataBuf = FX_Alloc(FX_BYTE, size);
922         if (pData) {
923             FXSYS_memcpy32(m_pDataBuf, pData, size);
924         }
925     }
926     m_dwSize = size;
927     if (m_pDict == NULL) {
928         m_pDict = FX_NEW CPDF_Dictionary;
929     }
930     m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
931     if (!bCompressed) {
932         m_pDict->RemoveAt(FX_BSTRC("Filter"));
933         m_pDict->RemoveAt(FX_BSTRC("DecodeParms"));
934     }
935 }
936 FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset, FX_LPBYTE buf, FX_DWORD size) const
937 {
938     if ((m_GenNum != (FX_DWORD) - 1) && m_pFile) {
939         return m_pFile->ReadBlock(buf, m_FileOffset + offset, size);
940     }
941     if (m_pDataBuf) {
942         FXSYS_memcpy32(buf, m_pDataBuf + offset, size);
943     }
944     return TRUE;
945 }
946 void CPDF_Stream::InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict)
947 {
948     InitStream(pDict);
949     m_pFile = pFile;
950     m_dwSize = (FX_DWORD)pFile->GetSize();
951     if (m_pDict) {
952         m_pDict->SetAtInteger(FX_BSTRC("Length"), m_dwSize);
953     }
954 }
955 FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const
956 {
957     if (!m_pDict)
958         return pOther->m_pDict ? FALSE : TRUE;
959
960     if (!m_pDict->Identical(pOther->m_pDict)) {
961         return FALSE;
962     }
963     if (m_dwSize != pOther->m_dwSize) {
964         return FALSE;
965     }
966     if (m_GenNum != (FX_DWORD) - 1 && pOther->m_GenNum != (FX_DWORD) - 1) {
967         if (m_pFile == pOther->m_pFile && m_pFile == NULL) {
968             return TRUE;
969         }
970         if (!m_pFile || !pOther->m_pFile) {
971             return FALSE;
972         }
973         FX_BYTE srcBuf[1024];
974         FX_BYTE destBuf[1024];
975         FX_DWORD size = m_dwSize;
976         FX_DWORD srcOffset = m_FileOffset;
977         FX_DWORD destOffset = pOther->m_FileOffset;
978         if (m_pFile == pOther->m_pFile && srcOffset == destOffset) {
979             return TRUE;
980         }
981         while (size > 0) {
982             FX_DWORD actualSize = size > 1024 ? 1024 : size;
983             m_pFile->ReadBlock(srcBuf, srcOffset, actualSize);
984             pOther->m_pFile->ReadBlock(destBuf, destOffset, actualSize);
985             if (FXSYS_memcmp32(srcBuf, destBuf, actualSize) != 0) {
986                 return FALSE;
987             }
988             size -= actualSize;
989             srcOffset += actualSize;
990             destOffset += actualSize;
991         }
992         return TRUE;
993     }
994     if (m_GenNum != (FX_DWORD) - 1 || pOther->m_GenNum != (FX_DWORD) - 1) {
995         IFX_FileRead* pFile = NULL;
996         FX_LPBYTE pBuf = NULL;
997         FX_DWORD offset = 0;
998         if (m_GenNum != (FX_DWORD) - 1) {
999             pFile = m_pFile;
1000             pBuf = pOther->m_pDataBuf;
1001             offset = m_FileOffset;
1002         }
1003         if (pOther->m_GenNum != (FX_DWORD) - 1) {
1004             pFile = pOther->m_pFile;
1005             pBuf = m_pDataBuf;
1006             offset = pOther->m_FileOffset;
1007         }
1008         if (NULL == pBuf) {
1009             return FALSE;
1010         }
1011         FX_BYTE srcBuf[1024];
1012         FX_DWORD size = m_dwSize;
1013         while (size > 0) {
1014             FX_DWORD actualSize = size > 1024 ? 1024 : size;
1015             m_pFile->ReadBlock(srcBuf, offset, actualSize);
1016             if (FXSYS_memcmp32(srcBuf, pBuf, actualSize) != 0) {
1017                 return FALSE;
1018             }
1019             pBuf += actualSize;
1020             size -= actualSize;
1021             offset += actualSize;
1022         }
1023         return TRUE;
1024     }
1025     return FXSYS_memcmp32(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
1026 }
1027 CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const
1028 {
1029     CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect);
1030     IFX_FileStream *pFS = NULL;
1031     if (lpfCallback) {
1032         pFS = lpfCallback((CPDF_Stream*)this, pUserData);
1033     }
1034     if (!pFS) {
1035         CPDF_StreamAcc acc;
1036         acc.LoadAllData(this, TRUE);
1037         FX_DWORD streamSize = acc.GetSize();
1038         CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, pCloneDict);
1039         return pObj;
1040     }
1041     CPDF_Stream* pObj = FX_NEW CPDF_Stream(NULL, 0, NULL);
1042     CPDF_StreamFilter *pSF = GetStreamFilter(TRUE);
1043     if (pSF) {
1044         FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096);
1045         FX_DWORD dwRead;
1046         do {
1047             dwRead = pSF->ReadBlock(pBuf, 4096);
1048             if (dwRead) {
1049                 pFS->WriteBlock(pBuf, dwRead);
1050             }
1051         } while (dwRead == 4096);
1052         pFS->Flush();
1053         FX_Free(pBuf);
1054         delete pSF;
1055     }
1056     pObj->InitStream((IFX_FileRead*)pFS, pCloneDict);
1057     return pObj;
1058 }
1059 extern FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict,
1060                               FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding,
1061                               CPDF_Dictionary*& pImageParms, FX_DWORD estimated_size, FX_BOOL bImageAcc);
1062 CPDF_StreamAcc::CPDF_StreamAcc()
1063 {
1064     m_bNewBuf = FALSE;
1065     m_pData = NULL;
1066     m_dwSize = 0;
1067     m_pImageParam = NULL;
1068     m_pStream = NULL;
1069     m_pSrcData = NULL;
1070 }
1071 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess, FX_DWORD estimated_size,
1072                                  FX_BOOL bImageAcc)
1073 {
1074     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1075         return;
1076     }
1077     m_pStream = pStream;
1078     if (pStream->IsMemoryBased() &&
1079             (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) {
1080         m_dwSize = pStream->m_dwSize;
1081         m_pData = (FX_LPBYTE)pStream->m_pDataBuf;
1082         return;
1083     }
1084     FX_LPBYTE pSrcData;
1085     FX_DWORD dwSrcSize = pStream->m_dwSize;
1086     if (dwSrcSize == 0) {
1087         return;
1088     }
1089     if (!pStream->IsMemoryBased()) {
1090         pSrcData = m_pSrcData = FX_Alloc(FX_BYTE, dwSrcSize);
1091         if (!pSrcData || !pStream->ReadRawData(0, pSrcData, dwSrcSize)) {
1092             return;
1093         }
1094     } else {
1095         pSrcData = pStream->m_pDataBuf;
1096     }
1097     FX_LPBYTE pDecryptedData;
1098     FX_DWORD dwDecryptedSize;
1099     if (pStream->m_pCryptoHandler) {
1100         CFX_BinaryBuf dest_buf;
1101         dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize));
1102         FX_LPVOID context = pStream->m_pCryptoHandler->DecryptStart(pStream->GetObjNum(), pStream->m_GenNum);
1103         pStream->m_pCryptoHandler->DecryptStream(context, pSrcData, dwSrcSize, dest_buf);
1104         pStream->m_pCryptoHandler->DecryptFinish(context, dest_buf);
1105         pDecryptedData = dest_buf.GetBuffer();
1106         dwDecryptedSize = dest_buf.GetSize();
1107         dest_buf.DetachBuffer();
1108     } else {
1109         pDecryptedData = pSrcData;
1110         dwDecryptedSize = dwSrcSize;
1111     }
1112     if (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess) {
1113         m_pData = pDecryptedData;
1114         m_dwSize = dwDecryptedSize;
1115     } else {
1116         FX_BOOL bRet = PDF_DataDecode(pDecryptedData, dwDecryptedSize, m_pStream->GetDict(),
1117                                       m_pData, m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc);
1118         if (!bRet) {
1119             m_pData = pDecryptedData;
1120             m_dwSize = dwDecryptedSize;
1121         }
1122     }
1123     if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
1124         FX_Free(pSrcData);
1125     }
1126     if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
1127         FX_Free(pDecryptedData);
1128     }
1129     m_pSrcData = NULL;
1130     m_bNewBuf = m_pData != pStream->m_pDataBuf;
1131 }
1132 CPDF_StreamAcc::~CPDF_StreamAcc()
1133 {
1134     if (m_bNewBuf && m_pData) {
1135         FX_Free(m_pData);
1136     }
1137     if (m_pSrcData) {
1138         FX_Free(m_pSrcData);
1139     }
1140 }
1141 FX_LPCBYTE CPDF_StreamAcc::GetData() const
1142 {
1143     if (m_bNewBuf) {
1144         return m_pData;
1145     }
1146     if (!m_pStream) {
1147         return NULL;
1148     }
1149     return m_pStream->m_pDataBuf;
1150 }
1151 FX_DWORD CPDF_StreamAcc::GetSize() const
1152 {
1153     if (m_bNewBuf) {
1154         return m_dwSize;
1155     }
1156     if (!m_pStream) {
1157         return 0;
1158     }
1159     return m_pStream->m_dwSize;
1160 }
1161 FX_LPBYTE CPDF_StreamAcc::DetachData()
1162 {
1163     if (m_bNewBuf) {
1164         FX_LPBYTE p = m_pData;
1165         m_pData = NULL;
1166         m_dwSize = 0;
1167         return p;
1168     }
1169     FX_LPBYTE p = FX_Alloc(FX_BYTE, m_dwSize);
1170     if (p == NULL) {
1171         return NULL;
1172     }
1173     FXSYS_memcpy32(p, m_pData, m_dwSize);
1174     return p;
1175 }
1176 void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
1177 {
1178     m_pObjList = pDoc;
1179     m_RefObjNum = objnum;
1180 }
1181 CPDF_IndirectObjects::CPDF_IndirectObjects(IPDF_DocParser* pParser)
1182 {
1183     m_pParser = pParser;
1184     m_IndirectObjs.InitHashTable(1013);
1185     if (pParser) {
1186         m_LastObjNum = m_pParser->GetLastObjNum();
1187     } else {
1188         m_LastObjNum = 0;
1189     }
1190 }
1191 CPDF_IndirectObjects::~CPDF_IndirectObjects()
1192 {
1193     FX_POSITION pos = m_IndirectObjs.GetStartPosition();
1194     while (pos) {
1195         FX_LPVOID key, value;
1196         m_IndirectObjs.GetNextAssoc(pos, key, value);
1197         ((CPDF_Object*)value)->Destroy();
1198     }
1199 }
1200 CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext)
1201 {
1202     if (objnum == 0) {
1203         return NULL;
1204     }
1205     FX_LPVOID value;
1206     {
1207         if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1208             if (((CPDF_Object*)value)->GetObjNum() == -1) {
1209                 return NULL;
1210             }
1211             return (CPDF_Object*)value;
1212         }
1213     }
1214     CPDF_Object* pObj = NULL;
1215     if (m_pParser) {
1216         pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
1217     }
1218     if (pObj == NULL) {
1219         return NULL;
1220     }
1221     pObj->m_ObjNum = objnum;
1222     if (m_LastObjNum < objnum) {
1223         m_LastObjNum = objnum;
1224     }
1225     if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1226         if (value) {
1227             ((CPDF_Object *)value)->Destroy();
1228         }
1229     }
1230     m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj);
1231     return pObj;
1232 }
1233 int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum)
1234 {
1235     FX_LPVOID value;
1236     if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1237         return ((CPDF_Object*)value)->GetType();
1238     }
1239     if (m_pParser) {
1240         PARSE_CONTEXT context;
1241         FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT));
1242         context.m_Flags = PDFPARSE_TYPEONLY;
1243         return (int)(FX_UINTPTR)m_pParser->ParseIndirectObject(this, objnum, &context);
1244     }
1245     return 0;
1246 }
1247 FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj)
1248 {
1249     if (pObj->m_ObjNum) {
1250         return pObj->m_ObjNum;
1251     }
1252     m_LastObjNum ++;
1253     m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)m_LastObjNum, pObj);
1254     pObj->m_ObjNum = m_LastObjNum;
1255     return m_LastObjNum;
1256 }
1257 void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum)
1258 {
1259     FX_LPVOID value;
1260     if (!m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1261         return;
1262     }
1263     if (((CPDF_Object*)value)->GetObjNum() == -1) {
1264         return;
1265     }
1266     ((CPDF_Object*)value)->Destroy();
1267     m_IndirectObjs.RemoveKey((FX_LPVOID)(FX_UINTPTR)objnum);
1268 }
1269 void CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj)
1270 {
1271     if (objnum == 0 || pObj == NULL) {
1272         return;
1273     }
1274     FX_LPVOID value = NULL;
1275     if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1276         if (value)
1277         {
1278             if (pObj->GetGenNum() <= ((CPDF_Object*)value)->GetGenNum())
1279                 return;
1280             else 
1281                 ((CPDF_Object*)value)->Destroy();
1282          }         
1283     }
1284     pObj->m_ObjNum = objnum;
1285     m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj);
1286     if (m_LastObjNum < objnum) {
1287         m_LastObjNum = objnum;
1288     }
1289 }
1290 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const
1291 {
1292     return m_LastObjNum;
1293 }