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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fpdfapi/fpdf_parser.h"
8 void CPDF_Object::Release()
15 void CPDF_Object::Destroy()
19 delete (CPDF_String*)this;
22 delete (CPDF_Name*)this;
25 delete (CPDF_Array*)this;
27 case PDFOBJ_DICTIONARY:
28 delete (CPDF_Dictionary*)this;
31 delete (CPDF_Stream*)this;
37 CFX_ByteString CPDF_Object::GetString() const
41 return ((CPDF_Boolean*)this)->m_bValue ? "true" : "false";
43 return ((CPDF_Number*)this)->GetString();
45 return ((CPDF_String*)this)->m_String;
47 return ((CPDF_Name*)this)->m_Name;
48 case PDFOBJ_REFERENCE: {
49 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
50 if (pRef->m_pObjList == NULL) {
53 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
55 return CFX_ByteString();
57 return pObj->GetString();
60 return CFX_ByteString();
62 CFX_ByteStringC CPDF_Object::GetConstString() const
66 return CFX_ByteStringC((FX_LPCBYTE)((CPDF_String*)this)->m_String, ((CPDF_String*)this)->m_String.GetLength());
68 return CFX_ByteStringC((FX_LPCBYTE)((CPDF_Name*)this)->m_Name, ((CPDF_Name*)this)->m_Name.GetLength());
69 case PDFOBJ_REFERENCE: {
70 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
71 if (pRef->m_pObjList == NULL) {
74 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
76 return CFX_ByteStringC();
78 return pObj->GetConstString();
81 return CFX_ByteStringC();
83 FX_FLOAT CPDF_Object::GetNumber() const
87 return ((CPDF_Number*)this)->GetNumber();
88 case PDFOBJ_REFERENCE: {
89 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
90 if (pRef->m_pObjList == NULL) {
93 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
97 return pObj->GetNumber();
102 FX_FLOAT CPDF_Object::GetNumber16() const
106 int CPDF_Object::GetInteger() const
110 return ((CPDF_Boolean*)this)->m_bValue;
112 return ((CPDF_Number*)this)->GetInteger();
113 case PDFOBJ_REFERENCE: {
114 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
115 PARSE_CONTEXT context;
116 FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT));
117 if (pRef->m_pObjList == NULL) {
120 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum, &context);
124 return pObj->GetInteger();
129 CPDF_Dictionary* CPDF_Object::GetDict() const
132 case PDFOBJ_DICTIONARY:
133 return (CPDF_Dictionary*)this;
135 return ((CPDF_Stream*)this)->GetDict();
136 case PDFOBJ_REFERENCE: {
137 CPDF_Reference* pRef = (CPDF_Reference*)this;
138 if (pRef->m_pObjList == NULL) {
141 CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
145 return pObj->GetDict();
150 CPDF_Array* CPDF_Object::GetArray() const
152 if (m_Type == PDFOBJ_ARRAY)
153 return (CPDF_Array*)this;
157 void CPDF_Object::SetString(const CFX_ByteString& str)
159 ASSERT(this != NULL);
162 ((CPDF_Boolean*)this)->m_bValue = str == FX_BSTRC("true") ? 1 : 0;
165 ((CPDF_Number*)this)->SetString(str);
168 ((CPDF_String*)this)->m_String = str;
171 ((CPDF_Name*)this)->m_Name = str;
176 int CPDF_Object::GetDirectType() const
178 if (m_Type != PDFOBJ_REFERENCE) {
181 CPDF_Reference* pRef = (CPDF_Reference*)this;
182 return pRef->m_pObjList->GetIndirectType(pRef->m_RefObjNum);
184 FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const
186 if (this == pOther) {
189 if (pOther == NULL) {
192 if (pOther->m_Type != m_Type) {
193 if (m_Type == PDFOBJ_REFERENCE && GetDirect()) {
194 return GetDirect()->IsIdentical(pOther);
195 } else if (pOther->m_Type == PDFOBJ_REFERENCE) {
196 return IsIdentical(pOther->GetDirect());
202 return (((CPDF_Boolean*)this)->Identical((CPDF_Boolean*)pOther));
204 return (((CPDF_Number*)this)->Identical((CPDF_Number*)pOther));
206 return (((CPDF_String*)this)->Identical((CPDF_String*)pOther));
208 return (((CPDF_Name*)this)->Identical((CPDF_Name*)pOther));
210 return (((CPDF_Array*)this)->Identical((CPDF_Array*)pOther));
211 case PDFOBJ_DICTIONARY:
212 return (((CPDF_Dictionary*)this)->Identical((CPDF_Dictionary*)pOther));
216 return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther));
217 case PDFOBJ_REFERENCE:
218 return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther));
222 CPDF_Object* CPDF_Object::GetDirect() const
224 if (m_Type != PDFOBJ_REFERENCE) {
225 return (CPDF_Object*)this;
227 CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this;
228 if (pRef->m_pObjList == NULL) {
231 return pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum);
233 CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const
235 CFX_MapPtrToPtr visited;
236 return CloneInternal(bDirect, &visited);
238 CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const
242 return FX_NEW CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue);
244 return FX_NEW CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer);
246 return FX_NEW CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex());
248 return FX_NEW CPDF_Name(((CPDF_Name*)this)->m_Name);
250 CPDF_Array* pCopy = FX_NEW CPDF_Array();
251 CPDF_Array* pThis = (CPDF_Array*)this;
252 int n = pThis->GetCount();
253 for (int i = 0; i < n; i ++) {
254 CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i);
255 pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
259 case PDFOBJ_DICTIONARY: {
260 CPDF_Dictionary* pCopy = FX_NEW CPDF_Dictionary();
261 CPDF_Dictionary* pThis = (CPDF_Dictionary*)this;
262 FX_POSITION pos = pThis->m_Map.GetStartPosition();
266 pThis->m_Map.GetNextAssoc(pos, key, (void*&)value);
267 pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited));
272 return FX_NEW CPDF_Null;
274 case PDFOBJ_STREAM: {
275 CPDF_Stream* pThis = (CPDF_Stream*)this;
277 acc.LoadAllData(pThis, TRUE);
278 FX_DWORD streamSize = acc.GetSize();
280 if (pThis->GetDict())
281 pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited));
283 pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, NULL);
286 case PDFOBJ_REFERENCE: {
287 CPDF_Reference* pRef = (CPDF_Reference*)this;
288 FX_DWORD obj_num = pRef->m_RefObjNum;
289 if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) {
290 visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1);
292 if (pRef->GetDirect())
293 ret = pRef->GetDirect()->CloneInternal(TRUE, visited);
298 return FX_NEW CPDF_Reference(pRef->m_pObjList, obj_num);
304 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const
307 return FX_NEW CPDF_Reference(pDoc, m_ObjNum);
311 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const
313 if (m_Type == PDFOBJ_STRING) {
314 return PDF_DecodeText(((CPDF_String*)this)->m_String, pCharMap);
315 } else if (m_Type == PDFOBJ_STREAM) {
316 CPDF_StreamAcc stream;
317 stream.LoadAllData((CPDF_Stream*)this, FALSE);
318 CFX_WideString result = PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
320 } else if (m_Type == PDFOBJ_NAME) {
321 return PDF_DecodeText(((CPDF_Name*)this)->m_Name, pCharMap);
323 return CFX_WideString();
325 void CPDF_Object::SetUnicodeText(FX_LPCWSTR pUnicodes, int len)
327 if (m_Type == PDFOBJ_STRING) {
328 ((CPDF_String*)this)->m_String = PDF_EncodeText(pUnicodes, len);
329 } else if (m_Type == PDFOBJ_STREAM) {
330 CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
331 ((CPDF_Stream*)this)->SetData((FX_LPBYTE)(FX_LPCSTR)result, result.GetLength(), FALSE, FALSE);
334 CPDF_Number::CPDF_Number(int value)
336 m_Type = PDFOBJ_NUMBER;
340 CPDF_Number::CPDF_Number(FX_FLOAT value)
342 m_Type = PDFOBJ_NUMBER;
346 CPDF_Number::CPDF_Number(FX_BOOL bInteger, void* pData)
348 m_Type = PDFOBJ_NUMBER;
349 m_bInteger = bInteger;
350 m_Integer = *(int*)pData;
352 extern void FX_atonum(FX_BSTR, FX_BOOL&, void*);
353 CPDF_Number::CPDF_Number(FX_BSTR str)
355 m_Type = PDFOBJ_NUMBER;
356 FX_atonum(str, m_bInteger, &m_Integer);
358 void CPDF_Number::SetString(FX_BSTR str)
360 FX_atonum(str, m_bInteger, &m_Integer);
362 FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const
364 return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
366 CFX_ByteString CPDF_Number::GetString() const
368 return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) : CFX_ByteString::FormatFloat(m_Float);
370 void CPDF_Number::SetNumber(FX_FLOAT value)
375 CPDF_String::CPDF_String(const CFX_WideString& str)
377 m_Type = PDFOBJ_STRING;
378 m_String = PDF_EncodeText(str, str.GetLength());
381 CPDF_Array::~CPDF_Array()
383 int size = m_Objects.GetSize();
384 CPDF_Object** pList = (CPDF_Object**)m_Objects.GetData();
385 for (int i = 0; i < size; i ++) {
390 CFX_FloatRect CPDF_Array::GetRect()
393 if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 4) {
396 rect.left = GetNumber(0);
397 rect.bottom = GetNumber(1);
398 rect.right = GetNumber(2);
399 rect.top = GetNumber(3);
402 CFX_AffineMatrix CPDF_Array::GetMatrix()
404 CFX_AffineMatrix matrix;
405 if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 6) {
408 matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3), GetNumber(4), GetNumber(5));
411 CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const
413 if (i >= (FX_DWORD)m_Objects.GetSize()) {
416 return (CPDF_Object*)m_Objects.GetAt(i);
418 CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const
420 if (i >= (FX_DWORD)m_Objects.GetSize()) {
423 return ((CPDF_Object*)m_Objects.GetAt(i))->GetDirect();
425 CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const
427 if (i < (FX_DWORD)m_Objects.GetSize()) {
428 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
429 return p->GetString();
432 return CFX_ByteString();
434 CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const
436 if (i < (FX_DWORD)m_Objects.GetSize()) {
437 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
438 return p->GetConstString();
441 return CFX_ByteStringC();
443 int CPDF_Array::GetInteger(FX_DWORD i) const
445 if (i >= (FX_DWORD)m_Objects.GetSize()) {
448 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
449 return p->GetInteger();
451 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const
453 if (i >= (FX_DWORD)m_Objects.GetSize()) {
456 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
457 return p->GetNumber();
459 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const
461 CPDF_Object* p = GetElementValue(i);
464 } else if (p->GetType() == PDFOBJ_DICTIONARY) {
465 return (CPDF_Dictionary*)p;
466 } else if (p->GetType() == PDFOBJ_STREAM) {
467 return ((CPDF_Stream*)p)->GetDict();
471 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const
473 CPDF_Object* p = GetElementValue(i);
474 if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
477 return (CPDF_Stream*)p;
479 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const
481 CPDF_Object* p = GetElementValue(i);
482 if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
485 return (CPDF_Array*)p;
487 void CPDF_Array::RemoveAt(FX_DWORD i)
489 ASSERT(m_Type == PDFOBJ_ARRAY);
490 if (i >= (FX_DWORD)m_Objects.GetSize()) {
493 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
496 m_Objects.RemoveAt(i);
498 void CPDF_Array::SetAt(FX_DWORD i, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
500 ASSERT(m_Type == PDFOBJ_ARRAY);
501 ASSERT(i < (FX_DWORD)m_Objects.GetSize());
502 if (i >= (FX_DWORD)m_Objects.GetSize()) {
505 CPDF_Object* pOld = (CPDF_Object*)m_Objects.GetAt(i);
508 if (pObj->GetObjNum()) {
509 ASSERT(pObjs != NULL);
510 pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
512 m_Objects.SetAt(i, pObj);
514 void CPDF_Array::InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
516 ASSERT(pObj != NULL);
517 if (pObj->GetObjNum()) {
518 ASSERT(pObjs != NULL);
519 pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
521 m_Objects.InsertAt(index, pObj);
523 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
525 ASSERT(pObj != NULL);
526 if (pObj->GetObjNum()) {
527 ASSERT(pObjs != NULL);
528 pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
532 void CPDF_Array::AddName(const CFX_ByteString& str)
534 ASSERT(m_Type == PDFOBJ_ARRAY);
535 Add(FX_NEW CPDF_Name(str));
537 void CPDF_Array::AddString(const CFX_ByteString& str)
539 ASSERT(m_Type == PDFOBJ_ARRAY);
540 Add(FX_NEW CPDF_String(str));
542 void CPDF_Array::AddInteger(int i)
544 ASSERT(m_Type == PDFOBJ_ARRAY);
545 Add(FX_NEW CPDF_Number(i));
547 void CPDF_Array::AddNumber(FX_FLOAT f)
549 ASSERT(m_Type == PDFOBJ_ARRAY);
550 CPDF_Number* pNumber = FX_NEW CPDF_Number;
551 pNumber->SetNumber(f);
554 void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
556 ASSERT(m_Type == PDFOBJ_ARRAY);
557 Add(FX_NEW CPDF_Reference(pDoc, objnum));
559 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const
561 if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
564 for (int i = 0; i < m_Objects.GetSize(); i ++)
565 if (!((CPDF_Object*)m_Objects[i])->IsIdentical((CPDF_Object*)pOther->m_Objects[i])) {
570 CPDF_Dictionary::~CPDF_Dictionary()
572 FX_POSITION pos = m_Map.GetStartPosition();
574 FX_LPVOID value = m_Map.GetNextValue(pos);
576 ((CPDF_Object*)value)->Release();
579 FX_POSITION CPDF_Dictionary::GetStartPos() const
581 return m_Map.GetStartPosition();
583 CPDF_Object* CPDF_Dictionary::GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const
589 m_Map.GetNextAssoc(pos, key, (FX_LPVOID&)p);
592 CPDF_Object* CPDF_Dictionary::GetElement(FX_BSTR key) const
594 CPDF_Object* p = NULL;
595 m_Map.Lookup(key, (void*&)p);
598 CPDF_Object* CPDF_Dictionary::GetElementValue(FX_BSTR key) const
600 CPDF_Object* p = NULL;
601 m_Map.Lookup(key, (void*&)p);
602 return p ? p->GetDirect() : NULL;
604 CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key) const
606 CPDF_Object* p = NULL;
607 m_Map.Lookup(key, (void*&)p);
609 return p->GetString();
611 return CFX_ByteString();
613 CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key) const
615 CPDF_Object* p = NULL;
616 m_Map.Lookup(key, (void*&)p);
618 return p->GetConstString();
620 return CFX_ByteStringC();
622 CFX_WideString CPDF_Dictionary::GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap) const
624 CPDF_Object* p = NULL;
625 m_Map.Lookup(key, (void*&)p);
627 if(p->GetType() == PDFOBJ_REFERENCE) {
628 p = ((CPDF_Reference*)p)->GetDirect();
630 return p->GetUnicodeText(pCharMap);
633 return p->GetUnicodeText(pCharMap);
636 return CFX_WideString();
638 CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key, FX_BSTR def) const
640 CPDF_Object* p = NULL;
641 m_Map.Lookup(key, (void*&)p);
643 return p->GetString();
645 return CFX_ByteString(def);
647 CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key, FX_BSTR def) const
649 CPDF_Object* p = NULL;
650 m_Map.Lookup(key, (void*&)p);
652 return p->GetConstString();
654 return CFX_ByteStringC(def);
656 int CPDF_Dictionary::GetInteger(FX_BSTR key) const
658 CPDF_Object* p = NULL;
659 m_Map.Lookup(key, (void*&)p);
661 return p->GetInteger();
665 int CPDF_Dictionary::GetInteger(FX_BSTR key, int def) const
667 CPDF_Object* p = NULL;
668 m_Map.Lookup(key, (void*&)p);
670 return p->GetInteger();
674 FX_FLOAT CPDF_Dictionary::GetNumber(FX_BSTR key) const
676 CPDF_Object* p = NULL;
677 m_Map.Lookup(key, (void*&)p);
679 return p->GetNumber();
683 FX_BOOL CPDF_Dictionary::GetBoolean(FX_BSTR key, FX_BOOL bDefault) const
685 CPDF_Object* p = NULL;
686 m_Map.Lookup(key, (void*&)p);
687 if (p && p->GetType() == PDFOBJ_BOOLEAN) {
688 return p->GetInteger();
692 CPDF_Dictionary* CPDF_Dictionary::GetDict(FX_BSTR key) const
694 CPDF_Object* p = GetElementValue(key);
697 } else if (p->GetType() == PDFOBJ_DICTIONARY) {
698 return (CPDF_Dictionary*)p;
699 } else if (p->GetType() == PDFOBJ_STREAM) {
700 return ((CPDF_Stream*)p)->GetDict();
704 CPDF_Array* CPDF_Dictionary::GetArray(FX_BSTR key) const
706 CPDF_Object* p = GetElementValue(key);
707 if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
710 return (CPDF_Array*)p;
712 CPDF_Stream* CPDF_Dictionary::GetStream(FX_BSTR key) const
714 CPDF_Object* p = GetElementValue(key);
715 if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
718 return (CPDF_Stream*)p;
720 CFX_FloatRect CPDF_Dictionary::GetRect(FX_BSTR key) const
723 CPDF_Array* pArray = GetArray(key);
725 rect = pArray->GetRect();
729 CFX_AffineMatrix CPDF_Dictionary::GetMatrix(FX_BSTR key) const
731 CFX_AffineMatrix matrix;
732 CPDF_Array* pArray = GetArray(key);
734 matrix = pArray->GetMatrix();
738 FX_BOOL CPDF_Dictionary::KeyExist(FX_BSTR key) const
741 return m_Map.Lookup(key, value);
743 void CPDF_Dictionary::SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs)
745 ASSERT(m_Type == PDFOBJ_DICTIONARY);
746 CPDF_Object* p = NULL;
747 m_Map.Lookup(key, (void*&)p);
754 if (pObj->GetObjNum()) {
755 ASSERT(pObjs != NULL);
756 pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum());
758 m_Map.SetAt(key, pObj);
760 m_Map.RemoveKey(key);
763 void CPDF_Dictionary::AddValue(FX_BSTR key, CPDF_Object* pObj)
765 ASSERT(m_Type == PDFOBJ_DICTIONARY);
766 m_Map.AddValue(key, pObj);
768 void CPDF_Dictionary::RemoveAt(FX_BSTR key)
770 ASSERT(m_Type == PDFOBJ_DICTIONARY);
771 CPDF_Object* p = NULL;
772 m_Map.Lookup(key, (void*&)p);
777 m_Map.RemoveKey(key);
779 void CPDF_Dictionary::ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey)
781 ASSERT(m_Type == PDFOBJ_DICTIONARY);
782 CPDF_Object* p = NULL;
783 m_Map.Lookup(oldkey, (void*&)p);
787 m_Map.RemoveKey(oldkey);
788 m_Map.SetAt(newkey, p);
790 FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const
792 if (pOther == NULL) {
795 if (m_Map.GetCount() != pOther->m_Map.GetCount()) {
798 FX_POSITION pos = m_Map.GetStartPosition();
802 m_Map.GetNextAssoc(pos, key, value);
805 if (!((CPDF_Object*)value)->IsIdentical(pOther->GetElement(key))) {
811 void CPDF_Dictionary::SetAtInteger(FX_BSTR key, int i)
813 SetAt(key, FX_NEW CPDF_Number(i));
815 void CPDF_Dictionary::SetAtName(FX_BSTR key, const CFX_ByteString& name)
817 SetAt(key, FX_NEW CPDF_Name(name));
819 void CPDF_Dictionary::SetAtString(FX_BSTR key, const CFX_ByteString& str)
821 SetAt(key, FX_NEW CPDF_String(str));
823 void CPDF_Dictionary::SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
825 SetAt(key, FX_NEW CPDF_Reference(pDoc, objnum));
827 void CPDF_Dictionary::AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
829 AddValue(key, FX_NEW CPDF_Reference(pDoc, objnum));
831 void CPDF_Dictionary::SetAtNumber(FX_BSTR key, FX_FLOAT f)
833 CPDF_Number* pNumber = FX_NEW CPDF_Number;
834 pNumber->SetNumber(f);
837 void CPDF_Dictionary::SetAtBoolean(FX_BSTR key, FX_BOOL bValue)
839 SetAt(key, FX_NEW CPDF_Boolean(bValue));
841 void CPDF_Dictionary::SetAtRect(FX_BSTR key, const CFX_FloatRect& rect)
843 CPDF_Array* pArray = FX_NEW CPDF_Array;
844 pArray->AddNumber(rect.left);
845 pArray->AddNumber(rect.bottom);
846 pArray->AddNumber(rect.right);
847 pArray->AddNumber(rect.top);
850 void CPDF_Dictionary::SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix)
852 CPDF_Array* pArray = FX_NEW CPDF_Array;
853 pArray->AddNumber16(matrix.a);
854 pArray->AddNumber16(matrix.b);
855 pArray->AddNumber16(matrix.c);
856 pArray->AddNumber16(matrix.d);
857 pArray->AddNumber(matrix.e);
858 pArray->AddNumber(matrix.f);
861 CPDF_Stream::CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict)
863 m_Type = PDFOBJ_STREAM;
866 m_GenNum = (FX_DWORD) - 1;
868 m_pCryptoHandler = NULL;
870 CPDF_Stream::~CPDF_Stream()
872 if (m_GenNum == (FX_DWORD) - 1 && m_pDataBuf != NULL) {
879 void CPDF_Stream::InitStream(CPDF_Dictionary* pDict)
887 if (m_GenNum == (FX_DWORD) - 1) {
894 m_pCryptoHandler = NULL;
897 void CPDF_Stream::InitStream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict)
900 m_GenNum = (FX_DWORD) - 1;
901 m_pDataBuf = FX_Alloc(FX_BYTE, size);
903 FXSYS_memcpy32(m_pDataBuf, pData, size);
907 m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
910 void CPDF_Stream::SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf)
912 if (m_GenNum == (FX_DWORD) - 1) {
917 m_GenNum = (FX_DWORD) - 1;
918 m_pCryptoHandler = NULL;
921 m_pDataBuf = (FX_LPBYTE)pData;
923 m_pDataBuf = FX_Alloc(FX_BYTE, size);
925 FXSYS_memcpy32(m_pDataBuf, pData, size);
929 if (m_pDict == NULL) {
930 m_pDict = FX_NEW CPDF_Dictionary;
932 m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
934 m_pDict->RemoveAt(FX_BSTRC("Filter"));
935 m_pDict->RemoveAt(FX_BSTRC("DecodeParms"));
938 FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset, FX_LPBYTE buf, FX_DWORD size) const
940 if ((m_GenNum != (FX_DWORD) - 1) && m_pFile) {
941 return m_pFile->ReadBlock(buf, m_FileOffset + offset, size);
944 FXSYS_memcpy32(buf, m_pDataBuf + offset, size);
948 void CPDF_Stream::InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict)
952 m_dwSize = (FX_DWORD)pFile->GetSize();
954 m_pDict->SetAtInteger(FX_BSTRC("Length"), m_dwSize);
957 FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const
960 return pOther->m_pDict ? FALSE : TRUE;
962 if (!m_pDict->Identical(pOther->m_pDict)) {
965 if (m_dwSize != pOther->m_dwSize) {
968 if (m_GenNum != (FX_DWORD) - 1 && pOther->m_GenNum != (FX_DWORD) - 1) {
969 if (m_pFile == pOther->m_pFile && m_pFile == NULL) {
972 if (!m_pFile || !pOther->m_pFile) {
975 FX_BYTE srcBuf[1024];
976 FX_BYTE destBuf[1024];
977 FX_DWORD size = m_dwSize;
978 FX_DWORD srcOffset = m_FileOffset;
979 FX_DWORD destOffset = pOther->m_FileOffset;
980 if (m_pFile == pOther->m_pFile && srcOffset == destOffset) {
984 FX_DWORD actualSize = size > 1024 ? 1024 : size;
985 m_pFile->ReadBlock(srcBuf, srcOffset, actualSize);
986 pOther->m_pFile->ReadBlock(destBuf, destOffset, actualSize);
987 if (FXSYS_memcmp32(srcBuf, destBuf, actualSize) != 0) {
991 srcOffset += actualSize;
992 destOffset += actualSize;
996 if (m_GenNum != (FX_DWORD) - 1 || pOther->m_GenNum != (FX_DWORD) - 1) {
997 IFX_FileRead* pFile = NULL;
998 FX_LPBYTE pBuf = NULL;
1000 if (m_GenNum != (FX_DWORD) - 1) {
1002 pBuf = pOther->m_pDataBuf;
1003 offset = m_FileOffset;
1005 if (pOther->m_GenNum != (FX_DWORD) - 1) {
1006 pFile = pOther->m_pFile;
1008 offset = pOther->m_FileOffset;
1013 FX_BYTE srcBuf[1024];
1014 FX_DWORD size = m_dwSize;
1016 FX_DWORD actualSize = size > 1024 ? 1024 : size;
1017 m_pFile->ReadBlock(srcBuf, offset, actualSize);
1018 if (FXSYS_memcmp32(srcBuf, pBuf, actualSize) != 0) {
1023 offset += actualSize;
1027 return FXSYS_memcmp32(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
1029 CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const
1031 CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect);
1032 IFX_FileStream *pFS = NULL;
1034 pFS = lpfCallback((CPDF_Stream*)this, pUserData);
1038 acc.LoadAllData(this, TRUE);
1039 FX_DWORD streamSize = acc.GetSize();
1040 CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, pCloneDict);
1043 CPDF_Stream* pObj = FX_NEW CPDF_Stream(NULL, 0, NULL);
1044 CPDF_StreamFilter *pSF = GetStreamFilter(TRUE);
1046 FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096);
1049 dwRead = pSF->ReadBlock(pBuf, 4096);
1051 pFS->WriteBlock(pBuf, dwRead);
1053 } while (dwRead == 4096);
1058 pObj->InitStream((IFX_FileRead*)pFS, pCloneDict);
1061 extern FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict,
1062 FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding,
1063 CPDF_Dictionary*& pImageParms, FX_DWORD estimated_size, FX_BOOL bImageAcc);
1064 CPDF_StreamAcc::CPDF_StreamAcc()
1069 m_pImageParam = NULL;
1073 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess, FX_DWORD estimated_size,
1076 if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1079 m_pStream = pStream;
1080 if (pStream->IsMemoryBased() &&
1081 (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) {
1082 m_dwSize = pStream->m_dwSize;
1083 m_pData = (FX_LPBYTE)pStream->m_pDataBuf;
1087 FX_DWORD dwSrcSize = pStream->m_dwSize;
1088 if (dwSrcSize == 0) {
1091 if (!pStream->IsMemoryBased()) {
1092 pSrcData = m_pSrcData = FX_Alloc(FX_BYTE, dwSrcSize);
1093 if (!pSrcData || !pStream->ReadRawData(0, pSrcData, dwSrcSize)) {
1097 pSrcData = pStream->m_pDataBuf;
1099 FX_LPBYTE pDecryptedData;
1100 FX_DWORD dwDecryptedSize;
1101 if (pStream->m_pCryptoHandler) {
1102 CFX_BinaryBuf dest_buf;
1103 dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize));
1104 FX_LPVOID context = pStream->m_pCryptoHandler->DecryptStart(pStream->GetObjNum(), pStream->m_GenNum);
1105 pStream->m_pCryptoHandler->DecryptStream(context, pSrcData, dwSrcSize, dest_buf);
1106 pStream->m_pCryptoHandler->DecryptFinish(context, dest_buf);
1107 pDecryptedData = dest_buf.GetBuffer();
1108 dwDecryptedSize = dest_buf.GetSize();
1109 dest_buf.DetachBuffer();
1111 pDecryptedData = pSrcData;
1112 dwDecryptedSize = dwSrcSize;
1114 if (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess) {
1115 m_pData = pDecryptedData;
1116 m_dwSize = dwDecryptedSize;
1118 FX_BOOL bRet = PDF_DataDecode(pDecryptedData, dwDecryptedSize, m_pStream->GetDict(),
1119 m_pData, m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc);
1121 m_pData = pDecryptedData;
1122 m_dwSize = dwDecryptedSize;
1125 if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
1128 if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
1129 FX_Free(pDecryptedData);
1132 m_bNewBuf = m_pData != pStream->m_pDataBuf;
1134 CPDF_StreamAcc::~CPDF_StreamAcc()
1136 if (m_bNewBuf && m_pData) {
1140 FX_Free(m_pSrcData);
1143 FX_LPCBYTE CPDF_StreamAcc::GetData() const
1151 return m_pStream->m_pDataBuf;
1153 FX_DWORD CPDF_StreamAcc::GetSize() const
1161 return m_pStream->m_dwSize;
1163 FX_LPBYTE CPDF_StreamAcc::DetachData()
1166 FX_LPBYTE p = m_pData;
1171 FX_LPBYTE p = FX_Alloc(FX_BYTE, m_dwSize);
1175 FXSYS_memcpy32(p, m_pData, m_dwSize);
1178 void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum)
1181 m_RefObjNum = objnum;
1183 CPDF_IndirectObjects::CPDF_IndirectObjects(IPDF_DocParser* pParser)
1185 m_pParser = pParser;
1186 m_IndirectObjs.InitHashTable(1013);
1188 m_LastObjNum = m_pParser->GetLastObjNum();
1193 CPDF_IndirectObjects::~CPDF_IndirectObjects()
1195 FX_POSITION pos = m_IndirectObjs.GetStartPosition();
1197 FX_LPVOID key, value;
1198 m_IndirectObjs.GetNextAssoc(pos, key, value);
1199 ((CPDF_Object*)value)->Destroy();
1202 CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext)
1209 if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1210 if (((CPDF_Object*)value)->GetObjNum() == -1) {
1213 return (CPDF_Object*)value;
1216 CPDF_Object* pObj = NULL;
1218 pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
1223 pObj->m_ObjNum = objnum;
1224 if (m_LastObjNum < objnum) {
1225 m_LastObjNum = objnum;
1227 if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1229 ((CPDF_Object *)value)->Destroy();
1232 m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj);
1235 int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum)
1238 if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1239 return ((CPDF_Object*)value)->GetType();
1242 PARSE_CONTEXT context;
1243 FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT));
1244 context.m_Flags = PDFPARSE_TYPEONLY;
1245 return (int)(FX_UINTPTR)m_pParser->ParseIndirectObject(this, objnum, &context);
1249 FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj)
1251 if (pObj->m_ObjNum) {
1252 return pObj->m_ObjNum;
1255 m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)m_LastObjNum, pObj);
1256 pObj->m_ObjNum = m_LastObjNum;
1257 return m_LastObjNum;
1259 void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum)
1262 if (!m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1265 if (((CPDF_Object*)value)->GetObjNum() == -1) {
1268 ((CPDF_Object*)value)->Destroy();
1269 m_IndirectObjs.RemoveKey((FX_LPVOID)(FX_UINTPTR)objnum);
1271 void CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj)
1273 if (objnum == 0 || pObj == NULL) {
1276 FX_LPVOID value = NULL;
1277 if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) {
1280 if (pObj->GetGenNum() <= ((CPDF_Object*)value)->GetGenNum())
1283 ((CPDF_Object*)value)->Destroy();
1286 pObj->m_ObjNum = objnum;
1287 m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj);
1288 if (m_LastObjNum < objnum) {
1289 m_LastObjNum = objnum;
1292 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const
1294 return m_LastObjNum;