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
CPDF_Document(CPDF_Parser * pParser)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 }
GetValidatePageData()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 }
GetValidateRenderData()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 }
LoadDoc()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 }
LoadAsynDoc(CPDF_Dictionary * pLinearized)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 }
LoadPages()90 void CPDF_Document::LoadPages()
91 {
92 m_PageList.SetSize(_GetPageCount());
93 }
94 extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*);
~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
_FindPDFPage(CPDF_Dictionary * pPages,int iPage,int nPagesToGo,int level)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 }
GetPage(int iPage)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 }
_FindPageIndex(CPDF_Dictionary * pNode,FX_DWORD & skip_count,FX_DWORD objnum,int & index,int level)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 }
GetPageIndex(FX_DWORD objnum)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 }
GetPageCount() const253 int CPDF_Document::GetPageCount() const
254 {
255 return m_PageList.GetSize();
256 }
_CountPages(CPDF_Dictionary * pPages,int level)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 }
_GetPageCount() const285 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 }
IsContentUsedElsewhere(FX_DWORD objnum,CPDF_Dictionary * pThisPageDict)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 }
GetUserPermissions(FX_BOOL bCheckRevision) const328 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 }
IsOwner() const335 FX_BOOL CPDF_Document::IsOwner() const
336 {
337 if (m_pParser == NULL) {
338 return TRUE;
339 }
340 return m_pParser->IsOwner();
341 }
IsFormStream(FX_DWORD objnum,FX_BOOL & bForm) const342 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 }
ClearPageData()358 void CPDF_Document::ClearPageData()
359 {
360 if (m_pDocPage) {
361 CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this);
362 }
363 }
ClearRenderData()364 void CPDF_Document::ClearRenderData()
365 {
366 if (m_pDocRender) {
367 CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender);
368 }
369 }
370