blob: 79b3e874a1a112d43e19dc4941593c1d21bd32cc [file] [log] [blame]
Lei Zhang94293682016-01-27 18:27:56 -08001// 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
dsinclair4d29e782016-10-04 14:02:47 -07007#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -04008
Tom Sepezffb51092019-08-09 19:27:25 +00009#include <memory>
10
dsinclair41872fa2016-10-04 11:29:35 -070011#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070012#include "core/fpdfapi/parser/cpdf_document.h"
Tom Sepez0208b0c2019-07-23 21:52:50 +000013#include "core/fpdfapi/render/cpdf_pagerendercache.h"
Tom Sepezffb51092019-08-09 19:27:25 +000014#include "fpdfsdk/cpdfsdk_pageview.h"
dsinclair521b7502016-11-02 13:02:28 -070015#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
Tom Sepez451ed2d2019-08-19 22:55:31 +000016#include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
Tom Sepezffb51092019-08-09 19:27:25 +000017#include "third_party/base/ptr_util.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040018#include "xfa/fxfa/cxfa_ffdocview.h"
19#include "xfa/fxfa/cxfa_ffpageview.h"
Tom Sepezbcb7a692019-08-09 21:21:09 +000020#include "xfa/fxfa/cxfa_ffwidget.h"
Tom Sepez66497fe2019-08-09 20:55:06 +000021#include "xfa/fxfa/cxfa_ffwidgethandler.h"
22#include "xfa/fxfa/cxfa_rendercontext.h"
23#include "xfa/fxgraphics/cxfa_graphics.h"
Lei Zhang94293682016-01-27 18:27:56 -080024
Tom Sepez9bf01812019-08-19 18:59:27 +000025CPDFXFA_Page::CPDFXFA_Page(CPDF_Document* pDocument, int page_index)
26 : m_pDocument(pDocument), m_iPageIndex(page_index) {
27 ASSERT(m_pDocument->GetExtension());
Lei Zhang30540a92018-10-04 22:31:12 +000028 ASSERT(m_iPageIndex >= 0);
29}
Lei Zhang94293682016-01-27 18:27:56 -080030
Lei Zhang30540a92018-10-04 22:31:12 +000031CPDFXFA_Page::~CPDFXFA_Page() = default;
Lei Zhang94293682016-01-27 18:27:56 -080032
Tom Sepez101535f2018-06-12 13:36:05 +000033CPDF_Page* CPDFXFA_Page::AsPDFPage() {
34 return m_pPDFPage.Get();
35}
36
37CPDFXFA_Page* CPDFXFA_Page::AsXFAPage() {
38 return this;
39}
40
41CPDF_Document* CPDFXFA_Page::GetDocument() const {
Tom Sepez9bf01812019-08-19 18:59:27 +000042 return m_pDocument.Get();
Tom Sepez101535f2018-06-12 13:36:05 +000043}
44
Henrique Nakashima7b094f82018-05-08 20:32:08 +000045bool CPDFXFA_Page::LoadPDFPage() {
Lei Zhang30540a92018-10-04 22:31:12 +000046 CPDF_Document* pPDFDoc = GetDocument();
Henrique Nakashima7b094f82018-05-08 20:32:08 +000047 CPDF_Dictionary* pDict = pPDFDoc->GetPageDictionary(m_iPageIndex);
48 if (!pDict)
49 return false;
50
Tom Sepez0208b0c2019-07-23 21:52:50 +000051 if (!m_pPDFPage || m_pPDFPage->GetDict() != pDict)
52 LoadPDFPageFromDict(pDict);
53
Henrique Nakashima7b094f82018-05-08 20:32:08 +000054 return true;
55}
56
Tom Sepez4ae52352019-01-07 20:39:29 +000057CXFA_FFPageView* CPDFXFA_Page::GetXFAPageView() const {
Tom Sepez9bf01812019-08-19 18:59:27 +000058 auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
59 CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
Tom Sepez4ae52352019-01-07 20:39:29 +000060 return pXFADocView ? pXFADocView->GetPageView(m_iPageIndex) : nullptr;
Lei Zhang94293682016-01-27 18:27:56 -080061}
62
Henrique Nakashima7b094f82018-05-08 20:32:08 +000063bool CPDFXFA_Page::LoadPage() {
Tom Sepez9bf01812019-08-19 18:59:27 +000064 auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
65 switch (pContext->GetFormType()) {
Henrique Nakashima7b094f82018-05-08 20:32:08 +000066 case FormType::kNone:
67 case FormType::kAcroForm:
68 case FormType::kXFAForeground:
69 return LoadPDFPage();
70 case FormType::kXFAFull:
Tom Sepez4ae52352019-01-07 20:39:29 +000071 return !!GetXFAPageView();
Henrique Nakashima7b094f82018-05-08 20:32:08 +000072 }
Lei Zhang30540a92018-10-04 22:31:12 +000073 NOTREACHED();
Henrique Nakashima7b094f82018-05-08 20:32:08 +000074 return false;
75}
76
Lei Zhang30540a92018-10-04 22:31:12 +000077void CPDFXFA_Page::LoadPDFPageFromDict(CPDF_Dictionary* pPageDict) {
78 ASSERT(pPageDict);
Tom Sepez0208b0c2019-07-23 21:52:50 +000079 m_pPDFPage = pdfium::MakeRetain<CPDF_Page>(GetDocument(), pPageDict);
80 m_pPDFPage->SetRenderCache(
81 pdfium::MakeUnique<CPDF_PageRenderCache>(m_pPDFPage.Get()));
Tom Sepezf06ed6d2018-06-04 18:26:07 +000082 m_pPDFPage->ParseContent();
Henrique Nakashima7b094f82018-05-08 20:32:08 +000083}
84
Dan Sinclair05df0752017-03-14 14:43:42 -040085float CPDFXFA_Page::GetPageWidth() const {
Tom Sepez4ae52352019-01-07 20:39:29 +000086 CXFA_FFPageView* pPageView = GetXFAPageView();
87 if (!m_pPDFPage && !pPageView)
Lei Zhang94293682016-01-27 18:27:56 -080088 return 0.0f;
89
Tom Sepez9bf01812019-08-19 18:59:27 +000090 auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
91 switch (pContext->GetFormType()) {
Ryan Harrison854d71c2017-10-18 12:28:14 -040092 case FormType::kNone:
93 case FormType::kAcroForm:
94 case FormType::kXFAForeground:
Lei Zhang94293682016-01-27 18:27:56 -080095 if (m_pPDFPage)
96 return m_pPDFPage->GetPageWidth();
Lei Zhangdb3c6ce2018-05-17 02:01:42 +000097 FALLTHROUGH;
Ryan Harrison854d71c2017-10-18 12:28:14 -040098 case FormType::kXFAFull:
Tom Sepez4ae52352019-01-07 20:39:29 +000099 if (pPageView)
100 return pPageView->GetPageViewRect().width;
Henrique Nakashima067a44f2018-02-16 03:46:28 +0000101 break;
Lei Zhang94293682016-01-27 18:27:56 -0800102 }
103
104 return 0.0f;
105}
106
Dan Sinclair05df0752017-03-14 14:43:42 -0400107float CPDFXFA_Page::GetPageHeight() const {
Tom Sepez4ae52352019-01-07 20:39:29 +0000108 CXFA_FFPageView* pPageView = GetXFAPageView();
109 if (!m_pPDFPage && !pPageView)
Lei Zhang94293682016-01-27 18:27:56 -0800110 return 0.0f;
111
Tom Sepez9bf01812019-08-19 18:59:27 +0000112 auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
113 switch (pContext->GetFormType()) {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400114 case FormType::kNone:
115 case FormType::kAcroForm:
116 case FormType::kXFAForeground:
Lei Zhang94293682016-01-27 18:27:56 -0800117 if (m_pPDFPage)
118 return m_pPDFPage->GetPageHeight();
Lei Zhangdb3c6ce2018-05-17 02:01:42 +0000119 FALLTHROUGH;
Ryan Harrison854d71c2017-10-18 12:28:14 -0400120 case FormType::kXFAFull:
Tom Sepez4ae52352019-01-07 20:39:29 +0000121 if (pPageView)
122 return pPageView->GetPageViewRect().height;
Henrique Nakashima067a44f2018-02-16 03:46:28 +0000123 break;
Lei Zhang94293682016-01-27 18:27:56 -0800124 }
125
126 return 0.0f;
127}
128
Lei Zhang822886b2018-04-12 17:24:45 +0000129Optional<CFX_PointF> CPDFXFA_Page::DeviceToPage(
130 const FX_RECT& rect,
131 int rotate,
132 const CFX_PointF& device_point) const {
Tom Sepez4ae52352019-01-07 20:39:29 +0000133 CXFA_FFPageView* pPageView = GetXFAPageView();
134 if (!m_pPDFPage && !pPageView)
Lei Zhang822886b2018-04-12 17:24:45 +0000135 return {};
Lei Zhang94293682016-01-27 18:27:56 -0800136
Lei Zhanga105fa12018-04-12 16:23:01 +0000137 CFX_PointF pos =
138 GetDisplayMatrix(rect, rotate).GetInverse().Transform(device_point);
Lei Zhang822886b2018-04-12 17:24:45 +0000139 return pos;
Lei Zhang94293682016-01-27 18:27:56 -0800140}
141
Lei Zhanga8db06a2018-04-12 17:53:15 +0000142Optional<CFX_PointF> CPDFXFA_Page::PageToDevice(
143 const FX_RECT& rect,
144 int rotate,
145 const CFX_PointF& page_point) const {
Tom Sepez4ae52352019-01-07 20:39:29 +0000146 CXFA_FFPageView* pPageView = GetXFAPageView();
147 if (!m_pPDFPage && !pPageView)
Lei Zhang822886b2018-04-12 17:24:45 +0000148 return {};
Lei Zhang94293682016-01-27 18:27:56 -0800149
Lei Zhangc4242b22018-04-12 15:50:49 +0000150 CFX_Matrix page2device = GetDisplayMatrix(rect, rotate);
Lei Zhanga8db06a2018-04-12 17:53:15 +0000151 return page2device.Transform(page_point);
Lei Zhang94293682016-01-27 18:27:56 -0800152}
153
Lei Zhangc4242b22018-04-12 15:50:49 +0000154CFX_Matrix CPDFXFA_Page::GetDisplayMatrix(const FX_RECT& rect,
Dan Sinclair1b08df12017-02-09 09:17:20 -0500155 int iRotate) const {
Tom Sepez4ae52352019-01-07 20:39:29 +0000156 CXFA_FFPageView* pPageView = GetXFAPageView();
157 if (!m_pPDFPage && !pPageView)
Dan Sinclair1b08df12017-02-09 09:17:20 -0500158 return CFX_Matrix();
Lei Zhang94293682016-01-27 18:27:56 -0800159
Tom Sepez9bf01812019-08-19 18:59:27 +0000160 auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
161 switch (pContext->GetFormType()) {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400162 case FormType::kNone:
163 case FormType::kAcroForm:
164 case FormType::kXFAForeground:
Dan Sinclair1b08df12017-02-09 09:17:20 -0500165 if (m_pPDFPage)
Lei Zhangc4242b22018-04-12 15:50:49 +0000166 return m_pPDFPage->GetDisplayMatrix(rect, iRotate);
Lei Zhangdb3c6ce2018-05-17 02:01:42 +0000167 FALLTHROUGH;
Ryan Harrison854d71c2017-10-18 12:28:14 -0400168 case FormType::kXFAFull:
Tom Sepez4ae52352019-01-07 20:39:29 +0000169 if (pPageView)
170 return pPageView->GetDisplayMatrix(rect, iRotate);
Henrique Nakashima067a44f2018-02-16 03:46:28 +0000171 break;
Lei Zhang94293682016-01-27 18:27:56 -0800172 }
Ryan Harrison854d71c2017-10-18 12:28:14 -0400173
Dan Sinclair1b08df12017-02-09 09:17:20 -0500174 return CFX_Matrix();
Lei Zhang94293682016-01-27 18:27:56 -0800175}
Tom Sepezffb51092019-08-09 19:27:25 +0000176
177CPDFSDK_Annot* CPDFXFA_Page::GetNextXFAAnnot(CPDFSDK_Annot* pSDKAnnot,
178 bool bNext) {
Tom Sepez451ed2d2019-08-19 22:55:31 +0000179 CPDFXFA_Widget* pXFAWidget = ToXFAWidget(pSDKAnnot);
180 if (!pXFAWidget)
181 return nullptr;
182
Tom Sepezffb51092019-08-09 19:27:25 +0000183 ObservedPtr<CPDFSDK_Annot> pObservedAnnot(pSDKAnnot);
184 CPDFSDK_PageView* pPageView = pSDKAnnot->GetPageView();
185 std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
186 GetXFAPageView()->CreateWidgetIterator(XFA_TRAVERSEWAY_Tranvalse,
187 XFA_WidgetStatus_Visible |
188 XFA_WidgetStatus_Viewable |
189 XFA_WidgetStatus_Focused));
190
191 // Check |pSDKAnnot| again because JS may have destroyed it
192 if (!pObservedAnnot || !pWidgetIterator)
193 return nullptr;
194
Tom Sepez451ed2d2019-08-19 22:55:31 +0000195 if (pWidgetIterator->GetCurrentWidget() != pXFAWidget->GetXFAFFWidget())
196 pWidgetIterator->SetCurrentWidget(pXFAWidget->GetXFAFFWidget());
197
Tom Sepezffb51092019-08-09 19:27:25 +0000198 CXFA_FFWidget* hNextFocus =
199 bNext ? pWidgetIterator->MoveToNext() : pWidgetIterator->MoveToPrevious();
200 if (!hNextFocus && pSDKAnnot)
201 hNextFocus = pWidgetIterator->MoveToFirst();
202
203 return pPageView->GetAnnotByXFAWidget(hNextFocus);
204}
Tom Sepez66497fe2019-08-09 20:55:06 +0000205
Tom Sepezbcb7a692019-08-09 21:21:09 +0000206int CPDFXFA_Page::HasFormFieldAtPoint(const CFX_PointF& point) const {
207 CXFA_FFPageView* pPageView = GetXFAPageView();
208 if (!pPageView)
209 return -1;
210
211 CXFA_FFDocView* pDocView = pPageView->GetDocView();
212 if (!pDocView)
213 return -1;
214
215 CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
216 if (!pWidgetHandler)
217 return -1;
218
219 std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
220 pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form,
221 XFA_WidgetStatus_Viewable));
222 if (!pWidgetIterator)
223 return -1;
224
225 CXFA_FFWidget* pXFAAnnot;
226 while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) {
227 if (pXFAAnnot->GetFormFieldType() == FormFieldType::kXFA)
228 continue;
229
230 CFX_FloatRect rcWidget = pXFAAnnot->GetWidgetRect().ToFloatRect();
231 rcWidget.Inflate(1.0f, 1.0f);
232 if (rcWidget.Contains(point))
233 return static_cast<int>(pXFAAnnot->GetFormFieldType());
234 }
235
236 return -1;
237}
238
Tom Sepez66497fe2019-08-09 20:55:06 +0000239void CPDFXFA_Page::DrawFocusAnnot(CFX_RenderDevice* pDevice,
240 CPDFSDK_Annot* pAnnot,
241 const CFX_Matrix& mtUser2Device,
242 const FX_RECT& rtClip) {
Tom Sepeza0624a02019-08-09 22:12:09 +0000243 CFX_RectF rectClip(rtClip);
Tom Sepez66497fe2019-08-09 20:55:06 +0000244 CXFA_Graphics gs(pDevice);
245 gs.SetClipRect(rectClip);
246
247 CXFA_FFPageView* xfaView = GetXFAPageView();
248 CXFA_RenderContext renderContext(xfaView, rectClip, mtUser2Device);
249 renderContext.DoRender(&gs);
250
Tom Sepez451ed2d2019-08-19 22:55:31 +0000251 CPDFXFA_Widget* pXFAWidget = ToXFAWidget(pAnnot);
252 if (!pXFAWidget)
Tom Sepez66497fe2019-08-09 20:55:06 +0000253 return;
254
255 CXFA_FFDocView* docView = xfaView->GetDocView();
256 if (!docView)
257 return;
258
Tom Sepez451ed2d2019-08-19 22:55:31 +0000259 docView->GetWidgetHandler()->RenderWidget(pXFAWidget->GetXFAFFWidget(), &gs,
Tom Sepez66497fe2019-08-09 20:55:06 +0000260 mtUser2Device, false);
261}