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