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