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