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