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