// 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/parser/xfa_script_layoutpseudomodel.h" #include "xfa/fxfa/app/xfa_ffnotify.h" #include "xfa/fxfa/fm2js/xfa_fm2jsapi.h" #include "xfa/fxfa/parser/xfa_doclayout.h" #include "xfa/fxfa/parser/xfa_document.h" #include "xfa/fxfa/parser/xfa_document_layout_imp.h" #include "xfa/fxfa/parser/xfa_layout_appadapter.h" #include "xfa/fxfa/parser/xfa_localemgr.h" #include "xfa/fxfa/parser/xfa_object.h" #include "xfa/fxfa/parser/xfa_parser.h" #include "xfa/fxfa/parser/xfa_parser_imp.h" #include "xfa/fxfa/parser/xfa_script.h" #include "xfa/fxfa/parser/xfa_script_imp.h" #include "xfa/fxfa/parser/xfa_utils.h" #include "xfa/fxjse/cfxjse_arguments.h" CScript_LayoutPseudoModel::CScript_LayoutPseudoModel(CXFA_Document* pDocument) : CXFA_OrdinaryObject(pDocument, XFA_ELEMENT_LayoutPseudoModel) { m_uScriptHash = XFA_HASHCODE_Layout; } CScript_LayoutPseudoModel::~CScript_LayoutPseudoModel() {} void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_Ready( FXJSE_HVALUE hValue, FX_BOOL bSetting, XFA_ATTRIBUTE eAttribute) { CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } if (bSetting) { ThrowScriptErrorMessage(XFA_IDS_UNABLE_SET_READY); return; } int32_t iStatus = pNotify->GetLayoutStatus(); FXJSE_Value_SetBoolean(hValue, iStatus >= 2); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_HWXY( CFXJSE_Arguments* pArguments, XFA_LAYOUTMODEL_HWXY layoutModel) { int32_t iLength = pArguments->GetLength(); if (iLength < 1 || iLength > 3) { const FX_WCHAR* methodName = NULL; switch (layoutModel) { case XFA_LAYOUTMODEL_H: methodName = L"h"; break; case XFA_LAYOUTMODEL_W: methodName = L"w"; break; case XFA_LAYOUTMODEL_X: methodName = L"x"; break; case XFA_LAYOUTMODEL_Y: methodName = L"y"; break; } ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, methodName); return; } CXFA_Node* pNode = NULL; CFX_WideString wsUnit = FX_WSTRC(L"pt"); int32_t iIndex = 0; if (iLength >= 1) { pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); } if (iLength >= 2) { CFX_ByteString bsUnit = pArguments->GetUTF8String(1); if (!bsUnit.IsEmpty()) { wsUnit = CFX_WideString::FromUTF8(bsUnit.AsStringC()); } } if (iLength >= 3) { iIndex = pArguments->GetInt32(2); } if (!pNode) { return; } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } CFX_RectF rtRect; CXFA_Measurement measure; CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); if (!pLayoutItem) { return; } while (iIndex > 0 && pLayoutItem) { pLayoutItem = pLayoutItem->GetNext(); iIndex--; } FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (!pLayoutItem) { FXJSE_Value_SetFloat(hValue, 0); return; } pLayoutItem->GetRect(rtRect, TRUE); switch (layoutModel) { case XFA_LAYOUTMODEL_H: measure.Set(rtRect.height, XFA_UNIT_Pt); break; case XFA_LAYOUTMODEL_W: measure.Set(rtRect.width, XFA_UNIT_Pt); break; case XFA_LAYOUTMODEL_X: measure.Set(rtRect.left, XFA_UNIT_Pt); break; case XFA_LAYOUTMODEL_Y: measure.Set(rtRect.top, XFA_UNIT_Pt); break; } XFA_UNIT unit = measure.GetUnit(wsUnit.AsStringC()); FX_FLOAT fValue = measure.ToUnit(unit); fValue = FXSYS_round(fValue * 1000) / 1000.0f; if (hValue) { FXJSE_Value_SetFloat(hValue, fValue); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_H( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_HWXY(pArguments, XFA_LAYOUTMODEL_H); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_W( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_HWXY(pArguments, XFA_LAYOUTMODEL_W); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_X( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_HWXY(pArguments, XFA_LAYOUTMODEL_X); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_Y( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_HWXY(pArguments, XFA_LAYOUTMODEL_Y); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_NumberedPageCount( CFXJSE_Arguments* pArguments, FX_BOOL bNumbered) { CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } int32_t iPageCount = 0; int32_t iPageNum = pDocLayout->CountPages(); if (bNumbered) { for (int32_t i = 0; i < iPageNum; i++) { CXFA_ContainerLayoutItem* pLayoutPage = pDocLayout->GetPage(i); if (!pLayoutPage) { continue; } CXFA_Node* pMasterPage = pLayoutPage->GetMasterPage(); if (pMasterPage->GetInteger(XFA_ATTRIBUTE_Numbered)) { iPageCount++; } } } else { iPageCount = iPageNum; } FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (hValue) { FXJSE_Value_SetInteger(hValue, iPageCount); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_PageCount( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_NumberedPageCount(pArguments, TRUE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_PageSpan( CFXJSE_Arguments* pArguments) { int32_t iLength = pArguments->GetLength(); if (iLength != 1) { ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"pageSpan"); return; } CXFA_Node* pNode = NULL; if (iLength >= 1) { pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); } if (!pNode) { return; } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } FXJSE_HVALUE hValue = pArguments->GetReturnValue(); CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); if (!pLayoutItem) { FXJSE_Value_SetInteger(hValue, -1); return; } int32_t iLast = pLayoutItem->GetLast()->GetPage()->GetPageIndex(); int32_t iFirst = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); int32_t iPageSpan = iLast - iFirst + 1; if (hValue) { FXJSE_Value_SetInteger(hValue, iPageSpan); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_Page( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_PageImp(pArguments, FALSE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_GetObjArray( CXFA_LayoutProcessor* pDocLayout, int32_t iPageNo, const CFX_WideString& wsType, FX_BOOL bOnPageArea, CXFA_NodeArray& retArray) { CXFA_ContainerLayoutItem* pLayoutPage = (CXFA_ContainerLayoutItem*)pDocLayout->GetPage(iPageNo); if (!pLayoutPage) { return; } if (wsType == FX_WSTRC(L"pageArea")) { if (CXFA_Node* pMasterPage = pLayoutPage->m_pFormNode) { retArray.Add(pMasterPage); } return; } if (wsType == FX_WSTRC(L"contentArea")) { for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; pItem = pItem->m_pNextSibling) { if (pItem->m_pFormNode->GetClassID() == XFA_ELEMENT_ContentArea) { retArray.Add(pItem->m_pFormNode); } } return; } CFX_MapPtrToPtr formItems; formItems.InitHashTable(256, TRUE); if (wsType.IsEmpty()) { if (CXFA_Node* pMasterPage = pLayoutPage->m_pFormNode) { retArray.Add(pMasterPage); } for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; pItem = pItem->m_pNextSibling) { if (pItem->m_pFormNode->GetClassID() == XFA_ELEMENT_ContentArea) { retArray.Add(pItem->m_pFormNode); if (!bOnPageArea) { CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, CXFA_TraverseStrategy_ContentLayoutItem> iterator((CXFA_ContentLayoutItem*)pItem->m_pFirstChild); for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); pItemChild; pItemChild = iterator.MoveToNext()) { if (!pItemChild->IsContentLayoutItem()) { continue; } XFA_ELEMENT eElementType = pItemChild->m_pFormNode->GetClassID(); if (eElementType != XFA_ELEMENT_Field && eElementType != XFA_ELEMENT_Draw && eElementType != XFA_ELEMENT_Subform && eElementType != XFA_ELEMENT_Area) { continue; } if (formItems.GetValueAt(pItemChild->m_pFormNode)) { continue; } formItems.SetAt(pItemChild->m_pFormNode, this); retArray.Add(pItemChild->m_pFormNode); } } } else { if (bOnPageArea) { CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, CXFA_TraverseStrategy_ContentLayoutItem> iterator((CXFA_ContentLayoutItem*)pItem); for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); pItemChild; pItemChild = iterator.MoveToNext()) { if (!pItemChild->IsContentLayoutItem()) { continue; } XFA_ELEMENT eElementType = pItemChild->m_pFormNode->GetClassID(); if (eElementType != XFA_ELEMENT_Field && eElementType != XFA_ELEMENT_Draw && eElementType != XFA_ELEMENT_Subform && eElementType != XFA_ELEMENT_Area) { continue; } if (formItems.GetValueAt(pItemChild->m_pFormNode)) { continue; } formItems.SetAt(pItemChild->m_pFormNode, this); retArray.Add(pItemChild->m_pFormNode); } } } } return; } XFA_ELEMENT eType = XFA_ELEMENT_UNKNOWN; if (wsType == FX_WSTRC(L"field")) { eType = XFA_ELEMENT_Field; } else if (wsType == FX_WSTRC(L"draw")) { eType = XFA_ELEMENT_Draw; } else if (wsType == FX_WSTRC(L"subform")) { eType = XFA_ELEMENT_Subform; } else if (wsType == FX_WSTRC(L"area")) { eType = XFA_ELEMENT_Area; } if (eType != XFA_ELEMENT_UNKNOWN) { for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; pItem = pItem->m_pNextSibling) { if (pItem->m_pFormNode->GetClassID() == XFA_ELEMENT_ContentArea) { if (!bOnPageArea) { CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, CXFA_TraverseStrategy_ContentLayoutItem> iterator((CXFA_ContentLayoutItem*)pItem->m_pFirstChild); for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); pItemChild; pItemChild = iterator.MoveToNext()) { if (!pItemChild->IsContentLayoutItem()) { continue; } if (pItemChild->m_pFormNode->GetClassID() != eType) { continue; } if (formItems.GetValueAt(pItemChild->m_pFormNode)) { continue; } formItems.SetAt(pItemChild->m_pFormNode, this); retArray.Add(pItemChild->m_pFormNode); } } } else { if (bOnPageArea) { CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, CXFA_TraverseStrategy_ContentLayoutItem> iterator((CXFA_ContentLayoutItem*)pItem); for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); pItemChild; pItemChild = iterator.MoveToNext()) { if (!pItemChild->IsContentLayoutItem()) { continue; } if (pItemChild->m_pFormNode->GetClassID() != eType) { continue; } if (formItems.GetValueAt(pItemChild->m_pFormNode)) { continue; } formItems.SetAt(pItemChild->m_pFormNode, this); retArray.Add(pItemChild->m_pFormNode); } } } } return; } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_PageContent( CFXJSE_Arguments* pArguments) { int32_t iLength = pArguments->GetLength(); if (iLength < 1 || iLength > 3) { ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"pageContent"); return; } int32_t iIndex = 0; CFX_WideString wsType; FX_BOOL bOnPageArea = FALSE; if (iLength >= 1) { iIndex = pArguments->GetInt32(0); } if (iLength >= 2) { CFX_ByteString bsType = pArguments->GetUTF8String(1); wsType = CFX_WideString::FromUTF8(bsType.AsStringC()); } if (iLength >= 3) { bOnPageArea = pArguments->GetInt32(2) == 0 ? FALSE : TRUE; } CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } CXFA_NodeArray retArray; Script_LayoutPseudoModel_GetObjArray(pDocLayout, iIndex, wsType, bOnPageArea, retArray); CXFA_ArrayNodeList* pArrayNodeList = new CXFA_ArrayNodeList(m_pDocument); pArrayNodeList->SetArrayNodeList(retArray); FXJSE_Value_SetObject(pArguments->GetReturnValue(), (CXFA_Object*)pArrayNodeList, m_pDocument->GetScriptContext()->GetJseNormalClass()); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_AbsPageCount( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_NumberedPageCount(pArguments, FALSE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_AbsPageCountInBatch( CFXJSE_Arguments* pArguments) { CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } CXFA_FFDoc* hDoc = pNotify->GetHDOC(); int32_t iPageCount = pNotify->GetDocProvider()->AbsPageCountInBatch(hDoc); FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (hValue) { FXJSE_Value_SetInteger(hValue, iPageCount); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_SheetCountInBatch( CFXJSE_Arguments* pArguments) { CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } CXFA_FFDoc* hDoc = pNotify->GetHDOC(); int32_t iPageCount = pNotify->GetDocProvider()->SheetCountInBatch(hDoc); FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (hValue) { FXJSE_Value_SetInteger(hValue, iPageCount); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_Relayout( CFXJSE_Arguments* pArguments) { CXFA_Node* pRootNode = m_pDocument->GetRoot(); CXFA_Node* pFormRoot = pRootNode->GetFirstChildByClass(XFA_ELEMENT_Form); ASSERT(pFormRoot); CXFA_Node* pContentRootNode = pFormRoot->GetNodeItem(XFA_NODEITEM_FirstChild); CXFA_LayoutProcessor* pLayoutProcessor = m_pDocument->GetLayoutProcessor(); if (pContentRootNode) { pLayoutProcessor->AddChangedContainer(pContentRootNode); } pLayoutProcessor->SetForceReLayout(TRUE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_AbsPageSpan( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_PageSpan(pArguments); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_AbsPageInBatch( CFXJSE_Arguments* pArguments) { int32_t iLength = pArguments->GetLength(); if (iLength != 1) { ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"absPageInBatch"); return; } CXFA_Node* pNode = NULL; if (iLength >= 1) { pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); } if (!pNode) { return; } CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } CXFA_FFWidget* hWidget = pNotify->GetHWidget(pDocLayout->GetLayoutItem(pNode)); if (!hWidget) { return; } CXFA_FFDoc* hDoc = pNotify->GetHDOC(); int32_t iPageCount = pNotify->GetDocProvider()->AbsPageInBatch(hDoc, hWidget); FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (hValue) { FXJSE_Value_SetInteger(hValue, iPageCount); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_SheetInBatch( CFXJSE_Arguments* pArguments) { int32_t iLength = pArguments->GetLength(); if (iLength != 1) { ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"sheetInBatch"); return; } CXFA_Node* pNode = NULL; if (iLength >= 1) { pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); } if (!pNode) { return; } CXFA_FFNotify* pNotify = m_pDocument->GetParser()->GetNotify(); if (!pNotify) { return; } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } CXFA_FFWidget* hWidget = pNotify->GetHWidget(pDocLayout->GetLayoutItem(pNode)); if (!hWidget) { return; } CXFA_FFDoc* hDoc = pNotify->GetHDOC(); int32_t iPageCount = pNotify->GetDocProvider()->SheetInBatch(hDoc, hWidget); FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (hValue) { FXJSE_Value_SetInteger(hValue, iPageCount); } } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_Sheet( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_PageImp(pArguments, TRUE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_RelayoutPageArea( CFXJSE_Arguments* pArguments) {} void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_SheetCount( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_NumberedPageCount(pArguments, FALSE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_AbsPage( CFXJSE_Arguments* pArguments) { Script_LayoutPseudoModel_PageImp(pArguments, TRUE); } void CScript_LayoutPseudoModel::Script_LayoutPseudoModel_PageImp( CFXJSE_Arguments* pArguments, FX_BOOL bAbsPage) { int32_t iLength = pArguments->GetLength(); if (iLength != 1) { const FX_WCHAR* methodName; if (bAbsPage) { methodName = L"absPage"; } else { methodName = L"page"; } ThrowScriptErrorMessage(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, methodName); return; } CXFA_Node* pNode = NULL; if (iLength >= 1) { pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); } int32_t iPage = 0; FXJSE_HVALUE hValue = pArguments->GetReturnValue(); if (!pNode && hValue) { FXJSE_Value_SetInteger(hValue, iPage); } CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); if (!pDocLayout) { return; } CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); if (!pLayoutItem) { FXJSE_Value_SetInteger(hValue, -1); return; } iPage = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); if (hValue) { FXJSE_Value_SetInteger(hValue, bAbsPage ? iPage : iPage + 1); } }