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