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