• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);
CPDF_Document(IPDF_DocParser * pParser)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 }
GetValidatePageData()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 }
GetValidateRenderData()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 }
LoadDoc()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 }
LoadAsynDoc(CPDF_Dictionary * pLinearized)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 }
LoadPages()89 void CPDF_Document::LoadPages()
90 {
91     m_PageList.SetSize(_GetPageCount());
92 }
93 extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*);
~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
_FindPDFPage(CPDF_Dictionary * pPages,int iPage,int nPagesToGo,int level)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 }
GetPage(int iPage)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 }
_FindPageIndex(CPDF_Dictionary * pNode,FX_DWORD & skip_count,FX_DWORD objnum,int & index,int level)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 }
GetPageIndex(FX_DWORD objnum)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 }
GetPageCount() const252 int CPDF_Document::GetPageCount() const
253 {
254     return m_PageList.GetSize();
255 }
_CountPages(CPDF_Dictionary * pPages,int level)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 }
_GetPageCount() const284 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 }
_EnumPages(CPDF_Dictionary * pPages,IPDF_EnumPageHandler * pHandler)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 }
EnumPages(IPDF_EnumPageHandler * pHandler)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 }
IsContentUsedElsewhere(FX_DWORD objnum,CPDF_Dictionary * pThisPageDict)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 }
GetUserPermissions(FX_BOOL bCheckRevision) const357 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 }
IsOwner() const364 FX_BOOL CPDF_Document::IsOwner() const
365 {
366     if (m_pParser == NULL) {
367         return TRUE;
368     }
369     return m_pParser->IsOwner();
370 }
IsFormStream(FX_DWORD objnum,FX_BOOL & bForm) const371 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 }
ClearPageData()387 void CPDF_Document::ClearPageData()
388 {
389     if (m_pDocPage) {
390         CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this);
391     }
392 }
ClearRenderData()393 void CPDF_Document::ClearRenderData()
394 {
395     if (m_pDocRender) {
396         CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender);
397     }
398 }
399