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
cxfa_ffpageview.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 "xfa/fxfa/cxfa_ffpageview.h"
8
9#include <algorithm>
10#include <vector>
11
12#include "core/fxcrt/stl_util.h"
13#include "fxjs/gc/container_trace.h"
14#include "fxjs/xfa/cjx_object.h"
15#include "third_party/base/check.h"
16#include "third_party/base/containers/contains.h"
17#include "xfa/fxfa/cxfa_ffcheckbutton.h"
18#include "xfa/fxfa/cxfa_ffdoc.h"
19#include "xfa/fxfa/cxfa_ffdocview.h"
20#include "xfa/fxfa/cxfa_fffield.h"
21#include "xfa/fxfa/cxfa_ffimageedit.h"
22#include "xfa/fxfa/cxfa_ffpushbutton.h"
23#include "xfa/fxfa/cxfa_ffwidget.h"
24#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
25#include "xfa/fxfa/parser/cxfa_node.h"
26#include "xfa/fxfa/parser/cxfa_traversal.h"
27#include "xfa/fxfa/parser/cxfa_traverse.h"
28
29namespace {
30
31CFX_Matrix GetPageMatrix(const CFX_RectF& docPageRect,
32 const FX_RECT& devicePageRect,
33 int32_t iRotate) {
34 DCHECK(iRotate >= 0);
35 DCHECK(iRotate <= 3);
36
37 CFX_Matrix m;
38 if (iRotate == 0 || iRotate == 2) {
39 m.a *= (float)devicePageRect.Width() / docPageRect.width;
40 m.d *= (float)devicePageRect.Height() / docPageRect.height;
41 } else {
42 m.a *= (float)devicePageRect.Height() / docPageRect.width;
43 m.d *= (float)devicePageRect.Width() / docPageRect.height;
44 }
45 m.Rotate(iRotate * 1.57079632675f);
46 switch (iRotate) {
47 case 0:
48 m.e = devicePageRect.left;
49 m.f = devicePageRect.top;
50 break;
51 case 1:
52 m.e = devicePageRect.right;
53 m.f = devicePageRect.top;
54 break;
55 case 2:
56 m.e = devicePageRect.right;
57 m.f = devicePageRect.bottom;
58 break;
59 case 3:
60 m.e = devicePageRect.left;
61 m.f = devicePageRect.bottom;
62 break;
63 default:
64 break;
65 }
66 return m;
67}
68
69bool PageWidgetFilter(CXFA_FFWidget* pWidget,
70 Mask<XFA_WidgetStatus> dwFilter,
71 bool bTraversal,
72 bool bIgnoreRelevant) {
73 CXFA_Node* pNode = pWidget->GetNode();
74
75 if ((dwFilter & XFA_WidgetStatus::kFocused) &&
76 (!pNode || pNode->GetElementType() != XFA_Element::Field)) {
77 return false;
78 }
79
80 CXFA_ContentLayoutItem* pItem = pWidget->GetLayoutItem();
81 if (bTraversal && pItem->TestStatusBits(XFA_WidgetStatus::kDisabled))
82 return false;
83 if (bIgnoreRelevant)
85
86 dwFilter &= Mask<XFA_WidgetStatus>{XFA_WidgetStatus::kVisible,
89 return pItem->TestStatusBits(dwFilter);
90}
91
92bool IsLayoutElement(XFA_Element eElement) {
93 switch (eElement) {
94 case XFA_Element::Area:
95 case XFA_Element::Subform:
96 case XFA_Element::ExclGroup:
97 case XFA_Element::SubformSet:
98 case XFA_Element::PageArea:
99 case XFA_Element::Form:
100 return true;
101 default:
102 return false;
103 }
104}
105
106CXFA_Document* GetDocForPageView(const CXFA_FFPageView* view) {
108}
109
110bool IsDocVersionBelow205(const CXFA_Document* doc) {
112}
113
114bool EnsureWidgetLoadedIfVisible(CXFA_FFWidget* pWidget) {
115 if (!pWidget->IsLoaded() &&
117 if (!pWidget->LoadWidget())
118 return false;
119 }
120 return true;
121}
122
123CXFA_FFWidget* LoadedWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
125 if (!pWidget)
126 return nullptr;
127
128 EnsureWidgetLoadedIfVisible(pWidget);
129 return pWidget;
130}
131
132CXFA_FFWidget* FilteredLoadedWidgetFromLayoutItem(
133 CXFA_LayoutItem* pLayoutItem,
134 Mask<XFA_WidgetStatus> dwFilter,
135 bool bIgnoreRelevant) {
137 if (!pWidget)
138 return nullptr;
139
140 if (!PageWidgetFilter(pWidget, dwFilter, false, bIgnoreRelevant))
141 return nullptr;
142
143 if (!EnsureWidgetLoadedIfVisible(pWidget))
144 return nullptr;
145
146 return pWidget;
147}
148
149class CXFA_TabParam {
150 public:
151 CXFA_TabParam() = default;
152 explicit CXFA_TabParam(CXFA_FFWidget* pWidget)
153 : m_pItem(pWidget->GetLayoutItem()) {}
154 CXFA_TabParam(const CXFA_TabParam&) = delete;
155 CXFA_TabParam(CXFA_TabParam&&) noexcept = default;
156 ~CXFA_TabParam() = default;
157
158 CXFA_TabParam& operator=(const CXFA_TabParam&) = delete;
159 CXFA_TabParam& operator=(CXFA_TabParam&&) noexcept = default;
160
161 CXFA_FFWidget* GetWidget() const { return m_pItem->GetFFWidget(); }
162 const std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>& GetChildren()
163 const {
164 return m_Children;
165 }
166 void ClearChildren() { m_Children.clear(); }
167 void AppendTabParam(const CXFA_TabParam* pParam) {
168 m_Children.push_back(pParam->m_pItem);
169 m_Children.insert(m_Children.end(), pParam->m_Children.begin(),
170 pParam->m_Children.end());
171 }
172
173 private:
174 cppgc::Persistent<CXFA_ContentLayoutItem> m_pItem;
175 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> m_Children;
176};
177
178void OrderContainer(CXFA_LayoutItemIterator* sIterator,
179 CXFA_LayoutItem* pViewItem,
180 CXFA_TabParam* pContainer,
181 bool* bCurrentItem,
182 bool* bContentArea,
183 bool bMasterPage) {
184 std::vector<CXFA_TabParam> tabParams;
185 CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext();
186 while (pSearchItem) {
187 if (!pSearchItem->IsContentLayoutItem()) {
188 *bContentArea = true;
189 pSearchItem = sIterator->MoveToNext();
190 continue;
191 }
192 if (bMasterPage && *bContentArea) {
193 break;
194 }
195 if (bMasterPage || *bContentArea) {
196 CXFA_FFWidget* hWidget = LoadedWidgetFromLayoutItem(pSearchItem);
197 if (!hWidget) {
198 pSearchItem = sIterator->MoveToNext();
199 continue;
200 }
201 if (pViewItem && (pSearchItem->GetParent() != pViewItem)) {
202 *bCurrentItem = true;
203 break;
204 }
205 tabParams.emplace_back(hWidget);
206 if (IsLayoutElement(pSearchItem->GetFormNode()->GetElementType())) {
207 OrderContainer(sIterator, pSearchItem, &tabParams.back(), bCurrentItem,
208 bContentArea, bMasterPage);
209 }
210 }
211 if (*bCurrentItem) {
212 pSearchItem = sIterator->GetCurrent();
213 *bCurrentItem = false;
214 } else {
215 pSearchItem = sIterator->MoveToNext();
216 }
217 }
218 std::sort(tabParams.begin(), tabParams.end(),
219 [](const CXFA_TabParam& arg1, const CXFA_TabParam& arg2) {
220 const CFX_RectF& rt1 = arg1.GetWidget()->GetWidgetRect();
221 const CFX_RectF& rt2 = arg2.GetWidget()->GetWidgetRect();
222 if (rt1.top - rt2.top >= kXFAWidgetPrecision)
223 return rt1.top < rt2.top;
224 return rt1.left < rt2.left;
225 });
226 for (const auto& param : tabParams)
227 pContainer->AppendTabParam(&param);
228}
229
230} // namespace
231
232CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea)
233 : m_pPageArea(pPageArea), m_pDocView(pDocView) {}
234
235CXFA_FFPageView::~CXFA_FFPageView() = default;
236
237void CXFA_FFPageView::Trace(cppgc::Visitor* visitor) const {
238 visitor->Trace(m_pPageArea);
239 visitor->Trace(m_pDocView);
240 visitor->Trace(m_pLayoutItem);
241}
242
243CXFA_FFDocView* CXFA_FFPageView::GetDocView() const {
244 return m_pDocView;
245}
246
247CFX_RectF CXFA_FFPageView::GetPageViewRect() const {
248 auto* pItem = GetLayoutItem();
249 if (!pItem)
250 return CFX_RectF();
251
252 return CFX_RectF(0, 0, pItem->GetPageSize());
253}
254
255CFX_Matrix CXFA_FFPageView::GetDisplayMatrix(const FX_RECT& rtDisp,
256 int32_t iRotate) const {
257 auto* pItem = GetLayoutItem();
258 if (!pItem)
259 return CFX_Matrix();
260
261 return GetPageMatrix(CFX_RectF(0, 0, pItem->GetPageSize()), rtDisp, iRotate);
262}
263
265 Mask<XFA_WidgetStatus> dwWidgetFilter) {
266 return cppgc::MakeGarbageCollected<CXFA_FFTabOrderPageWidgetIterator>(
267 GetDocView()->GetDoc()->GetHeap()->GetAllocationHandle(), this,
268 dwWidgetFilter);
269}
270
271CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(
272 CXFA_FFPageView* pPageView,
273 Mask<XFA_WidgetStatus> dwFilter)
276 m_bIgnoreRelevant(IsDocVersionBelow205(GetDocForPageView(pPageView))) {}
277
278CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() = default;
279
280CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToFirst() {
281 m_sIterator.Reset();
282 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem;
283 pLayoutItem = m_sIterator.MoveToNext()) {
284 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
285 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
286 if (hWidget)
287 return hWidget;
288 }
289 return nullptr;
290}
291
292CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() {
293 m_sIterator.SetCurrent(nullptr);
294 return MoveToPrevious();
295}
296
297CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToNext() {
298 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem;
299 pLayoutItem = m_sIterator.MoveToNext()) {
300 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
301 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
302 if (hWidget)
303 return hWidget;
304 }
305 return nullptr;
306}
307
308CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToPrevious() {
309 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem;
310 pLayoutItem = m_sIterator.MoveToPrev()) {
311 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
312 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
313 if (hWidget)
314 return hWidget;
315 }
316 return nullptr;
317}
318
319CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() {
320 CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent();
321 return pLayoutItem ? CXFA_FFWidget::FromLayoutItem(pLayoutItem) : nullptr;
322}
323
324bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* pWidget) {
325 return pWidget && m_sIterator.SetCurrent(pWidget->GetLayoutItem());
326}
327
328CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator(
329 CXFA_FFPageView* pPageView,
330 Mask<XFA_WidgetStatus> dwFilter)
331 : m_pPageViewLayout(pPageView->GetLayoutItem()),
332 m_dwFilter(dwFilter),
333 m_bIgnoreRelevant(IsDocVersionBelow205(GetDocForPageView(pPageView))) {
334 CreateTabOrderWidgetArray();
335}
336
337CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() =
338 default;
339
340void CXFA_FFTabOrderPageWidgetIterator::Trace(cppgc::Visitor* visitor) const {
341 visitor->Trace(m_pPageViewLayout);
342 ContainerTrace(visitor, m_TabOrderWidgetArray);
343}
344
345CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() {
346 for (int32_t i = 0; i < fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray);
347 i++) {
348 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
349 true, m_bIgnoreRelevant)) {
350 m_iCurWidget = i;
351 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
352 }
353 }
354 return nullptr;
355}
356
357CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() {
358 for (int32_t i = fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray) - 1;
359 i >= 0; i--) {
360 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
361 true, m_bIgnoreRelevant)) {
362 m_iCurWidget = i;
363 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
364 }
365 }
366 return nullptr;
367}
368
369CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() {
370 for (int32_t i = m_iCurWidget + 1;
371 i < fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) {
372 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
373 true, m_bIgnoreRelevant)) {
374 m_iCurWidget = i;
375 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
376 }
377 }
378 m_iCurWidget = -1;
379 return nullptr;
380}
381
382CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() {
383 for (int32_t i = m_iCurWidget - 1; i >= 0; i--) {
384 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
385 true, m_bIgnoreRelevant)) {
386 m_iCurWidget = i;
387 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
388 }
389 }
390 m_iCurWidget = -1;
391 return nullptr;
392}
393
394CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() {
395 return m_iCurWidget >= 0 ? m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget()
396 : nullptr;
397}
398
399bool CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget(
400 CXFA_FFWidget* hWidget) {
401 auto it = std::find(m_TabOrderWidgetArray.begin(),
402 m_TabOrderWidgetArray.end(), hWidget->GetLayoutItem());
403 if (it == m_TabOrderWidgetArray.end())
404 return false;
405
406 m_iCurWidget =
407 pdfium::base::checked_cast<int32_t>(it - m_TabOrderWidgetArray.begin());
408 return true;
409}
410
411CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget(
412 CXFA_FFWidget* pWidget) {
413 CXFA_Traversal* pTraversal = pWidget->GetNode()->GetChild<CXFA_Traversal>(
414 0, XFA_Element::Traversal, false);
415 if (pTraversal) {
416 CXFA_Traverse* pTraverse =
417 pTraversal->GetChild<CXFA_Traverse>(0, XFA_Element::Traverse, false);
418 if (pTraverse) {
419 absl::optional<WideString> traverseWidgetName =
420 pTraverse->JSObject()->TryAttribute(XFA_Attribute::Ref, true);
421 if (traverseWidgetName.has_value())
422 return FindWidgetByName(traverseWidgetName.value(), pWidget);
423 }
424 }
425 return nullptr;
426}
427CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName(
428 const WideString& wsWidgetName,
429 CXFA_FFWidget* pRefWidget) {
430 return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget);
431}
432
433void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() {
434 m_TabOrderWidgetArray.clear();
435
436 const std::vector<CXFA_ContentLayoutItem*> items =
437 CreateSpaceOrderLayoutItems();
438 if (items.empty())
439 return;
440
441 CXFA_ContentLayoutItem* item = items[0];
442 while (m_TabOrderWidgetArray.size() < items.size()) {
443 if (!pdfium::Contains(m_TabOrderWidgetArray, item)) {
444 m_TabOrderWidgetArray.emplace_back(item);
447 auto it = std::find(items.begin(), items.end(), item);
448 size_t index = it != items.end() ? it - items.begin() + 1 : 0;
449 while (true) {
450 CXFA_FFWidget* radio = items[index % items.size()]->GetFFWidget();
452 break;
453 if (!pdfium::Contains(m_TabOrderWidgetArray, item))
454 m_TabOrderWidgetArray.emplace_back(radio->GetLayoutItem());
455 ++index;
456 }
457 }
458 CXFA_FFWidget* next_widget = GetTraverseWidget(item->GetFFWidget());
459 if (next_widget) {
460 item = next_widget->GetLayoutItem();
461 continue;
462 }
463 }
464 auto it = std::find(items.begin(), items.end(), item);
465 size_t index = it != items.end() ? it - items.begin() + 1 : 0;
466 item = items[index % items.size()];
467 }
468}
469
470std::vector<CXFA_ContentLayoutItem*>
471CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderLayoutItems() {
472 std::vector<CXFA_ContentLayoutItem*> items;
473 CXFA_LayoutItemIterator sIterator(m_pPageViewLayout.Get());
474 CXFA_TabParam tabparam;
475 bool bCurrentItem = false;
476 bool bContentArea = false;
477 OrderContainer(&sIterator, nullptr, &tabparam, &bCurrentItem, &bContentArea,
478 false);
479 items.reserve(tabparam.GetChildren().size());
480 for (const auto& layout_item : tabparam.GetChildren())
481 items.push_back(layout_item);
482
483 sIterator.Reset();
484 bCurrentItem = false;
485 bContentArea = false;
486 tabparam.ClearChildren();
487 OrderContainer(&sIterator, nullptr, &tabparam, &bCurrentItem, &bContentArea,
488 true);
489 for (const auto& layout_item : tabparam.GetChildren())
490 items.push_back(layout_item);
491
492 return items;
493}
void Rotate(float fRadian)
CFX_Matrix()=default
constexpr CFX_RectF()=default
CFX_RectF(float dst_left, float dst_top, const SizeType &dst_size)
bool TestStatusBits(Mask< XFA_WidgetStatus > val) const
XFA_VERSION GetCurVersionMode() const
CXFA_FFDoc * GetDoc() const
CXFA_FFWidget * GetWidgetByName(const WideString &wsName, CXFA_FFWidget *pRefWidget)
CXFA_Document * GetXFADoc() const
Definition cxfa_ffdoc.h:167
CXFA_ViewLayoutItem * GetLayoutItem() 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_FFPageWidgetIterator() override
CXFA_FFPageWidgetIterator(CXFA_FFPageView *pPageView, Mask< XFA_WidgetStatus > dwFilter)
CXFA_FFWidget * MoveToLast() override
CXFA_FFWidget * MoveToNext() override
CXFA_FFWidget * MoveToFirst() override
bool SetCurrentWidget(CXFA_FFWidget *hWidget) override
CXFA_FFWidget * GetCurrentWidget() override
CXFA_FFWidget * MoveToPrevious() override
CXFA_FFWidget * MoveToFirst() override
CXFA_FFWidget * MoveToLast() override
CXFA_FFWidget * MoveToNext() override
CXFA_FFWidget * GetCurrentWidget() override
CXFA_FFWidget * MoveToPrevious() override
bool SetCurrentWidget(CXFA_FFWidget *hWidget) override
static CXFA_FFWidget * FromLayoutItem(CXFA_LayoutItem *pLayoutItem)
const CFX_RectF & GetWidgetRect() const
virtual bool IsLoaded()
CXFA_Node * GetNode() const
virtual bool LoadWidget()
CXFA_ContentLayoutItem * GetLayoutItem() const
CXFA_FFDocView * GetDocView() const
bool IsContentLayoutItem() const
CXFA_Node * GetFormNode() const
CXFA_Node * GetExclGroupIfExists()
XFA_FFWidgetType GetFFWidgetType()
XFA_Element GetElementType() const
Definition cxfa_object.h:91
CFX_SizeF GetPageSize() const
@ XFA_VERSION_205
constexpr float kXFAWidgetPrecision
XFA_FFWidgetType
XFA_WidgetStatus
Definition fxfa.h:61
XFA_Element
Definition fxfa_basic.h:75
Definition heap.h:12
int Height() const
int32_t bottom
int32_t right
int Width() const
int32_t top
int32_t left