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