1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_page.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_pageimagecache.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_document.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_pageview.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/graphics/cfgas_gegraphics.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdocview.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffpageview.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidget.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidgethandler.h"
24*3ac0a46fSAndroid Build Coastguard Worker
25*3ac0a46fSAndroid Build Coastguard Worker namespace {
26*3ac0a46fSAndroid Build Coastguard Worker
27*3ac0a46fSAndroid Build Coastguard Worker constexpr Mask<XFA_WidgetStatus> kIteratorFilter = {
28*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kVisible,
29*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kViewable,
30*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kFocused,
31*3ac0a46fSAndroid Build Coastguard Worker };
32*3ac0a46fSAndroid Build Coastguard Worker
GCedWidgetIteratorForPage(CXFA_FFPageView * pFFPageView,CPDFSDK_PageView * pPageView)33*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* GCedWidgetIteratorForPage(
34*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pFFPageView,
35*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_PageView* pPageView) {
36*3ac0a46fSAndroid Build Coastguard Worker if (!pFFPageView)
37*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
38*3ac0a46fSAndroid Build Coastguard Worker
39*3ac0a46fSAndroid Build Coastguard Worker ObservedPtr<CPDFSDK_PageView> pWatchedPageView(pPageView);
40*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pIterator =
41*3ac0a46fSAndroid Build Coastguard Worker pFFPageView->CreateGCedTraverseWidgetIterator(kIteratorFilter);
42*3ac0a46fSAndroid Build Coastguard Worker
43*3ac0a46fSAndroid Build Coastguard Worker // Check |pPageView| again because JS may have destroyed it.
44*3ac0a46fSAndroid Build Coastguard Worker return pWatchedPageView ? pIterator : nullptr;
45*3ac0a46fSAndroid Build Coastguard Worker }
46*3ac0a46fSAndroid Build Coastguard Worker
GCedWidgetIteratorForAnnot(CXFA_FFPageView * pFFPageView,CPDFSDK_Annot * pSDKAnnot)47*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* GCedWidgetIteratorForAnnot(
48*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pFFPageView,
49*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* pSDKAnnot) {
50*3ac0a46fSAndroid Build Coastguard Worker if (!pFFPageView)
51*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
52*3ac0a46fSAndroid Build Coastguard Worker
53*3ac0a46fSAndroid Build Coastguard Worker CPDFXFA_Widget* pXFAWidget = ToXFAWidget(pSDKAnnot);
54*3ac0a46fSAndroid Build Coastguard Worker if (!pXFAWidget)
55*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
56*3ac0a46fSAndroid Build Coastguard Worker
57*3ac0a46fSAndroid Build Coastguard Worker ObservedPtr<CPDFSDK_Annot> pObservedAnnot(pSDKAnnot);
58*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pWidgetIterator =
59*3ac0a46fSAndroid Build Coastguard Worker pFFPageView->CreateGCedTraverseWidgetIterator(kIteratorFilter);
60*3ac0a46fSAndroid Build Coastguard Worker
61*3ac0a46fSAndroid Build Coastguard Worker // Check |pSDKAnnot| again because JS may have destroyed it.
62*3ac0a46fSAndroid Build Coastguard Worker if (!pObservedAnnot)
63*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
64*3ac0a46fSAndroid Build Coastguard Worker
65*3ac0a46fSAndroid Build Coastguard Worker if (pWidgetIterator->GetCurrentWidget() != pXFAWidget->GetXFAFFWidget())
66*3ac0a46fSAndroid Build Coastguard Worker pWidgetIterator->SetCurrentWidget(pXFAWidget->GetXFAFFWidget());
67*3ac0a46fSAndroid Build Coastguard Worker
68*3ac0a46fSAndroid Build Coastguard Worker return pWidgetIterator;
69*3ac0a46fSAndroid Build Coastguard Worker }
70*3ac0a46fSAndroid Build Coastguard Worker
71*3ac0a46fSAndroid Build Coastguard Worker } // namespace
72*3ac0a46fSAndroid Build Coastguard Worker
CPDFXFA_Page(CPDF_Document * pDocument,int page_index)73*3ac0a46fSAndroid Build Coastguard Worker CPDFXFA_Page::CPDFXFA_Page(CPDF_Document* pDocument, int page_index)
74*3ac0a46fSAndroid Build Coastguard Worker : m_pDocument(pDocument), m_iPageIndex(page_index) {
75*3ac0a46fSAndroid Build Coastguard Worker DCHECK(m_pDocument->GetExtension());
76*3ac0a46fSAndroid Build Coastguard Worker DCHECK(m_iPageIndex >= 0);
77*3ac0a46fSAndroid Build Coastguard Worker }
78*3ac0a46fSAndroid Build Coastguard Worker
79*3ac0a46fSAndroid Build Coastguard Worker CPDFXFA_Page::~CPDFXFA_Page() = default;
80*3ac0a46fSAndroid Build Coastguard Worker
AsPDFPage()81*3ac0a46fSAndroid Build Coastguard Worker CPDF_Page* CPDFXFA_Page::AsPDFPage() {
82*3ac0a46fSAndroid Build Coastguard Worker return m_pPDFPage.Get();
83*3ac0a46fSAndroid Build Coastguard Worker }
84*3ac0a46fSAndroid Build Coastguard Worker
AsXFAPage()85*3ac0a46fSAndroid Build Coastguard Worker CPDFXFA_Page* CPDFXFA_Page::AsXFAPage() {
86*3ac0a46fSAndroid Build Coastguard Worker return this;
87*3ac0a46fSAndroid Build Coastguard Worker }
88*3ac0a46fSAndroid Build Coastguard Worker
GetDocument() const89*3ac0a46fSAndroid Build Coastguard Worker CPDF_Document* CPDFXFA_Page::GetDocument() const {
90*3ac0a46fSAndroid Build Coastguard Worker return m_pDocument;
91*3ac0a46fSAndroid Build Coastguard Worker }
92*3ac0a46fSAndroid Build Coastguard Worker
LoadPDFPage()93*3ac0a46fSAndroid Build Coastguard Worker bool CPDFXFA_Page::LoadPDFPage() {
94*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Dictionary> pDict =
95*3ac0a46fSAndroid Build Coastguard Worker GetDocument()->GetMutablePageDictionary(m_iPageIndex);
96*3ac0a46fSAndroid Build Coastguard Worker if (!pDict)
97*3ac0a46fSAndroid Build Coastguard Worker return false;
98*3ac0a46fSAndroid Build Coastguard Worker
99*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage || m_pPDFPage->GetDict() != pDict)
100*3ac0a46fSAndroid Build Coastguard Worker LoadPDFPageFromDict(std::move(pDict));
101*3ac0a46fSAndroid Build Coastguard Worker
102*3ac0a46fSAndroid Build Coastguard Worker return true;
103*3ac0a46fSAndroid Build Coastguard Worker }
104*3ac0a46fSAndroid Build Coastguard Worker
GetXFAPageView() const105*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* CPDFXFA_Page::GetXFAPageView() const {
106*3ac0a46fSAndroid Build Coastguard Worker auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
107*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
108*3ac0a46fSAndroid Build Coastguard Worker return pXFADocView ? pXFADocView->GetPageView(m_iPageIndex) : nullptr;
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker
LoadPage()111*3ac0a46fSAndroid Build Coastguard Worker bool CPDFXFA_Page::LoadPage() {
112*3ac0a46fSAndroid Build Coastguard Worker auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
113*3ac0a46fSAndroid Build Coastguard Worker switch (pContext->GetFormType()) {
114*3ac0a46fSAndroid Build Coastguard Worker case FormType::kNone:
115*3ac0a46fSAndroid Build Coastguard Worker case FormType::kAcroForm:
116*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAForeground:
117*3ac0a46fSAndroid Build Coastguard Worker return LoadPDFPage();
118*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAFull:
119*3ac0a46fSAndroid Build Coastguard Worker return !!GetXFAPageView();
120*3ac0a46fSAndroid Build Coastguard Worker }
121*3ac0a46fSAndroid Build Coastguard Worker }
122*3ac0a46fSAndroid Build Coastguard Worker
LoadPDFPageFromDict(RetainPtr<CPDF_Dictionary> pPageDict)123*3ac0a46fSAndroid Build Coastguard Worker void CPDFXFA_Page::LoadPDFPageFromDict(RetainPtr<CPDF_Dictionary> pPageDict) {
124*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pPageDict);
125*3ac0a46fSAndroid Build Coastguard Worker m_pPDFPage =
126*3ac0a46fSAndroid Build Coastguard Worker pdfium::MakeRetain<CPDF_Page>(GetDocument(), std::move(pPageDict));
127*3ac0a46fSAndroid Build Coastguard Worker m_pPDFPage->AddPageImageCache();
128*3ac0a46fSAndroid Build Coastguard Worker m_pPDFPage->ParseContent();
129*3ac0a46fSAndroid Build Coastguard Worker }
130*3ac0a46fSAndroid Build Coastguard Worker
GetPageWidth() const131*3ac0a46fSAndroid Build Coastguard Worker float CPDFXFA_Page::GetPageWidth() const {
132*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
133*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage && !pPageView)
134*3ac0a46fSAndroid Build Coastguard Worker return 0.0f;
135*3ac0a46fSAndroid Build Coastguard Worker
136*3ac0a46fSAndroid Build Coastguard Worker auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
137*3ac0a46fSAndroid Build Coastguard Worker switch (pContext->GetFormType()) {
138*3ac0a46fSAndroid Build Coastguard Worker case FormType::kNone:
139*3ac0a46fSAndroid Build Coastguard Worker case FormType::kAcroForm:
140*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAForeground:
141*3ac0a46fSAndroid Build Coastguard Worker if (m_pPDFPage)
142*3ac0a46fSAndroid Build Coastguard Worker return m_pPDFPage->GetPageWidth();
143*3ac0a46fSAndroid Build Coastguard Worker [[fallthrough]];
144*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAFull:
145*3ac0a46fSAndroid Build Coastguard Worker if (pPageView)
146*3ac0a46fSAndroid Build Coastguard Worker return pPageView->GetPageViewRect().width;
147*3ac0a46fSAndroid Build Coastguard Worker break;
148*3ac0a46fSAndroid Build Coastguard Worker }
149*3ac0a46fSAndroid Build Coastguard Worker
150*3ac0a46fSAndroid Build Coastguard Worker return 0.0f;
151*3ac0a46fSAndroid Build Coastguard Worker }
152*3ac0a46fSAndroid Build Coastguard Worker
GetPageHeight() const153*3ac0a46fSAndroid Build Coastguard Worker float CPDFXFA_Page::GetPageHeight() const {
154*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
155*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage && !pPageView)
156*3ac0a46fSAndroid Build Coastguard Worker return 0.0f;
157*3ac0a46fSAndroid Build Coastguard Worker
158*3ac0a46fSAndroid Build Coastguard Worker auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
159*3ac0a46fSAndroid Build Coastguard Worker switch (pContext->GetFormType()) {
160*3ac0a46fSAndroid Build Coastguard Worker case FormType::kNone:
161*3ac0a46fSAndroid Build Coastguard Worker case FormType::kAcroForm:
162*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAForeground:
163*3ac0a46fSAndroid Build Coastguard Worker if (m_pPDFPage)
164*3ac0a46fSAndroid Build Coastguard Worker return m_pPDFPage->GetPageHeight();
165*3ac0a46fSAndroid Build Coastguard Worker [[fallthrough]];
166*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAFull:
167*3ac0a46fSAndroid Build Coastguard Worker if (pPageView)
168*3ac0a46fSAndroid Build Coastguard Worker return pPageView->GetPageViewRect().height;
169*3ac0a46fSAndroid Build Coastguard Worker break;
170*3ac0a46fSAndroid Build Coastguard Worker }
171*3ac0a46fSAndroid Build Coastguard Worker
172*3ac0a46fSAndroid Build Coastguard Worker return 0.0f;
173*3ac0a46fSAndroid Build Coastguard Worker }
174*3ac0a46fSAndroid Build Coastguard Worker
DeviceToPage(const FX_RECT & rect,int rotate,const CFX_PointF & device_point) const175*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFX_PointF> CPDFXFA_Page::DeviceToPage(
176*3ac0a46fSAndroid Build Coastguard Worker const FX_RECT& rect,
177*3ac0a46fSAndroid Build Coastguard Worker int rotate,
178*3ac0a46fSAndroid Build Coastguard Worker const CFX_PointF& device_point) const {
179*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
180*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage && !pPageView)
181*3ac0a46fSAndroid Build Coastguard Worker return absl::nullopt;
182*3ac0a46fSAndroid Build Coastguard Worker
183*3ac0a46fSAndroid Build Coastguard Worker CFX_Matrix page2device = GetDisplayMatrix(rect, rotate);
184*3ac0a46fSAndroid Build Coastguard Worker return page2device.GetInverse().Transform(device_point);
185*3ac0a46fSAndroid Build Coastguard Worker }
186*3ac0a46fSAndroid Build Coastguard Worker
PageToDevice(const FX_RECT & rect,int rotate,const CFX_PointF & page_point) const187*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFX_PointF> CPDFXFA_Page::PageToDevice(
188*3ac0a46fSAndroid Build Coastguard Worker const FX_RECT& rect,
189*3ac0a46fSAndroid Build Coastguard Worker int rotate,
190*3ac0a46fSAndroid Build Coastguard Worker const CFX_PointF& page_point) const {
191*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
192*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage && !pPageView)
193*3ac0a46fSAndroid Build Coastguard Worker return absl::nullopt;
194*3ac0a46fSAndroid Build Coastguard Worker
195*3ac0a46fSAndroid Build Coastguard Worker CFX_Matrix page2device = GetDisplayMatrix(rect, rotate);
196*3ac0a46fSAndroid Build Coastguard Worker return page2device.Transform(page_point);
197*3ac0a46fSAndroid Build Coastguard Worker }
198*3ac0a46fSAndroid Build Coastguard Worker
GetDisplayMatrix(const FX_RECT & rect,int iRotate) const199*3ac0a46fSAndroid Build Coastguard Worker CFX_Matrix CPDFXFA_Page::GetDisplayMatrix(const FX_RECT& rect,
200*3ac0a46fSAndroid Build Coastguard Worker int iRotate) const {
201*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
202*3ac0a46fSAndroid Build Coastguard Worker if (!m_pPDFPage && !pPageView)
203*3ac0a46fSAndroid Build Coastguard Worker return CFX_Matrix();
204*3ac0a46fSAndroid Build Coastguard Worker
205*3ac0a46fSAndroid Build Coastguard Worker auto* pContext = static_cast<CPDFXFA_Context*>(m_pDocument->GetExtension());
206*3ac0a46fSAndroid Build Coastguard Worker switch (pContext->GetFormType()) {
207*3ac0a46fSAndroid Build Coastguard Worker case FormType::kNone:
208*3ac0a46fSAndroid Build Coastguard Worker case FormType::kAcroForm:
209*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAForeground:
210*3ac0a46fSAndroid Build Coastguard Worker if (m_pPDFPage)
211*3ac0a46fSAndroid Build Coastguard Worker return m_pPDFPage->GetDisplayMatrix(rect, iRotate);
212*3ac0a46fSAndroid Build Coastguard Worker [[fallthrough]];
213*3ac0a46fSAndroid Build Coastguard Worker case FormType::kXFAFull:
214*3ac0a46fSAndroid Build Coastguard Worker if (pPageView)
215*3ac0a46fSAndroid Build Coastguard Worker return pPageView->GetDisplayMatrix(rect, iRotate);
216*3ac0a46fSAndroid Build Coastguard Worker break;
217*3ac0a46fSAndroid Build Coastguard Worker }
218*3ac0a46fSAndroid Build Coastguard Worker
219*3ac0a46fSAndroid Build Coastguard Worker return CFX_Matrix();
220*3ac0a46fSAndroid Build Coastguard Worker }
221*3ac0a46fSAndroid Build Coastguard Worker
GetNextXFAAnnot(CPDFSDK_Annot * pSDKAnnot) const222*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* CPDFXFA_Page::GetNextXFAAnnot(CPDFSDK_Annot* pSDKAnnot) const {
223*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pWidgetIterator =
224*3ac0a46fSAndroid Build Coastguard Worker GCedWidgetIteratorForAnnot(GetXFAPageView(), pSDKAnnot);
225*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetIterator)
226*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
227*3ac0a46fSAndroid Build Coastguard Worker
228*3ac0a46fSAndroid Build Coastguard Worker return pSDKAnnot->GetPageView()->GetAnnotForFFWidget(
229*3ac0a46fSAndroid Build Coastguard Worker pWidgetIterator->MoveToNext());
230*3ac0a46fSAndroid Build Coastguard Worker }
231*3ac0a46fSAndroid Build Coastguard Worker
GetPrevXFAAnnot(CPDFSDK_Annot * pSDKAnnot) const232*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* CPDFXFA_Page::GetPrevXFAAnnot(CPDFSDK_Annot* pSDKAnnot) const {
233*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pWidgetIterator =
234*3ac0a46fSAndroid Build Coastguard Worker GCedWidgetIteratorForAnnot(GetXFAPageView(), pSDKAnnot);
235*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetIterator)
236*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
237*3ac0a46fSAndroid Build Coastguard Worker
238*3ac0a46fSAndroid Build Coastguard Worker return pSDKAnnot->GetPageView()->GetAnnotForFFWidget(
239*3ac0a46fSAndroid Build Coastguard Worker pWidgetIterator->MoveToPrevious());
240*3ac0a46fSAndroid Build Coastguard Worker }
241*3ac0a46fSAndroid Build Coastguard Worker
GetFirstXFAAnnot(CPDFSDK_PageView * page_view) const242*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* CPDFXFA_Page::GetFirstXFAAnnot(
243*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_PageView* page_view) const {
244*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pWidgetIterator =
245*3ac0a46fSAndroid Build Coastguard Worker GCedWidgetIteratorForPage(GetXFAPageView(), page_view);
246*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetIterator)
247*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
248*3ac0a46fSAndroid Build Coastguard Worker
249*3ac0a46fSAndroid Build Coastguard Worker return page_view->GetAnnotForFFWidget(pWidgetIterator->MoveToFirst());
250*3ac0a46fSAndroid Build Coastguard Worker }
251*3ac0a46fSAndroid Build Coastguard Worker
GetLastXFAAnnot(CPDFSDK_PageView * page_view) const252*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* CPDFXFA_Page::GetLastXFAAnnot(
253*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_PageView* page_view) const {
254*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget::IteratorIface* pWidgetIterator =
255*3ac0a46fSAndroid Build Coastguard Worker GCedWidgetIteratorForPage(GetXFAPageView(), page_view);
256*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetIterator)
257*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
258*3ac0a46fSAndroid Build Coastguard Worker
259*3ac0a46fSAndroid Build Coastguard Worker return page_view->GetAnnotForFFWidget(pWidgetIterator->MoveToLast());
260*3ac0a46fSAndroid Build Coastguard Worker }
261*3ac0a46fSAndroid Build Coastguard Worker
HasFormFieldAtPoint(const CFX_PointF & point) const262*3ac0a46fSAndroid Build Coastguard Worker int CPDFXFA_Page::HasFormFieldAtPoint(const CFX_PointF& point) const {
263*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pPageView = GetXFAPageView();
264*3ac0a46fSAndroid Build Coastguard Worker if (!pPageView)
265*3ac0a46fSAndroid Build Coastguard Worker return -1;
266*3ac0a46fSAndroid Build Coastguard Worker
267*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView* pDocView = pPageView->GetDocView();
268*3ac0a46fSAndroid Build Coastguard Worker if (!pDocView)
269*3ac0a46fSAndroid Build Coastguard Worker return -1;
270*3ac0a46fSAndroid Build Coastguard Worker
271*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
272*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetHandler)
273*3ac0a46fSAndroid Build Coastguard Worker return -1;
274*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageWidgetIterator pWidgetIterator(pPageView,
275*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kViewable);
276*3ac0a46fSAndroid Build Coastguard Worker
277*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pXFAAnnot;
278*3ac0a46fSAndroid Build Coastguard Worker while ((pXFAAnnot = pWidgetIterator.MoveToNext()) != nullptr) {
279*3ac0a46fSAndroid Build Coastguard Worker if (pXFAAnnot->GetFormFieldType() == FormFieldType::kXFA)
280*3ac0a46fSAndroid Build Coastguard Worker continue;
281*3ac0a46fSAndroid Build Coastguard Worker
282*3ac0a46fSAndroid Build Coastguard Worker CFX_FloatRect rcWidget = pXFAAnnot->GetWidgetRect().ToFloatRect();
283*3ac0a46fSAndroid Build Coastguard Worker rcWidget.Inflate(1.0f, 1.0f);
284*3ac0a46fSAndroid Build Coastguard Worker if (rcWidget.Contains(point))
285*3ac0a46fSAndroid Build Coastguard Worker return static_cast<int>(pXFAAnnot->GetFormFieldType());
286*3ac0a46fSAndroid Build Coastguard Worker }
287*3ac0a46fSAndroid Build Coastguard Worker
288*3ac0a46fSAndroid Build Coastguard Worker return -1;
289*3ac0a46fSAndroid Build Coastguard Worker }
290*3ac0a46fSAndroid Build Coastguard Worker
DrawFocusAnnot(CFX_RenderDevice * pDevice,CPDFSDK_Annot * pAnnot,const CFX_Matrix & mtUser2Device,const FX_RECT & rtClip)291*3ac0a46fSAndroid Build Coastguard Worker void CPDFXFA_Page::DrawFocusAnnot(CFX_RenderDevice* pDevice,
292*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Annot* pAnnot,
293*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& mtUser2Device,
294*3ac0a46fSAndroid Build Coastguard Worker const FX_RECT& rtClip) {
295*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rectClip(rtClip);
296*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEGraphics gs(pDevice);
297*3ac0a46fSAndroid Build Coastguard Worker gs.SetClipRect(rectClip);
298*3ac0a46fSAndroid Build Coastguard Worker
299*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* xfaView = GetXFAPageView();
300*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageWidgetIterator pWidgetIterator(
301*3ac0a46fSAndroid Build Coastguard Worker xfaView, Mask<XFA_WidgetStatus>{XFA_WidgetStatus::kVisible,
302*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kViewable});
303*3ac0a46fSAndroid Build Coastguard Worker
304*3ac0a46fSAndroid Build Coastguard Worker while (true) {
305*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pWidget = pWidgetIterator.MoveToNext();
306*3ac0a46fSAndroid Build Coastguard Worker if (!pWidget)
307*3ac0a46fSAndroid Build Coastguard Worker break;
308*3ac0a46fSAndroid Build Coastguard Worker
309*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtWidgetBox = pWidget->GetBBox(CXFA_FFWidget::kDoNotDrawFocus);
310*3ac0a46fSAndroid Build Coastguard Worker ++rtWidgetBox.width;
311*3ac0a46fSAndroid Build Coastguard Worker ++rtWidgetBox.height;
312*3ac0a46fSAndroid Build Coastguard Worker if (rtWidgetBox.IntersectWith(rectClip))
313*3ac0a46fSAndroid Build Coastguard Worker pWidget->RenderWidget(&gs, mtUser2Device, CXFA_FFWidget::kHighlight);
314*3ac0a46fSAndroid Build Coastguard Worker }
315*3ac0a46fSAndroid Build Coastguard Worker
316*3ac0a46fSAndroid Build Coastguard Worker CPDFXFA_Widget* pXFAWidget = ToXFAWidget(pAnnot);
317*3ac0a46fSAndroid Build Coastguard Worker if (!pXFAWidget)
318*3ac0a46fSAndroid Build Coastguard Worker return;
319*3ac0a46fSAndroid Build Coastguard Worker
320*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView* docView = xfaView->GetDocView();
321*3ac0a46fSAndroid Build Coastguard Worker if (!docView)
322*3ac0a46fSAndroid Build Coastguard Worker return;
323*3ac0a46fSAndroid Build Coastguard Worker
324*3ac0a46fSAndroid Build Coastguard Worker docView->GetWidgetHandler()->RenderWidget(pXFAWidget->GetXFAFFWidget(), &gs,
325*3ac0a46fSAndroid Build Coastguard Worker mtUser2Device, false);
326*3ac0a46fSAndroid Build Coastguard Worker }
327