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