summaryrefslogtreecommitdiff
path: root/xfa/fxfa/cxfa_ffpageview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fxfa/cxfa_ffpageview.cpp')
-rw-r--r--xfa/fxfa/cxfa_ffpageview.cpp459
1 files changed, 459 insertions, 0 deletions
diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp
new file mode 100644
index 0000000000..3eda5a1d4a
--- /dev/null
+++ b/xfa/fxfa/cxfa_ffpageview.cpp
@@ -0,0 +1,459 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fxfa/cxfa_ffpageview.h"
+
+#include <memory>
+#include <vector>
+
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+#include "xfa/fde/fde_render.h"
+#include "xfa/fxfa/app/xfa_ffcheckbutton.h"
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffimageedit.h"
+#include "xfa/fxfa/app/xfa_ffpushbutton.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/cxfa_ffdoc.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+
+namespace {
+
+CFX_Matrix GetPageMatrix(const CFX_RectF& docPageRect,
+ const CFX_Rect& devicePageRect,
+ int32_t iRotate,
+ uint32_t dwCoordinatesType) {
+ ASSERT(iRotate >= 0 && iRotate <= 3);
+
+ bool bFlipX = (dwCoordinatesType & 0x01) != 0;
+ bool bFlipY = (dwCoordinatesType & 0x02) != 0;
+ CFX_Matrix m((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0);
+ if (iRotate == 0 || iRotate == 2) {
+ m.a *= (float)devicePageRect.width / docPageRect.width;
+ m.d *= (float)devicePageRect.height / docPageRect.height;
+ } else {
+ m.a *= (float)devicePageRect.height / docPageRect.width;
+ m.d *= (float)devicePageRect.width / docPageRect.height;
+ }
+ m.Rotate(iRotate * 1.57079632675f);
+ switch (iRotate) {
+ case 0:
+ m.e = bFlipX ? (float)devicePageRect.right() : (float)devicePageRect.left;
+ m.f = bFlipY ? (float)devicePageRect.bottom() : (float)devicePageRect.top;
+ break;
+ case 1:
+ m.e = bFlipY ? (float)devicePageRect.left : (float)devicePageRect.right();
+ m.f = bFlipX ? (float)devicePageRect.bottom() : (float)devicePageRect.top;
+ break;
+ case 2:
+ m.e = bFlipX ? (float)devicePageRect.left : (float)devicePageRect.right();
+ m.f = bFlipY ? (float)devicePageRect.top : (float)devicePageRect.bottom();
+ break;
+ case 3:
+ m.e = bFlipY ? (float)devicePageRect.right() : (float)devicePageRect.left;
+ m.f = bFlipX ? (float)devicePageRect.top : (float)devicePageRect.bottom();
+ break;
+ default:
+ break;
+ }
+ return m;
+}
+
+bool PageWidgetFilter(CXFA_FFWidget* pWidget,
+ uint32_t dwFilter,
+ bool bTraversal,
+ bool bIgnorerelevant) {
+ CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc();
+
+ if (!!(dwFilter & XFA_WidgetStatus_Focused) &&
+ pWidgetAcc->GetElementType() != XFA_Element::Field) {
+ return false;
+ }
+
+ uint32_t dwStatus = pWidget->GetStatus();
+ if (bTraversal && (dwStatus & XFA_WidgetStatus_Disabled))
+ return false;
+ if (bIgnorerelevant)
+ return !!(dwStatus & XFA_WidgetStatus_Visible);
+
+ dwFilter &= (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable |
+ XFA_WidgetStatus_Printable);
+ return (dwFilter & dwStatus) == dwFilter;
+}
+
+bool IsLayoutElement(XFA_Element eElement, bool bLayoutContainer) {
+ switch (eElement) {
+ case XFA_Element::Draw:
+ case XFA_Element::Field:
+ case XFA_Element::InstanceManager:
+ return !bLayoutContainer;
+ case XFA_Element::Area:
+ case XFA_Element::Subform:
+ case XFA_Element::ExclGroup:
+ case XFA_Element::SubformSet:
+ case XFA_Element::PageArea:
+ case XFA_Element::Form:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace
+
+CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea)
+ : CXFA_ContainerLayoutItem(pPageArea), m_pDocView(pDocView) {}
+
+CXFA_FFPageView::~CXFA_FFPageView() {}
+
+CXFA_FFDocView* CXFA_FFPageView::GetDocView() const {
+ return m_pDocView;
+}
+
+CFX_RectF CXFA_FFPageView::GetPageViewRect() const {
+ return CFX_RectF(0, 0, GetPageSize());
+}
+
+CFX_Matrix CXFA_FFPageView::GetDisplayMatrix(const CFX_Rect& rtDisp,
+ int32_t iRotate) const {
+ return GetPageMatrix(CFX_RectF(0, 0, GetPageSize()), rtDisp, iRotate, 0);
+}
+
+IXFA_WidgetIterator* CXFA_FFPageView::CreateWidgetIterator(
+ uint32_t dwTraverseWay,
+ uint32_t dwWidgetFilter) {
+ switch (dwTraverseWay) {
+ case XFA_TRAVERSEWAY_Tranvalse:
+ return new CXFA_FFTabOrderPageWidgetIterator(this, dwWidgetFilter);
+ case XFA_TRAVERSEWAY_Form:
+ return new CXFA_FFPageWidgetIterator(this, dwWidgetFilter);
+ }
+ return nullptr;
+}
+
+CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView,
+ uint32_t dwFilter)
+ : m_pPageView(pPageView), m_dwFilter(dwFilter), m_sIterator(pPageView) {
+ m_bIgnorerelevant =
+ m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() <
+ XFA_VERSION_205;
+}
+
+CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {}
+
+void CXFA_FFPageWidgetIterator::Reset() {
+ m_sIterator.Reset();
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToFirst() {
+ m_sIterator.Reset();
+ for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem;
+ pLayoutItem = m_sIterator.MoveToNext()) {
+ if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) {
+ return hWidget;
+ }
+ }
+ return nullptr;
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() {
+ m_sIterator.SetCurrent(nullptr);
+ return MoveToPrevious();
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToNext() {
+ for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem;
+ pLayoutItem = m_sIterator.MoveToNext()) {
+ if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) {
+ return hWidget;
+ }
+ }
+ return nullptr;
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToPrevious() {
+ for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem;
+ pLayoutItem = m_sIterator.MoveToPrev()) {
+ if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) {
+ return hWidget;
+ }
+ }
+ return nullptr;
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() {
+ CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent();
+ return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : nullptr;
+}
+bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* hWidget) {
+ return hWidget && m_sIterator.SetCurrent(hWidget);
+}
+CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetWidget(
+ CXFA_LayoutItem* pLayoutItem) {
+ if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) {
+ if (!PageWidgetFilter(pWidget, m_dwFilter, false, m_bIgnorerelevant)) {
+ return nullptr;
+ }
+ if (!pWidget->IsLoaded() &&
+ (pWidget->GetStatus() & XFA_WidgetStatus_Visible) != 0) {
+ pWidget->LoadWidget();
+ }
+ return pWidget;
+ }
+ return nullptr;
+}
+
+CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator(
+ CXFA_FFPageView* pPageView,
+ uint32_t dwFilter)
+ : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) {
+ m_bIgnorerelevant =
+ m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() <
+ XFA_VERSION_205;
+ Reset();
+}
+
+CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {}
+
+void CXFA_FFTabOrderPageWidgetIterator::Reset() {
+ CreateTabOrderWidgetArray();
+ m_iCurWidget = -1;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() {
+ for (int32_t i = 0;
+ i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) {
+ if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true,
+ m_bIgnorerelevant)) {
+ m_iCurWidget = i;
+ return m_TabOrderWidgetArray[m_iCurWidget];
+ }
+ }
+ return nullptr;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() {
+ for (int32_t i = pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) - 1;
+ i >= 0; i--) {
+ if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true,
+ m_bIgnorerelevant)) {
+ m_iCurWidget = i;
+ return m_TabOrderWidgetArray[m_iCurWidget];
+ }
+ }
+ return nullptr;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() {
+ for (int32_t i = m_iCurWidget + 1;
+ i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) {
+ if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true,
+ m_bIgnorerelevant)) {
+ m_iCurWidget = i;
+ return m_TabOrderWidgetArray[m_iCurWidget];
+ }
+ }
+ m_iCurWidget = -1;
+ return nullptr;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() {
+ for (int32_t i = m_iCurWidget - 1; i >= 0; i--) {
+ if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true,
+ m_bIgnorerelevant)) {
+ m_iCurWidget = i;
+ return m_TabOrderWidgetArray[m_iCurWidget];
+ }
+ }
+ m_iCurWidget = -1;
+ return nullptr;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() {
+ return m_iCurWidget >= 0 ? m_TabOrderWidgetArray[m_iCurWidget] : nullptr;
+}
+
+bool CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget(
+ CXFA_FFWidget* hWidget) {
+ auto it = std::find(m_TabOrderWidgetArray.begin(),
+ m_TabOrderWidgetArray.end(), hWidget);
+ if (it == m_TabOrderWidgetArray.end())
+ return false;
+
+ m_iCurWidget = it - m_TabOrderWidgetArray.begin();
+ return true;
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget(
+ CXFA_FFWidget* pWidget) {
+ CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc();
+ CXFA_Node* pTraversal = pAcc->GetNode()->GetChild(0, XFA_Element::Traversal);
+ if (pTraversal) {
+ CXFA_Node* pTraverse = pTraversal->GetChild(0, XFA_Element::Traverse);
+ if (pTraverse) {
+ CFX_WideString wsTraverseWidgetName;
+ if (pTraverse->GetAttribute(XFA_ATTRIBUTE_Ref, wsTraverseWidgetName)) {
+ return FindWidgetByName(wsTraverseWidgetName, pWidget);
+ }
+ }
+ }
+ return nullptr;
+}
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName(
+ const CFX_WideString& wsWidgetName,
+ CXFA_FFWidget* pRefWidget) {
+ return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget);
+}
+
+void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() {
+ m_TabOrderWidgetArray.clear();
+
+ std::vector<CXFA_FFWidget*> SpaceOrderWidgetArray;
+ CreateSpaceOrderWidgetArray(&SpaceOrderWidgetArray);
+ if (SpaceOrderWidgetArray.empty())
+ return;
+
+ int32_t nWidgetCount = pdfium::CollectionSize<int32_t>(SpaceOrderWidgetArray);
+ CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0];
+ while (pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) <
+ nWidgetCount) {
+ if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) {
+ m_TabOrderWidgetArray.push_back(hWidget);
+ CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc();
+ if (pWidgetAcc->GetUIType() == XFA_Element::ExclGroup) {
+ auto it = std::find(SpaceOrderWidgetArray.begin(),
+ SpaceOrderWidgetArray.end(), hWidget);
+ int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end()
+ ? it - SpaceOrderWidgetArray.begin() + 1
+ : 0;
+ while (true) {
+ CXFA_FFWidget* pRadio =
+ SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount];
+ if (pRadio->GetDataAcc()->GetExclGroup() != pWidgetAcc) {
+ break;
+ }
+ if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) {
+ m_TabOrderWidgetArray.push_back(pRadio);
+ }
+ iWidgetIndex++;
+ }
+ }
+ if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) {
+ hWidget = hTraverseWidget;
+ continue;
+ }
+ }
+ auto it = std::find(SpaceOrderWidgetArray.begin(),
+ SpaceOrderWidgetArray.end(), hWidget);
+ int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end()
+ ? it - SpaceOrderWidgetArray.begin() + 1
+ : 0;
+ hWidget = SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount];
+ }
+}
+
+static int32_t XFA_TabOrderWidgetComparator(const void* phWidget1,
+ const void* phWidget2) {
+ auto* param1 = *static_cast<CXFA_TabParam**>(const_cast<void*>(phWidget1));
+ auto* param2 = *static_cast<CXFA_TabParam**>(const_cast<void*>(phWidget2));
+ CFX_RectF rt1 = param1->m_pWidget->GetWidgetRect();
+ CFX_RectF rt2 = param2->m_pWidget->GetWidgetRect();
+ float x1 = rt1.left, y1 = rt1.top, x2 = rt2.left, y2 = rt2.top;
+ if (y1 < y2 || (y1 - y2 < XFA_FLOAT_PERCISION && x1 < x2))
+ return -1;
+ return 1;
+}
+
+void CXFA_FFTabOrderPageWidgetIterator::OrderContainer(
+ CXFA_LayoutItemIterator* sIterator,
+ CXFA_LayoutItem* pContainerItem,
+ CXFA_TabParam* pContainer,
+ bool& bCurrentItem,
+ bool& bContentArea,
+ bool bMarsterPage) {
+ CFX_ArrayTemplate<CXFA_TabParam*> tabParams;
+ CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext();
+ while (pSearchItem) {
+ if (!pSearchItem->IsContentLayoutItem()) {
+ bContentArea = true;
+ pSearchItem = sIterator->MoveToNext();
+ continue;
+ }
+ if (bMarsterPage && bContentArea) {
+ break;
+ }
+ if (bMarsterPage || bContentArea) {
+ CXFA_FFWidget* hWidget = GetWidget(pSearchItem);
+ if (!hWidget) {
+ pSearchItem = sIterator->MoveToNext();
+ continue;
+ }
+ if (pContainerItem && (pSearchItem->GetParent() != pContainerItem)) {
+ bCurrentItem = true;
+ break;
+ }
+ CXFA_TabParam* pParam = new CXFA_TabParam;
+ pParam->m_pWidget = hWidget;
+ tabParams.Add(pParam);
+ if (IsLayoutElement(pSearchItem->GetFormNode()->GetElementType(), true)) {
+ OrderContainer(sIterator, pSearchItem, pParam, bCurrentItem,
+ bContentArea, bMarsterPage);
+ }
+ }
+ if (bCurrentItem) {
+ pSearchItem = sIterator->GetCurrent();
+ bCurrentItem = false;
+ } else {
+ pSearchItem = sIterator->MoveToNext();
+ }
+ }
+ int32_t iChildren = tabParams.GetSize();
+ if (iChildren > 1) {
+ FXSYS_qsort(tabParams.GetData(), iChildren, sizeof(void*),
+ XFA_TabOrderWidgetComparator);
+ }
+ for (int32_t iStart = 0; iStart < iChildren; iStart++) {
+ std::unique_ptr<CXFA_TabParam> pParam(tabParams[iStart]);
+ pContainer->m_Children.push_back(pParam->m_pWidget);
+ pContainer->m_Children.insert(pContainer->m_Children.end(),
+ pParam->m_Children.begin(),
+ pParam->m_Children.end());
+ }
+ tabParams.RemoveAll();
+}
+void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray(
+ std::vector<CXFA_FFWidget*>* WidgetArray) {
+ CXFA_LayoutItemIterator sIterator(m_pPageView);
+ auto pParam = pdfium::MakeUnique<CXFA_TabParam>();
+ bool bCurrentItem = false;
+ bool bContentArea = false;
+ OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea);
+ WidgetArray->insert(WidgetArray->end(), pParam->m_Children.begin(),
+ pParam->m_Children.end());
+
+ sIterator.Reset();
+ bCurrentItem = false;
+ bContentArea = false;
+ pParam->m_Children.clear();
+ OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea,
+ true);
+ WidgetArray->insert(WidgetArray->end(), pParam->m_Children.begin(),
+ pParam->m_Children.end());
+}
+
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget(
+ CXFA_LayoutItem* pLayoutItem) {
+ if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) {
+ if (!pWidget->IsLoaded() &&
+ (pWidget->GetStatus() & XFA_WidgetStatus_Visible)) {
+ pWidget->LoadWidget();
+ }
+ return pWidget;
+ }
+ return nullptr;
+}
+
+CXFA_TabParam::CXFA_TabParam() : m_pWidget(nullptr) {}
+
+CXFA_TabParam::~CXFA_TabParam() {}