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/fpdfapi/fpdf_module.h"
      9 
     10 CPDF_Document::CPDF_Document(CPDF_Parser* pParser) : CPDF_IndirectObjects(pParser)
     11 {
     12     ASSERT(pParser != NULL);
     13     m_pRootDict = NULL;
     14     m_pInfoDict = NULL;
     15     m_bLinearized = FALSE;
     16     m_dwFirstPageNo = 0;
     17     m_dwFirstPageObjNum = 0;
     18     m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);
     19     m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);
     20 }
     21 CPDF_DocPageData* CPDF_Document::GetValidatePageData()
     22 {
     23     if (m_pDocPage) {
     24         return m_pDocPage;
     25     }
     26     m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);
     27     return m_pDocPage;
     28 }
     29 CPDF_DocRenderData* CPDF_Document::GetValidateRenderData()
     30 {
     31     if (m_pDocRender) {
     32         return m_pDocRender;
     33     }
     34     m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);
     35     return m_pDocRender;
     36 }
     37 void CPDF_Document::LoadDoc()
     38 {
     39     m_LastObjNum = m_pParser->GetLastObjNum();
     40     CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum());
     41     if (pRootObj == NULL) {
     42         return;
     43     }
     44     m_pRootDict = pRootObj->GetDict();
     45     if (m_pRootDict == NULL) {
     46         return;
     47     }
     48     CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum());
     49     if (pInfoObj) {
     50         m_pInfoDict = pInfoObj->GetDict();
     51     }
     52     CPDF_Array* pIDArray = m_pParser->GetIDArray();
     53     if (pIDArray) {
     54         m_ID1 = pIDArray->GetString(0);
     55         m_ID2 = pIDArray->GetString(1);
     56     }
     57     m_PageList.SetSize(_GetPageCount());
     58 }
     59 void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized)
     60 {
     61     m_bLinearized = TRUE;
     62     m_LastObjNum = m_pParser->GetLastObjNum();
     63     CPDF_Object* indirectObj = GetIndirectObject(m_pParser->GetRootObjNum());
     64     m_pRootDict = indirectObj ? indirectObj->GetDict() : NULL;
     65     if (m_pRootDict == NULL) {
     66         return;
     67     }
     68     indirectObj = GetIndirectObject(m_pParser->GetInfoObjNum());
     69     m_pInfoDict = indirectObj ? indirectObj->GetDict() : NULL;
     70     CPDF_Array* pIDArray = m_pParser->GetIDArray();
     71     if (pIDArray) {
     72         m_ID1 = pIDArray->GetString(0);
     73         m_ID2 = pIDArray->GetString(1);
     74     }
     75     FX_DWORD dwPageCount = 0;
     76     CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N"));
     77     if (pCount && pCount->GetType() == PDFOBJ_NUMBER) {
     78         dwPageCount = pCount->GetInteger();
     79     }
     80     m_PageList.SetSize(dwPageCount);
     81     CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P"));
     82     if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
     83         m_dwFirstPageNo = pNo->GetInteger();
     84     }
     85     CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O"));
     86     if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) {
     87         m_dwFirstPageObjNum = pObjNum->GetInteger();
     88     }
     89 }
     90 void CPDF_Document::LoadPages()
     91 {
     92     m_PageList.SetSize(_GetPageCount());
     93 }
     94 extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*);
     95 CPDF_Document::~CPDF_Document()
     96 {
     97     if (m_pDocPage) {
     98         CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this);
     99         CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this);
    100     }
    101     if (m_pDocRender) {
    102         CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender);
    103     }
    104 }
    105 #define		FX_MAX_PAGE_LEVEL			1024
    106 CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level)
    107 {
    108     CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));
    109     if (pKidList == NULL) {
    110         if (nPagesToGo == 0) {
    111             return pPages;
    112         }
    113         return NULL;
    114     }
    115     if (level >= FX_MAX_PAGE_LEVEL) {
    116         return NULL;
    117     }
    118     int nKids = pKidList->GetCount();
    119     for (int i = 0; i < nKids; i ++) {
    120         CPDF_Dictionary* pKid = pKidList->GetDict(i);
    121         if (pKid == NULL) {
    122             nPagesToGo --;
    123             continue;
    124         }
    125         if (pKid == pPages) {
    126             continue;
    127         }
    128         if (!pKid->KeyExist(FX_BSTRC("Kids"))) {
    129             if (nPagesToGo == 0) {
    130                 return pKid;
    131             }
    132             m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum());
    133             nPagesToGo --;
    134         } else {
    135             int nPages = pKid->GetInteger(FX_BSTRC("Count"));
    136             if (nPagesToGo < nPages) {
    137                 return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1);
    138             }
    139             nPagesToGo -= nPages;
    140         }
    141     }
    142     return NULL;
    143 }
    144 CPDF_Dictionary* CPDF_Document::GetPage(int iPage)
    145 {
    146     if (iPage < 0 || iPage >= m_PageList.GetSize()) {
    147         return NULL;
    148     }
    149     if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) {
    150         CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum);
    151         if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) {
    152             return (CPDF_Dictionary*)pObj;
    153         }
    154     }
    155     int objnum = m_PageList.GetAt(iPage);
    156     if (objnum) {
    157         CPDF_Object* pObj = GetIndirectObject(objnum);
    158         ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY);
    159         return (CPDF_Dictionary*)pObj;
    160     }
    161     CPDF_Dictionary* pRoot = GetRoot();
    162     if (pRoot == NULL) {
    163         return NULL;
    164     }
    165     CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
    166     if (pPages == NULL) {
    167         return NULL;
    168     }
    169     CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0);
    170     if (pPage == NULL) {
    171         return NULL;
    172     }
    173     m_PageList.SetAt(iPage, pPage->GetObjNum());
    174     return pPage;
    175 }
    176 int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level)
    177 {
    178     if (pNode->KeyExist(FX_BSTRC("Kids"))) {
    179         CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids"));
    180         if (pKidList == NULL) {
    181             return -1;
    182         }
    183         if (level >= FX_MAX_PAGE_LEVEL) {
    184             return -1;
    185         }
    186         FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count"));
    187         if (count <= skip_count) {
    188             skip_count -= count;
    189             index += count;
    190             return -1;
    191         }
    192         if (count && count == pKidList->GetCount()) {
    193             for (FX_DWORD i = 0; i < count; i ++) {
    194                 CPDF_Object* pKid = pKidList->GetElement(i);
    195                 if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) {
    196                     if (((CPDF_Reference*) pKid)->GetRefObjNum() == objnum) {
    197                         m_PageList.SetAt(index + i, objnum);
    198                         return index + i;
    199                     }
    200                 }
    201             }
    202         }
    203         for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {
    204             CPDF_Dictionary* pKid = pKidList->GetDict(i);
    205             if (pKid == NULL) {
    206                 continue;
    207             }
    208             if (pKid == pNode) {
    209                 continue;
    210             }
    211             int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1);
    212             if (found_index >= 0) {
    213                 return found_index;
    214             }
    215         }
    216     } else {
    217         if (objnum == pNode->GetObjNum()) {
    218             return index;
    219         }
    220         if (skip_count) {
    221             skip_count--;
    222         }
    223         index ++;
    224     }
    225     return -1;
    226 }
    227 int CPDF_Document::GetPageIndex(FX_DWORD objnum)
    228 {
    229     FX_DWORD nPages = m_PageList.GetSize();
    230     FX_DWORD skip_count = 0;
    231     FX_BOOL bSkipped = FALSE;
    232     for (FX_DWORD i = 0; i < nPages; i ++) {
    233         FX_DWORD objnum1 = m_PageList.GetAt(i);
    234         if (objnum1 == objnum) {
    235             return i;
    236         }
    237         if (!bSkipped && objnum1 == 0) {
    238             skip_count = i;
    239             bSkipped = TRUE;
    240         }
    241     }
    242     CPDF_Dictionary* pRoot = GetRoot();
    243     if (pRoot == NULL) {
    244         return -1;
    245     }
    246     CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
    247     if (pPages == NULL) {
    248         return -1;
    249     }
    250     int index = 0;
    251     return _FindPageIndex(pPages, skip_count, objnum, index);
    252 }
    253 int CPDF_Document::GetPageCount() const
    254 {
    255     return m_PageList.GetSize();
    256 }
    257 static int _CountPages(CPDF_Dictionary* pPages, int level)
    258 {
    259     if (level > 128) {
    260         return 0;
    261     }
    262     int count = pPages->GetInteger(FX_BSTRC("Count"));
    263     if (count > 0 && count < FPDF_PAGE_MAX_NUM) {
    264         return count;
    265     }
    266     CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));
    267     if (pKidList == NULL) {
    268         return 0;
    269     }
    270     count = 0;
    271     for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {
    272         CPDF_Dictionary* pKid = pKidList->GetDict(i);
    273         if (pKid == NULL) {
    274             continue;
    275         }
    276         if (!pKid->KeyExist(FX_BSTRC("Kids"))) {
    277             count ++;
    278         } else {
    279             count += _CountPages(pKid, level + 1);
    280         }
    281     }
    282     pPages->SetAtInteger(FX_BSTRC("Count"), count);
    283     return count;
    284 }
    285 int CPDF_Document::_GetPageCount() const
    286 {
    287     CPDF_Dictionary* pRoot = GetRoot();
    288     if (pRoot == NULL) {
    289         return 0;
    290     }
    291     CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
    292     if (pPages == NULL) {
    293         return 0;
    294     }
    295     if (!pPages->KeyExist(FX_BSTRC("Kids"))) {
    296         return 1;
    297     }
    298     return _CountPages(pPages, 0);
    299 }
    300 FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict)
    301 {
    302     for (int i = 0; i < m_PageList.GetSize(); i ++) {
    303         CPDF_Dictionary* pPageDict = GetPage(i);
    304         if (pPageDict == pThisPageDict) {
    305             continue;
    306         }
    307         CPDF_Object* pContents = pPageDict ? pPageDict->GetElement(FX_BSTRC("Contents")) : NULL;
    308         if (pContents == NULL) {
    309             continue;
    310         }
    311         if (pContents->GetDirectType() == PDFOBJ_ARRAY) {
    312             CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect();
    313             for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) {
    314                 CPDF_Object* pRef = pArray->GetElement(j);
    315                 if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
    316                     continue;
    317                 }
    318                 if (((CPDF_Reference*) pRef)->GetRefObjNum() == objnum) {
    319                     return TRUE;
    320                 }
    321             }
    322         } else if (pContents->GetObjNum() == objnum) {
    323             return TRUE;
    324         }
    325     }
    326     return FALSE;
    327 }
    328 FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const
    329 {
    330     if (m_pParser == NULL) {
    331         return (FX_DWORD) - 1;
    332     }
    333     return m_pParser->GetPermissions(bCheckRevision);
    334 }
    335 FX_BOOL CPDF_Document::IsOwner() const
    336 {
    337     if (m_pParser == NULL) {
    338         return TRUE;
    339     }
    340     return m_pParser->IsOwner();
    341 }
    342 FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const
    343 {
    344     {
    345         CPDF_Object* pObj;
    346         if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) {
    347             bForm = pObj->GetType() == PDFOBJ_STREAM &&
    348                     ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form");
    349             return TRUE;
    350         }
    351     }
    352     if (m_pParser == NULL) {
    353         bForm = FALSE;
    354         return TRUE;
    355     }
    356     return m_pParser->IsFormStream(objnum, bForm);
    357 }
    358 void CPDF_Document::ClearPageData()
    359 {
    360     if (m_pDocPage) {
    361         CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this);
    362     }
    363 }
    364 void CPDF_Document::ClearRenderData()
    365 {
    366     if (m_pDocRender) {
    367         CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender);
    368     }
    369 }
    370