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 "fpdfsdk/include/fsdk_define.h"
8 #include "fpdfsdk/include/fsdk_mgr.h"
9 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h"
10 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
11 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h"
12 
CPDFXFA_Page(CPDFXFA_Document * pDoc,int page_index)13 CPDFXFA_Page::CPDFXFA_Page(CPDFXFA_Document* pDoc, int page_index)
14     : m_pPDFPage(NULL),
15       m_pXFAPageView(NULL),
16       m_iPageIndex(page_index),
17       m_pDocument(pDoc),
18       m_iRef(1) {}
19 
~CPDFXFA_Page()20 CPDFXFA_Page::~CPDFXFA_Page() {
21   if (m_pPDFPage)
22     delete m_pPDFPage;
23   m_pPDFPage = NULL;
24   m_pXFAPageView = NULL;
25 }
26 
Release()27 void CPDFXFA_Page::Release() {
28   m_iRef--;
29   if (m_iRef > 0)
30     return;
31 
32   if (m_pDocument)
33     m_pDocument->RemovePage(this);
34 
35   delete this;
36 }
37 
LoadPDFPage()38 FX_BOOL CPDFXFA_Page::LoadPDFPage() {
39   if (!m_pDocument)
40     return FALSE;
41   CPDF_Document* pPDFDoc = m_pDocument->GetPDFDoc();
42   if (pPDFDoc) {
43     CPDF_Dictionary* pDict = pPDFDoc->GetPage(m_iPageIndex);
44     if (pDict == NULL)
45       return FALSE;
46     if (m_pPDFPage) {
47       if (m_pPDFPage->m_pFormDict == pDict)
48         return TRUE;
49 
50       delete m_pPDFPage;
51       m_pPDFPage = NULL;
52     }
53 
54     m_pPDFPage = new CPDF_Page;
55     m_pPDFPage->Load(pPDFDoc, pDict);
56     m_pPDFPage->ParseContent();
57     return TRUE;
58   }
59 
60   return FALSE;
61 }
62 
LoadXFAPageView()63 FX_BOOL CPDFXFA_Page::LoadXFAPageView() {
64   if (!m_pDocument)
65     return FALSE;
66   IXFA_Doc* pXFADoc = m_pDocument->GetXFADoc();
67   if (!pXFADoc)
68     return FALSE;
69 
70   IXFA_DocView* pXFADocView = m_pDocument->GetXFADocView();
71   if (!pXFADocView)
72     return FALSE;
73 
74   IXFA_PageView* pPageView = pXFADocView->GetPageView(m_iPageIndex);
75   if (!pPageView)
76     return FALSE;
77 
78   if (m_pXFAPageView == pPageView)
79     return TRUE;
80 
81   m_pXFAPageView = pPageView;
82   (void)m_pXFAPageView->LoadPageView(nullptr);
83   return TRUE;
84 }
85 
LoadPage()86 FX_BOOL CPDFXFA_Page::LoadPage() {
87   if (!m_pDocument || m_iPageIndex < 0)
88     return FALSE;
89 
90   int iDocType = m_pDocument->GetDocType();
91   switch (iDocType) {
92     case DOCTYPE_PDF:
93     case DOCTYPE_STATIC_XFA: {
94       return LoadPDFPage();
95     }
96     case DOCTYPE_DYNAMIC_XFA: {
97       return LoadXFAPageView();
98     }
99     default:
100       return FALSE;
101   }
102 
103   return FALSE;
104 }
105 
LoadPDFPage(CPDF_Dictionary * pageDict)106 FX_BOOL CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) {
107   if (!m_pDocument || m_iPageIndex < 0 || !pageDict)
108     return FALSE;
109 
110   if (m_pPDFPage)
111     delete m_pPDFPage;
112 
113   m_pPDFPage = new CPDF_Page();
114   m_pPDFPage->Load(m_pDocument->GetPDFDoc(), pageDict);
115   m_pPDFPage->ParseContent();
116 
117   return TRUE;
118 }
119 
GetPageWidth()120 FX_FLOAT CPDFXFA_Page::GetPageWidth() {
121   ASSERT(m_pDocument != NULL);
122 
123   if (!m_pPDFPage && !m_pXFAPageView)
124     return 0.0f;
125 
126   int nDocType = m_pDocument->GetDocType();
127   switch (nDocType) {
128     case DOCTYPE_DYNAMIC_XFA: {
129       if (m_pXFAPageView) {
130         CFX_RectF rect;
131         m_pXFAPageView->GetPageViewRect(rect);
132         return rect.width;
133       }
134     } break;
135     case DOCTYPE_STATIC_XFA:
136     case DOCTYPE_PDF: {
137       if (m_pPDFPage)
138         return m_pPDFPage->GetPageWidth();
139     } break;
140     default:
141       return 0.0f;
142   }
143 
144   return 0.0f;
145 }
146 
GetPageHeight()147 FX_FLOAT CPDFXFA_Page::GetPageHeight() {
148   ASSERT(m_pDocument != NULL);
149 
150   if (!m_pPDFPage && !m_pXFAPageView)
151     return 0.0f;
152 
153   int nDocType = m_pDocument->GetDocType();
154   switch (nDocType) {
155     case DOCTYPE_PDF:
156     case DOCTYPE_STATIC_XFA: {
157       if (m_pPDFPage)
158         return m_pPDFPage->GetPageHeight();
159     } break;
160     case DOCTYPE_DYNAMIC_XFA: {
161       if (m_pXFAPageView) {
162         CFX_RectF rect;
163         m_pXFAPageView->GetPageViewRect(rect);
164         return rect.height;
165       }
166     } break;
167     default:
168       return 0.0f;
169   }
170 
171   return 0.0f;
172 }
173 
DeviceToPage(int start_x,int start_y,int size_x,int size_y,int rotate,int device_x,int device_y,double * page_x,double * page_y)174 void CPDFXFA_Page::DeviceToPage(int start_x,
175                                 int start_y,
176                                 int size_x,
177                                 int size_y,
178                                 int rotate,
179                                 int device_x,
180                                 int device_y,
181                                 double* page_x,
182                                 double* page_y) {
183   ASSERT(m_pDocument != NULL);
184 
185   if (!m_pPDFPage && !m_pXFAPageView)
186     return;
187 
188   CFX_Matrix page2device;
189   CFX_Matrix device2page;
190   FX_FLOAT page_x_f, page_y_f;
191 
192   GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
193 
194   device2page.SetReverse(page2device);
195   device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
196                         page_y_f);
197 
198   *page_x = (page_x_f);
199   *page_y = (page_y_f);
200 }
201 
PageToDevice(int start_x,int start_y,int size_x,int size_y,int rotate,double page_x,double page_y,int * device_x,int * device_y)202 void CPDFXFA_Page::PageToDevice(int start_x,
203                                 int start_y,
204                                 int size_x,
205                                 int size_y,
206                                 int rotate,
207                                 double page_x,
208                                 double page_y,
209                                 int* device_x,
210                                 int* device_y) {
211   if (!m_pPDFPage && !m_pXFAPageView)
212     return;
213 
214   CFX_Matrix page2device;
215   FX_FLOAT device_x_f, device_y_f;
216 
217   GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
218 
219   page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
220                         device_y_f);
221 
222   *device_x = FXSYS_round(device_x_f);
223   *device_y = FXSYS_round(device_y_f);
224 }
225 
GetDisplayMatrix(CFX_Matrix & matrix,int xPos,int yPos,int xSize,int ySize,int iRotate) const226 void CPDFXFA_Page::GetDisplayMatrix(CFX_Matrix& matrix,
227                                     int xPos,
228                                     int yPos,
229                                     int xSize,
230                                     int ySize,
231                                     int iRotate) const {
232   ASSERT(m_pDocument != NULL);
233 
234   if (!m_pPDFPage && !m_pXFAPageView)
235     return;
236 
237   int nDocType = m_pDocument->GetDocType();
238   switch (nDocType) {
239     case DOCTYPE_DYNAMIC_XFA: {
240       if (m_pXFAPageView) {
241         CFX_Rect rect;
242         rect.Set(xPos, yPos, xSize, ySize);
243         m_pXFAPageView->GetDisplayMatrix(matrix, rect, iRotate);
244       }
245     } break;
246     case DOCTYPE_PDF:
247     case DOCTYPE_STATIC_XFA: {
248       if (m_pPDFPage) {
249         m_pPDFPage->GetDisplayMatrix(matrix, xPos, yPos, xSize, ySize, iRotate);
250       }
251     } break;
252     default:
253       return;
254   }
255 }
256