| // 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/include/xfa_ffpageview.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/include/xfa_ffdoc.h" |
| #include "xfa/fxfa/include/xfa_ffdocview.h" |
| #include "xfa/fxfa/include/xfa_ffwidget.h" |
| |
| namespace { |
| |
| void GetPageMatrix(CFX_Matrix& pageMatrix, |
| const CFX_RectF& docPageRect, |
| const CFX_Rect& devicePageRect, |
| int32_t iRotate, |
| uint32_t dwCoordinatesType) { |
| ASSERT(iRotate >= 0 && iRotate <= 3); |
| FX_BOOL bFlipX = (dwCoordinatesType & 0x01) != 0; |
| FX_BOOL bFlipY = (dwCoordinatesType & 0x02) != 0; |
| CFX_Matrix m; |
| m.Set((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0); |
| if (iRotate == 0 || iRotate == 2) { |
| m.a *= (FX_FLOAT)devicePageRect.width / docPageRect.width; |
| m.d *= (FX_FLOAT)devicePageRect.height / docPageRect.height; |
| } else { |
| m.a *= (FX_FLOAT)devicePageRect.height / docPageRect.width; |
| m.d *= (FX_FLOAT)devicePageRect.width / docPageRect.height; |
| } |
| m.Rotate(iRotate * 1.57079632675f); |
| switch (iRotate) { |
| case 0: |
| m.e = bFlipX ? (FX_FLOAT)devicePageRect.right() |
| : (FX_FLOAT)devicePageRect.left; |
| m.f = bFlipY ? (FX_FLOAT)devicePageRect.bottom() |
| : (FX_FLOAT)devicePageRect.top; |
| break; |
| case 1: |
| m.e = bFlipY ? (FX_FLOAT)devicePageRect.left |
| : (FX_FLOAT)devicePageRect.right(); |
| m.f = bFlipX ? (FX_FLOAT)devicePageRect.bottom() |
| : (FX_FLOAT)devicePageRect.top; |
| break; |
| case 2: |
| m.e = bFlipX ? (FX_FLOAT)devicePageRect.left |
| : (FX_FLOAT)devicePageRect.right(); |
| m.f = bFlipY ? (FX_FLOAT)devicePageRect.top |
| : (FX_FLOAT)devicePageRect.bottom(); |
| break; |
| case 3: |
| m.e = bFlipY ? (FX_FLOAT)devicePageRect.right() |
| : (FX_FLOAT)devicePageRect.left; |
| m.f = bFlipX ? (FX_FLOAT)devicePageRect.top |
| : (FX_FLOAT)devicePageRect.bottom(); |
| break; |
| default: |
| break; |
| } |
| pageMatrix = m; |
| } |
| |
| bool PageWidgetFilter(CXFA_FFWidget* pWidget, |
| uint32_t dwFilter, |
| FX_BOOL bTraversal, |
| FX_BOOL bIgnorerelevant) { |
| CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc(); |
| |
| if (!!(dwFilter & XFA_WidgetStatus_Focused) && |
| pWidgetAcc->GetClassID() != 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; |
| } |
| |
| } // 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; |
| } |
| |
| int32_t CXFA_FFPageView::GetPageViewIndex() const { |
| return GetPageIndex(); |
| } |
| |
| void CXFA_FFPageView::GetPageViewRect(CFX_RectF& rtPage) const { |
| CFX_SizeF sz; |
| GetPageSize(sz); |
| rtPage.Set(0, 0, sz); |
| } |
| void CXFA_FFPageView::GetDisplayMatrix(CFX_Matrix& mt, |
| const CFX_Rect& rtDisp, |
| int32_t iRotate) const { |
| CFX_SizeF sz; |
| GetPageSize(sz); |
| CFX_RectF fdePage; |
| fdePage.Set(0, 0, sz.x, sz.y); |
| GetPageMatrix(mt, fdePage, 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.Init(pPageView); |
| m_bIgnorerelevant = ((CXFA_FFDoc*)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 NULL; |
| } |
| CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() { |
| m_sIterator.SetCurrent(NULL); |
| 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 NULL; |
| } |
| 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 NULL; |
| } |
| CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() { |
| CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); |
| return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : NULL; |
| } |
| FX_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 NULL; |
| } |
| if (!pWidget->IsLoaded() && |
| (pWidget->GetStatus() & XFA_WidgetStatus_Visible) != 0) { |
| pWidget->LoadWidget(); |
| } |
| return pWidget; |
| } |
| return NULL; |
| } |
| |
| CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator( |
| CXFA_FFPageView* pPageView, |
| uint32_t dwFilter) |
| : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) { |
| m_bIgnorerelevant = ((CXFA_FFDoc*)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() { |
| if (m_TabOrderWidgetArray.GetSize() > 0) { |
| for (int32_t i = 0; i < m_TabOrderWidgetArray.GetSize(); i++) { |
| if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, |
| m_bIgnorerelevant)) { |
| m_iCurWidget = i; |
| return m_TabOrderWidgetArray[m_iCurWidget]; |
| } |
| } |
| } |
| return NULL; |
| } |
| CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() { |
| if (m_TabOrderWidgetArray.GetSize() > 0) { |
| for (int32_t i = m_TabOrderWidgetArray.GetSize() - 1; i >= 0; i--) { |
| if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, |
| m_bIgnorerelevant)) { |
| m_iCurWidget = i; |
| return m_TabOrderWidgetArray[m_iCurWidget]; |
| } |
| } |
| } |
| return NULL; |
| } |
| CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() { |
| for (int32_t i = m_iCurWidget + 1; i < m_TabOrderWidgetArray.GetSize(); i++) { |
| if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, |
| m_bIgnorerelevant)) { |
| m_iCurWidget = i; |
| return m_TabOrderWidgetArray[m_iCurWidget]; |
| } |
| } |
| m_iCurWidget = -1; |
| return NULL; |
| } |
| 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 NULL; |
| } |
| CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() { |
| if (m_iCurWidget >= 0) { |
| return m_TabOrderWidgetArray[m_iCurWidget]; |
| } |
| return NULL; |
| } |
| FX_BOOL CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget( |
| CXFA_FFWidget* hWidget) { |
| int32_t iWidgetIndex = m_TabOrderWidgetArray.Find(hWidget); |
| if (iWidgetIndex >= 0) { |
| m_iCurWidget = iWidgetIndex; |
| return TRUE; |
| } |
| return FALSE; |
| } |
| 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 NULL; |
| } |
| CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName( |
| const CFX_WideString& wsWidgetName, |
| CXFA_FFWidget* pRefWidget) { |
| return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget); |
| } |
| void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() { |
| m_TabOrderWidgetArray.RemoveAll(); |
| CXFA_WidgetArray SpaceOrderWidgetArray; |
| CreateSpaceOrderWidgetArray(SpaceOrderWidgetArray); |
| int32_t nWidgetCount = SpaceOrderWidgetArray.GetSize(); |
| if (nWidgetCount < 1) { |
| return; |
| } |
| CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0]; |
| for (; m_TabOrderWidgetArray.GetSize() < nWidgetCount;) { |
| if (m_TabOrderWidgetArray.Find(hWidget) < 0) { |
| m_TabOrderWidgetArray.Add(hWidget); |
| CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); |
| if (pWidgetAcc->GetUIType() == XFA_ELEMENT_ExclGroup) { |
| int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget) + 1; |
| while (TRUE) { |
| CXFA_FFWidget* pRadio = |
| SpaceOrderWidgetArray[(iWidgetIndex) % nWidgetCount]; |
| if (pRadio->GetDataAcc()->GetExclGroup() != pWidgetAcc) { |
| break; |
| } |
| if (m_TabOrderWidgetArray.Find(hWidget) < 0) { |
| m_TabOrderWidgetArray.Add(pRadio); |
| } |
| iWidgetIndex++; |
| } |
| } |
| if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) { |
| hWidget = hTraverseWidget; |
| continue; |
| } |
| } |
| int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget); |
| hWidget = SpaceOrderWidgetArray[(iWidgetIndex + 1) % nWidgetCount]; |
| } |
| } |
| static int32_t XFA_TabOrderWidgetComparator(const void* phWidget1, |
| const void* phWidget2) { |
| CXFA_FFWidget* pWidget1 = (*(CXFA_TabParam**)phWidget1)->m_pWidget; |
| CXFA_FFWidget* pWidget2 = (*(CXFA_TabParam**)phWidget2)->m_pWidget; |
| CFX_RectF rt1, rt2; |
| pWidget1->GetWidgetRect(rt1); |
| pWidget2->GetWidgetRect(rt2); |
| FX_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, |
| FX_BOOL& bCurrentItem, |
| FX_BOOL& bContentArea, |
| FX_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 (XFA_IsLayoutElement(pSearchItem->GetFormNode()->GetClassID(), 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++) { |
| CXFA_TabParam* pParam = tabParams[iStart]; |
| pContainer->m_Children.Add(pParam->m_pWidget); |
| if (pParam->m_Children.GetSize() > 0) { |
| pContainer->m_Children.Append(pParam->m_Children); |
| } |
| delete pParam; |
| } |
| tabParams.RemoveAll(); |
| } |
| void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray( |
| CXFA_WidgetArray& WidgetArray) { |
| CXFA_LayoutItemIterator sIterator; |
| sIterator.Init(m_pPageView); |
| CXFA_TabParam* pParam = new CXFA_TabParam; |
| FX_BOOL bCurrentItem = FALSE; |
| FX_BOOL bContentArea = FALSE; |
| OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea); |
| if (pParam->m_Children.GetSize() > 0) { |
| WidgetArray.Append(pParam->m_Children); |
| } |
| sIterator.Reset(); |
| bCurrentItem = FALSE; |
| bContentArea = FALSE; |
| pParam->m_Children.RemoveAll(); |
| OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea, TRUE); |
| if (pParam->m_Children.GetSize() > 0) { |
| WidgetArray.Append(pParam->m_Children); |
| } |
| delete pParam; |
| } |
| 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 NULL; |
| } |