// 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_layout_pagemgr_new.h" #include "xfa/fxfa/app/xfa_ffnotify.h" #include "xfa/fxfa/fm2js/xfa_fm2jsapi.h" #include "xfa/fxfa/parser/xfa_docdata.h" #include "xfa/fxfa/parser/xfa_doclayout.h" #include "xfa/fxfa/parser/xfa_document.h" #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h" #include "xfa/fxfa/parser/xfa_document_layout_imp.h" #include "xfa/fxfa/parser/xfa_layout_appadapter.h" #include "xfa/fxfa/parser/xfa_layout_itemlayout.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" CXFA_LayoutPageMgr::CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor) : m_pLayoutProcessor(pLayoutProcessor), m_pTemplatePageSetRoot(nullptr), m_pPageSetLayoutItemRoot(nullptr), m_pPageSetCurRoot(nullptr), m_pCurrentContainerRecord(nullptr), m_pCurPageArea(nullptr), m_nAvailPages(0), m_nCurPageCount(0), m_ePageSetMode(XFA_ATTRIBUTEENUM_OrderedOccurrence), m_bCreateOverFlowPage(FALSE) {} CXFA_LayoutPageMgr::~CXFA_LayoutPageMgr() { ClearData(); CXFA_LayoutItem* pLayoutItem = GetRootLayoutItem(); CXFA_LayoutItem* pNextLayout = NULL; for (; pLayoutItem; pLayoutItem = pNextLayout) { pNextLayout = pLayoutItem->m_pNextSibling; XFA_ReleaseLayoutItem(pLayoutItem); } } FX_BOOL CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) { PrepareLayout(); CXFA_Node* pTemplateNode = pFormNode->GetTemplateNode(); if (!pTemplateNode) { return FALSE; } m_pTemplatePageSetRoot = pTemplateNode->GetProperty(0, XFA_ELEMENT_PageSet); ASSERT(m_pTemplatePageSetRoot); if (m_pPageSetLayoutItemRoot) { m_pPageSetLayoutItemRoot->m_pParent = NULL; m_pPageSetLayoutItemRoot->m_pFirstChild = NULL; m_pPageSetLayoutItemRoot->m_pNextSibling = NULL; m_pPageSetLayoutItemRoot->m_pFormNode = m_pTemplatePageSetRoot; } else { m_pPageSetLayoutItemRoot = new CXFA_ContainerLayoutItem(m_pTemplatePageSetRoot); } m_pPageSetCurRoot = m_pPageSetLayoutItemRoot; m_pTemplatePageSetRoot->SetUserData(XFA_LAYOUTITEMKEY, (void*)m_pPageSetLayoutItemRoot); XFA_ATTRIBUTEENUM eRelation = m_pTemplatePageSetRoot->GetEnum(XFA_ATTRIBUTE_Relation); if (eRelation != XFA_ATTRIBUTEENUM_Unknown) { m_ePageSetMode = eRelation; } InitPageSetMap(); CXFA_Node* pPageArea = NULL; int32_t iCount = 0; for (pPageArea = m_pTemplatePageSetRoot->GetNodeItem(XFA_NODEITEM_FirstChild); pPageArea; pPageArea = pPageArea->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pPageArea->GetClassID() == XFA_ELEMENT_PageArea) { iCount++; if (pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea)) { return TRUE; } } } if (iCount > 0) { return FALSE; } CXFA_Document* pDocument = pTemplateNode->GetDocument(); CXFA_Document* pObjFactory = pDocument->GetParser()->GetFactory(); pPageArea = m_pTemplatePageSetRoot->GetChild(0, XFA_ELEMENT_PageArea); if (!pPageArea) { pPageArea = pObjFactory->CreateNode(m_pTemplatePageSetRoot->GetPacketID(), XFA_ELEMENT_PageArea); if (!pPageArea) { return FALSE; } m_pTemplatePageSetRoot->InsertChild(pPageArea, NULL); pPageArea->SetFlag(XFA_NODEFLAG_Initialized); } CXFA_Node* pContentArea = pPageArea->GetChild(0, XFA_ELEMENT_ContentArea); if (!pContentArea) { pContentArea = pObjFactory->CreateNode(pPageArea->GetPacketID(), XFA_ELEMENT_ContentArea); if (!pContentArea) { return FALSE; } pPageArea->InsertChild(pContentArea, NULL); pContentArea->SetFlag(XFA_NODEFLAG_Initialized); pContentArea->SetMeasure(XFA_ATTRIBUTE_X, CXFA_Measurement(0.25f, XFA_UNIT_In)); pContentArea->SetMeasure(XFA_ATTRIBUTE_Y, CXFA_Measurement(0.25f, XFA_UNIT_In)); pContentArea->SetMeasure(XFA_ATTRIBUTE_W, CXFA_Measurement(8.0f, XFA_UNIT_In)); pContentArea->SetMeasure(XFA_ATTRIBUTE_H, CXFA_Measurement(10.5f, XFA_UNIT_In)); } CXFA_Node* pMedium = pPageArea->GetChild(0, XFA_ELEMENT_Medium); if (!pMedium) { pMedium = pObjFactory->CreateNode(pPageArea->GetPacketID(), XFA_ELEMENT_Medium); if (!pContentArea) { return FALSE; } pPageArea->InsertChild(pMedium, NULL); pMedium->SetFlag(XFA_NODEFLAG_Initialized); pMedium->SetMeasure(XFA_ATTRIBUTE_Short, CXFA_Measurement(8.5f, XFA_UNIT_In)); pMedium->SetMeasure(XFA_ATTRIBUTE_Long, CXFA_Measurement(11.0f, XFA_UNIT_In)); } return TRUE; } FX_BOOL CXFA_LayoutPageMgr::PrepareFirstPage(CXFA_Node* pRootSubform) { FX_BOOL bProBreakBefore = FALSE; CXFA_Node* pBreakBeforeNode = NULL; while (pRootSubform) { for (CXFA_Node* pBreakNode = pRootSubform->GetNodeItem(XFA_NODEITEM_FirstChild); pBreakNode; pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { XFA_ELEMENT eType = pBreakNode->GetClassID(); if (eType == XFA_ELEMENT_BreakBefore || (eType == XFA_ELEMENT_Break && pBreakNode->GetEnum(XFA_ATTRIBUTE_Before) != XFA_ATTRIBUTEENUM_Auto)) { bProBreakBefore = TRUE; pBreakBeforeNode = pBreakNode; break; } } if (bProBreakBefore) { break; } bProBreakBefore = TRUE; pRootSubform = pRootSubform->GetFirstChildByClass(XFA_ELEMENT_Subform); while (pRootSubform && !XFA_ItemLayoutProcessor_IsTakingSpace(pRootSubform)) { pRootSubform = pRootSubform->GetNextSameClassSibling(XFA_ELEMENT_Subform); } } CXFA_Node *pLeader, *pTrailer; if (pBreakBeforeNode && ExecuteBreakBeforeOrAfter(pBreakBeforeNode, TRUE, pLeader, pTrailer)) { m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition(); return TRUE; } return AppendNewPage(TRUE); } FX_BOOL CXFA_LayoutPageMgr::AppendNewPage(FX_BOOL bFirstTemPage) { if (m_pCurrentContainerRecord != m_rgProposedContainerRecord.GetTailPosition()) { return TRUE; } CXFA_Node* pPageNode = GetNextAvailPageArea(NULL); if (!pPageNode) { return FALSE; } if (bFirstTemPage && m_pCurrentContainerRecord == NULL) { m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition(); } return !bFirstTemPage || m_pCurrentContainerRecord; } static void XFA_LayoutItemMgr_ReorderLayoutItemToTail( CXFA_ContainerLayoutItem* pLayoutItem) { CXFA_ContainerLayoutItem* pParentLayoutItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent; if (!pParentLayoutItem) { return; } pParentLayoutItem->RemoveChild(pLayoutItem); pParentLayoutItem->AddChild(pLayoutItem); } static void XFA_LayoutItemMgr_RemoveLayoutItem( CXFA_ContainerLayoutItem* pLayoutItem) { CXFA_ContainerLayoutItem* pParentLayoutItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent; if (!pParentLayoutItem) { return; } pParentLayoutItem->RemoveChild(pLayoutItem); } void CXFA_LayoutPageMgr::RemoveLayoutRecord(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord) { if (!pNewRecord || !pPrevRecord) { return; } if (pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) { XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageSet); return; } if (pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) { XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageArea); return; } if (pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) { XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurContentArea); return; } } void CXFA_LayoutPageMgr::ReorderPendingLayoutRecordToTail( CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord) { if (!pNewRecord || !pPrevRecord) { return; } if (pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) { XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageSet); return; } if (pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) { XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageArea); return; } if (pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) { XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurContentArea); return; } } void CXFA_LayoutPageMgr::SubmitContentItem( CXFA_ContentLayoutItem* pContentLayoutItem, XFA_ItemLayoutProcessorResult eStatus) { if (pContentLayoutItem) { GetCurrentContainerRecord()->pCurContentArea->AddChild(pContentLayoutItem); m_bCreateOverFlowPage = FALSE; } if (eStatus != XFA_ItemLayoutProcessorResult_Done) { if (eStatus == XFA_ItemLayoutProcessorResult_PageFullBreak && m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetTailPosition()) { AppendNewPage(); } m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetTailPosition(); m_pCurPageArea = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode; } } FX_FLOAT CXFA_LayoutPageMgr::GetAvailHeight() { CXFA_ContainerLayoutItem* pLayoutItem = GetCurrentContainerRecord()->pCurContentArea; if (!pLayoutItem || !pLayoutItem->m_pFormNode) return 0.0f; FX_FLOAT fAvailHeight = pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); if (fAvailHeight >= XFA_LAYOUT_FLOAT_PERCISION) return fAvailHeight; if (m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetHeadPosition()) { return 0.0f; } return XFA_LAYOUT_FLOAT_MAX; } static CXFA_Node* XFA_ResolveBreakTarget(CXFA_Node* pPageSetRoot, FX_BOOL bNewExprStyle, CFX_WideStringC& wsTargetExpr) { CXFA_Document* pDocument = pPageSetRoot->GetDocument(); if (wsTargetExpr.IsEmpty()) { return NULL; } CFX_WideString wsTargetAll = wsTargetExpr; wsTargetAll.TrimLeft(); wsTargetAll.TrimRight(); int32_t iSpliteIndex = 0; FX_BOOL bTargetAllFind = TRUE; while (iSpliteIndex != -1) { CFX_WideString wsTargetExpr; int32_t iSpliteNextIndex = 0; if (!bTargetAllFind) { iSpliteNextIndex = wsTargetAll.Find(' ', iSpliteIndex); wsTargetExpr = wsTargetAll.Mid(iSpliteIndex, iSpliteNextIndex - iSpliteIndex); } else { wsTargetExpr = wsTargetAll; } if (wsTargetExpr.IsEmpty()) { return NULL; } bTargetAllFind = FALSE; if (wsTargetExpr.GetAt(0) == '#') { CXFA_Node* pNode = pDocument->GetNodeByID( ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Template)), wsTargetExpr.Mid(1).AsStringC()); if (pNode) { return pNode; } } else if (bNewExprStyle) { CFX_WideString wsProcessedTarget = wsTargetExpr; if (wsTargetExpr.Left(4) == FX_WSTRC(L"som(") && wsTargetExpr.Right(1) == FX_WSTRC(L")")) { wsProcessedTarget = wsTargetExpr.Mid(4, wsTargetExpr.GetLength() - 5); } XFA_RESOLVENODE_RS rs; int32_t iCount = pDocument->GetScriptContext()->ResolveObjects( pPageSetRoot, wsProcessedTarget.AsStringC(), rs, XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent); if (iCount > 0 && rs.nodes[0]->IsNode()) { return rs.nodes[0]->AsNode(); } } iSpliteIndex = iSpliteNextIndex; } return NULL; } FX_BOOL XFA_LayoutPageMgr_RunBreakTestScript(CXFA_Node* pTestScript) { CFX_WideString wsExpression; pTestScript->TryContent(wsExpression); if (wsExpression.IsEmpty()) { return TRUE; } return pTestScript->GetDocument()->GetParser()->GetNotify()->RunScript( pTestScript, pTestScript->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode)); } CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( CXFA_Node* pPageNode, FX_BOOL bCreateNew) { CXFA_ContainerRecord* pNewRecord = new CXFA_ContainerRecord(); if (m_pCurrentContainerRecord) { if (!IsPageSetRootOrderedOccurrence() || pPageNode == NULL) { *pNewRecord = *GetCurrentContainerRecord(); m_rgProposedContainerRecord.AddTail(pNewRecord); return pNewRecord; } CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent); if (!bCreateNew) { if (pPageSet == m_pTemplatePageSetRoot) { pNewRecord->pCurPageSet = m_pPageSetCurRoot; } else { CXFA_ContainerLayoutItem* pParentLayoutItem = (CXFA_ContainerLayoutItem*)pPageSet->GetUserData(XFA_LAYOUTITEMKEY); if (pParentLayoutItem == NULL) { pParentLayoutItem = m_pPageSetCurRoot; } pNewRecord->pCurPageSet = pParentLayoutItem; } } else { CXFA_ContainerLayoutItem* pParentPageSetLayout = NULL; if (pPageSet == GetCurrentContainerRecord()->pCurPageSet->m_pFormNode) { pParentPageSetLayout = (CXFA_ContainerLayoutItem*)GetCurrentContainerRecord() ->pCurPageSet->m_pParent; } else { pParentPageSetLayout = (CXFA_ContainerLayoutItem*)pPageSet->GetNodeItem( XFA_NODEITEM_Parent) ->GetUserData(XFA_LAYOUTITEMKEY); } CXFA_ContainerLayoutItem* pPageSetLayoutItem = new CXFA_ContainerLayoutItem(pPageSet); pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem); if (pParentPageSetLayout == NULL) { CXFA_ContainerLayoutItem* pPrePageSet = m_pPageSetLayoutItemRoot; while (pPrePageSet->m_pNextSibling) { pPrePageSet = (CXFA_ContainerLayoutItem*)pPrePageSet->m_pNextSibling; } pPrePageSet->m_pNextSibling = pPageSetLayoutItem; m_pPageSetCurRoot = pPageSetLayoutItem; } else { pParentPageSetLayout->AddChild(pPageSetLayoutItem); } pNewRecord->pCurPageSet = pPageSetLayoutItem; } } else { if (pPageNode) { CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent); if (pPageSet == m_pTemplatePageSetRoot) { pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot; } else { CXFA_ContainerLayoutItem* pPageSetLayoutItem = new CXFA_ContainerLayoutItem(pPageSet); pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem); m_pPageSetLayoutItemRoot->AddChild(pPageSetLayoutItem); pNewRecord->pCurPageSet = pPageSetLayoutItem; } } else { pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot; } } m_rgProposedContainerRecord.AddTail(pNewRecord); return pNewRecord; } void CXFA_LayoutPageMgr::AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pNewPageArea) { CXFA_ContainerLayoutItem* pNewPageAreaLayoutItem = NULL; if (m_PageArray.GetSize() > m_nAvailPages) { CXFA_ContainerLayoutItem* pContainerItem = m_PageArray[m_nAvailPages]; pContainerItem->m_pFormNode = pNewPageArea; m_nAvailPages++; pNewPageAreaLayoutItem = pContainerItem; } else { CXFA_FFNotify* pNotify = pNewPageArea->GetDocument()->GetParser()->GetNotify(); CXFA_ContainerLayoutItem* pContainerItem = (CXFA_ContainerLayoutItem*)pNotify->OnCreateLayoutItem(pNewPageArea); m_PageArray.Add(pContainerItem); m_nAvailPages++; pNotify->OnPageEvent(pContainerItem, XFA_PAGEEVENT_PageAdded, (void*)(uintptr_t)m_nAvailPages); pNewPageAreaLayoutItem = pContainerItem; } pNewRecord->pCurPageSet->AddChild(pNewPageAreaLayoutItem); pNewRecord->pCurPageArea = pNewPageAreaLayoutItem; pNewRecord->pCurContentArea = NULL; } void CXFA_LayoutPageMgr::AddContentAreaLayoutItem( CXFA_ContainerRecord* pNewRecord, CXFA_Node* pContentArea) { if (pContentArea == NULL) { pNewRecord->pCurContentArea = NULL; return; } CXFA_ContainerLayoutItem* pNewContentAreaLayoutItem = new CXFA_ContainerLayoutItem(pContentArea); ASSERT(pNewRecord->pCurPageArea); pNewRecord->pCurPageArea->AddChild(pNewContentAreaLayoutItem); pNewRecord->pCurContentArea = pNewContentAreaLayoutItem; } class CXFA_TraverseStrategy_PageSetContainerLayoutItem { public: static inline CXFA_ContainerLayoutItem* GetFirstChild( CXFA_ContainerLayoutItem* pLayoutItem) { if (pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet) { CXFA_ContainerLayoutItem* pChildItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pFirstChild; while (pChildItem && pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) { pChildItem = (CXFA_ContainerLayoutItem*)pChildItem->m_pNextSibling; } return pChildItem; } return NULL; } static inline CXFA_ContainerLayoutItem* GetNextSibling( CXFA_ContainerLayoutItem* pLayoutItem) { CXFA_ContainerLayoutItem* pChildItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pNextSibling; while (pChildItem && pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) { pChildItem = (CXFA_ContainerLayoutItem*)pChildItem->m_pNextSibling; } return pChildItem; } static inline CXFA_ContainerLayoutItem* GetParent( CXFA_ContainerLayoutItem* pLayoutItem) { return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent; } }; void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { CXFA_ContainerLayoutItem* pRootPageSetLayoutItem = m_pPageSetLayoutItemRoot; for (; pRootPageSetLayoutItem; pRootPageSetLayoutItem = (CXFA_ContainerLayoutItem*)pRootPageSetLayoutItem->m_pNextSibling) { CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItem, CXFA_TraverseStrategy_PageSetContainerLayoutItem> sIterator(pRootPageSetLayoutItem); for (CXFA_ContainerLayoutItem* pPageSetLayoutItem = sIterator.GetCurrent(); pPageSetLayoutItem; pPageSetLayoutItem = sIterator.MoveToNext()) { XFA_ATTRIBUTEENUM ePageRelation = pPageSetLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Relation); switch (ePageRelation) { case XFA_ATTRIBUTEENUM_OrderedOccurrence: default: { ProcessLastPageSet(); } break; case XFA_ATTRIBUTEENUM_SimplexPaginated: case XFA_ATTRIBUTEENUM_DuplexPaginated: { CXFA_LayoutItem* pLastPageAreaLayoutItem = NULL; int32_t nPageAreaCount = 0; for (CXFA_LayoutItem* pPageAreaLayoutItem = pPageSetLayoutItem->m_pFirstChild; pPageAreaLayoutItem; pPageAreaLayoutItem = pPageAreaLayoutItem->m_pNextSibling) { if (pPageAreaLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) { continue; } nPageAreaCount++; pLastPageAreaLayoutItem = pPageAreaLayoutItem; } if (!pLastPageAreaLayoutItem) { break; } if (!FindPageAreaFromPageSet_SimplexDuplex( pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE, TRUE, nPageAreaCount == 1 ? XFA_ATTRIBUTEENUM_Only : XFA_ATTRIBUTEENUM_Last) && (nPageAreaCount == 1 && !FindPageAreaFromPageSet_SimplexDuplex( pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE, TRUE, XFA_ATTRIBUTEENUM_Last))) { break; } CXFA_Node* pNode = m_pCurPageArea; XFA_ATTRIBUTEENUM eCurChoice = pNode->GetEnum(XFA_ATTRIBUTE_PagePosition); if (eCurChoice == XFA_ATTRIBUTEENUM_Last) { XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any; pNode->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven); XFA_ATTRIBUTEENUM eLastChoice = pLastPageAreaLayoutItem->m_pFormNode->GetEnum( XFA_ATTRIBUTE_PagePosition); if (eLastChoice == XFA_ATTRIBUTEENUM_First && (ePageRelation == XFA_ATTRIBUTEENUM_SimplexPaginated || eOddOrEven != XFA_ATTRIBUTEENUM_Odd)) { CXFA_ContainerRecord* pRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pRecord, pNode); break; } } FX_BOOL bUsable = TRUE; CFX_ArrayTemplate<FX_FLOAT> rgUsedHeights; for (CXFA_LayoutItem* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild; pChildLayoutItem; pChildLayoutItem = pChildLayoutItem->m_pNextSibling) { if (pChildLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_ContentArea) { continue; } FX_FLOAT fUsedHeight = 0; for (CXFA_LayoutItem* pContentChildLayoutItem = pChildLayoutItem->m_pFirstChild; pContentChildLayoutItem; pContentChildLayoutItem = pContentChildLayoutItem->m_pNextSibling) { if (CXFA_ContentLayoutItem* pContent = pContentChildLayoutItem->AsContentLayoutItem()) { fUsedHeight += pContent->m_sSize.y; } } rgUsedHeights.Add(fUsedHeight); } int32_t iCurContentAreaIndex = -1; for (CXFA_Node* pContentAreaNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); pContentAreaNode; pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) { continue; } iCurContentAreaIndex++; if (rgUsedHeights[iCurContentAreaIndex] > pContentAreaNode->GetMeasure(XFA_ATTRIBUTE_H) .ToUnit(XFA_UNIT_Pt) + XFA_LAYOUT_FLOAT_PERCISION) { bUsable = FALSE; break; } } if (bUsable) { CXFA_LayoutItem* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild; CXFA_Node* pContentAreaNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); pLastPageAreaLayoutItem->m_pFormNode = pNode; while (pChildLayoutItem && pContentAreaNode) { if (pChildLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_ContentArea) { pChildLayoutItem = pChildLayoutItem->m_pNextSibling; continue; } if (pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) { pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling); continue; } pChildLayoutItem->m_pFormNode = pContentAreaNode; pChildLayoutItem = pChildLayoutItem->m_pNextSibling; pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling); } } else if (pNode->GetEnum(XFA_ATTRIBUTE_PagePosition) == XFA_ATTRIBUTEENUM_Last) { CXFA_ContainerRecord* pRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pRecord, pNode); } } break; } } } } int32_t CXFA_LayoutPageMgr::GetPageCount() const { return m_PageArray.GetSize(); } CXFA_ContainerLayoutItem* CXFA_LayoutPageMgr::GetPage(int32_t index) const { if (index < 0 || index >= m_PageArray.GetSize()) return nullptr; return m_PageArray[index]; } int32_t CXFA_LayoutPageMgr::GetPageIndex( const CXFA_ContainerLayoutItem* pPage) const { // FIXME: Find() method should take const. return m_PageArray.Find(const_cast<CXFA_ContainerLayoutItem*>(pPage)); } FX_BOOL CXFA_LayoutPageMgr::RunBreak(XFA_ELEMENT eBreakType, XFA_ATTRIBUTEENUM eTargetType, CXFA_Node* pTarget, FX_BOOL bStartNew) { FX_BOOL bRet = FALSE; switch (eTargetType) { case XFA_ATTRIBUTEENUM_ContentArea: if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_ContentArea) { pTarget = NULL; } if (!pTarget || !m_pCurrentContainerRecord || pTarget != GetCurrentContainerRecord()->pCurContentArea->m_pFormNode || bStartNew) { CXFA_Node* pPageArea = NULL; if (pTarget) { pPageArea = pTarget->GetNodeItem(XFA_NODEITEM_Parent); } pPageArea = GetNextAvailPageArea(pPageArea, pTarget); bRet = pPageArea != NULL; } break; case XFA_ATTRIBUTEENUM_PageArea: if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) { pTarget = NULL; } if (!pTarget || !m_pCurrentContainerRecord || pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode || bStartNew) { CXFA_Node* pPageArea = GetNextAvailPageArea(pTarget, NULL, TRUE); bRet = pPageArea != NULL; } break; case XFA_ATTRIBUTEENUM_PageOdd: if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) { pTarget = NULL; } if (m_nAvailPages % 2 != 1 || !m_pCurrentContainerRecord || (pTarget && pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode) || bStartNew) { if (m_nAvailPages % 2 == 1) { } } break; case XFA_ATTRIBUTEENUM_PageEven: if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) { pTarget = NULL; } if (m_nAvailPages % 2 != 0 || !m_pCurrentContainerRecord || (pTarget && pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode) || bStartNew) { if (m_nAvailPages % 2 == 0) { } } break; case XFA_ATTRIBUTEENUM_Auto: default: break; } return bRet; } FX_BOOL CXFA_LayoutPageMgr::ExecuteBreakBeforeOrAfter( CXFA_Node* pCurNode, FX_BOOL bBefore, CXFA_Node*& pBreakLeaderTemplate, CXFA_Node*& pBreakTrailerTemplate) { XFA_ELEMENT eType = pCurNode->GetClassID(); switch (eType) { case XFA_ELEMENT_BreakBefore: case XFA_ELEMENT_BreakAfter: { CFX_WideStringC wsBreakLeader, wsBreakTrailer; CXFA_Node* pFormNode = pCurNode->GetNodeItem( XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); CXFA_Node* pContainer = pFormNode->GetTemplateNode(); FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0; CXFA_Node* pScript = pCurNode->GetFirstChildByClass(XFA_ELEMENT_Script); if (pScript && !XFA_LayoutPageMgr_RunBreakTestScript(pScript)) { return FALSE; } CFX_WideStringC wsTarget = pCurNode->GetCData(XFA_ATTRIBUTE_Target); CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget); wsBreakTrailer = pCurNode->GetCData(XFA_ATTRIBUTE_Trailer); wsBreakLeader = pCurNode->GetCData(XFA_ATTRIBUTE_Leader); pBreakLeaderTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakLeader); pBreakTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakTrailer); if (RunBreak(eType, pCurNode->GetEnum(XFA_ATTRIBUTE_TargetType), pTarget, bStartNew)) { return TRUE; } else { if (m_rgProposedContainerRecord.GetCount() > 0 && m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetHeadPosition() && eType == XFA_ELEMENT_BreakBefore) { CXFA_Node* pParentNode = pFormNode->GetNodeItem( XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); if (!pParentNode || pFormNode != pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild, XFA_OBJECTTYPE_ContainerNode)) { break; } pParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent); if (!pParentNode || pParentNode->GetClassID() != XFA_ELEMENT_Form) { break; } return TRUE; } } } break; case XFA_ELEMENT_Break: { FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0; CFX_WideStringC wsTarget = pCurNode->GetCData( bBefore ? XFA_ATTRIBUTE_BeforeTarget : XFA_ATTRIBUTE_AfterTarget); CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget); if (RunBreak(bBefore ? XFA_ELEMENT_BreakBefore : XFA_ELEMENT_BreakAfter, pCurNode->GetEnum(bBefore ? XFA_ATTRIBUTE_Before : XFA_ATTRIBUTE_After), pTarget, bStartNew)) { return TRUE; } } break; default: break; } return FALSE; } static void XFA_SetLayoutGeneratedNodeFlag(CXFA_Node* pNode) { pNode->SetFlag(XFA_NODEFLAG_LayoutGeneratedNode, TRUE, FALSE); pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE, FALSE); } FX_BOOL CXFA_LayoutPageMgr::ProcessBreakBeforeOrAfter( CXFA_Node* pBreakNode, FX_BOOL bBefore, CXFA_Node*& pBreakLeaderNode, CXFA_Node*& pBreakTrailerNode, FX_BOOL& bCreatePage) { CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL; CXFA_Node* pFormNode = pBreakNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); if (XFA_ItemLayoutProcessor_IsTakingSpace(pFormNode)) { bCreatePage = ExecuteBreakBeforeOrAfter(pBreakNode, bBefore, pLeaderTemplate, pTrailerTemplate); CXFA_Document* pDocument = pBreakNode->GetDocument(); CXFA_Node* pDataScope = NULL; pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); if (pLeaderTemplate) { if (!pDataScope) { pDataScope = XFA_DataMerge_FindDataScope(pFormNode); } pBreakLeaderNode = pDocument->DataMerge_CopyContainer( pLeaderTemplate, pFormNode, pDataScope, TRUE); pDocument->DataMerge_UpdateBindingRelations(pBreakLeaderNode); XFA_SetLayoutGeneratedNodeFlag(pBreakLeaderNode); } if (pTrailerTemplate) { if (!pDataScope) { pDataScope = XFA_DataMerge_FindDataScope(pFormNode); } pBreakTrailerNode = pDocument->DataMerge_CopyContainer( pTrailerTemplate, pFormNode, pDataScope, TRUE); pDocument->DataMerge_UpdateBindingRelations(pBreakTrailerNode); XFA_SetLayoutGeneratedNodeFlag(pBreakTrailerNode); } return TRUE; } return FALSE; } FX_BOOL CXFA_LayoutPageMgr::ProcessBookendLeaderOrTrailer( CXFA_Node* pBookendNode, FX_BOOL bLeader, CXFA_Node*& pBookendAppendNode) { CXFA_Node* pLeaderTemplate = NULL; CXFA_Node* pFormNode = pBookendNode->GetNodeItem( XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); if (ResolveBookendLeaderOrTrailer(pBookendNode, bLeader, pLeaderTemplate)) { CXFA_Document* pDocument = pBookendNode->GetDocument(); CXFA_Node* pDataScope = NULL; if (pLeaderTemplate) { if (!pDataScope) { pDataScope = XFA_DataMerge_FindDataScope(pFormNode); } pBookendAppendNode = pDocument->DataMerge_CopyContainer( pLeaderTemplate, pFormNode, pDataScope, TRUE); pDocument->DataMerge_UpdateBindingRelations(pBookendAppendNode); XFA_SetLayoutGeneratedNodeFlag(pBookendAppendNode); return TRUE; } } return FALSE; } CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode, CXFA_Node*& pLeaderTemplate, CXFA_Node*& pTrailerTemplate, FX_BOOL bCreatePage) { CFX_WideStringC wsOverflowLeader, wsOverflowTrailer; CXFA_Node* pContainer = pOverflowNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode) ->GetTemplateNode(); if (pOverflowNode->GetClassID() == XFA_ELEMENT_Break) { CFX_WideStringC wsOverflowLeader; CFX_WideStringC wsOverflowTarget; CFX_WideStringC wsOverflowTrailer; pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader); pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer); pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget); if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || !wsOverflowTarget.IsEmpty()) { if (!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) { CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsOverflowTarget); if (pTarget) { m_bCreateOverFlowPage = TRUE; switch (pTarget->GetClassID()) { case XFA_ELEMENT_PageArea: RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget, TRUE); break; case XFA_ELEMENT_ContentArea: RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea, pTarget, TRUE); break; default: break; } } } if (!bCreatePage) { pLeaderTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader); pTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer); } return pOverflowNode; } return NULL; } else if (pOverflowNode->GetClassID() == XFA_ELEMENT_Overflow) { CFX_WideStringC wsOverflowTarget; pOverflowNode->TryCData(XFA_ATTRIBUTE_Leader, wsOverflowLeader); pOverflowNode->TryCData(XFA_ATTRIBUTE_Trailer, wsOverflowTrailer); pOverflowNode->TryCData(XFA_ATTRIBUTE_Target, wsOverflowTarget); if (!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) { CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsOverflowTarget); if (pTarget) { m_bCreateOverFlowPage = TRUE; switch (pTarget->GetClassID()) { case XFA_ELEMENT_PageArea: RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget, TRUE); break; case XFA_ELEMENT_ContentArea: RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea, pTarget, TRUE); break; default: break; } } } if (!bCreatePage) { pLeaderTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader); pTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer); } return pOverflowNode; } return NULL; } FX_BOOL CXFA_LayoutPageMgr::ProcessOverflow(CXFA_Node* pFormNode, CXFA_Node*& pLeaderNode, CXFA_Node*& pTrailerNode, FX_BOOL bDataMerge, FX_BOOL bCreatePage) { if (pFormNode == NULL) { return FALSE; } CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL; FX_BOOL bIsOverflowNode = FALSE; if (pFormNode->GetClassID() == XFA_ELEMENT_Overflow || pFormNode->GetClassID() == XFA_ELEMENT_Break) { bIsOverflowNode = TRUE; } for (CXFA_Node* pCurNode = bIsOverflowNode ? pFormNode : pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) { if (BreakOverflow(pCurNode, pLeaderTemplate, pTrailerTemplate, bCreatePage)) { if (bIsOverflowNode) { pFormNode = pCurNode->GetNodeItem(XFA_NODEITEM_Parent); } CXFA_Document* pDocument = pCurNode->GetDocument(); CXFA_Node* pDataScope = NULL; if (pLeaderTemplate) { if (!pDataScope) { pDataScope = XFA_DataMerge_FindDataScope(pFormNode); } pLeaderNode = pDocument->DataMerge_CopyContainer( pLeaderTemplate, pFormNode, pDataScope, TRUE); pDocument->DataMerge_UpdateBindingRelations(pLeaderNode); XFA_SetLayoutGeneratedNodeFlag(pLeaderNode); } if (pTrailerTemplate) { if (!pDataScope) { pDataScope = XFA_DataMerge_FindDataScope(pFormNode); } pTrailerNode = pDocument->DataMerge_CopyContainer( pTrailerTemplate, pFormNode, pDataScope, TRUE); pDocument->DataMerge_UpdateBindingRelations(pTrailerNode); XFA_SetLayoutGeneratedNodeFlag(pTrailerNode); } return TRUE; } if (bIsOverflowNode) { break; } } return FALSE; } FX_BOOL CXFA_LayoutPageMgr::ResolveBookendLeaderOrTrailer( CXFA_Node* pBookendNode, FX_BOOL bLeader, CXFA_Node*& pBookendAppendTemplate) { CFX_WideStringC wsBookendLeader; CXFA_Node* pContainer = pBookendNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode) ->GetTemplateNode(); if (pBookendNode->GetClassID() == XFA_ELEMENT_Break) { pBookendNode->TryCData( bLeader ? XFA_ATTRIBUTE_BookendLeader : XFA_ATTRIBUTE_BookendTrailer, wsBookendLeader); if (!wsBookendLeader.IsEmpty()) { pBookendAppendTemplate = XFA_ResolveBreakTarget(pContainer, FALSE, wsBookendLeader); return TRUE; } return FALSE; } else if (pBookendNode->GetClassID() == XFA_ELEMENT_Bookend) { pBookendNode->TryCData( bLeader ? XFA_ATTRIBUTE_Leader : XFA_ATTRIBUTE_Trailer, wsBookendLeader); pBookendAppendTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsBookendLeader); return TRUE; } return FALSE; } FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet( CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery) { if (pPageSet == NULL && pStartChild == NULL) { return FALSE; } if (IsPageSetRootOrderedOccurrence()) { return FindPageAreaFromPageSet_Ordered(pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage, bQuery); } XFA_ATTRIBUTEENUM ePreferredPosition = m_pCurrentContainerRecord ? XFA_ATTRIBUTEENUM_Rest : XFA_ATTRIBUTEENUM_First; return FindPageAreaFromPageSet_SimplexDuplex( pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage, bQuery, ePreferredPosition); } FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_Ordered( CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery) { int32_t iPageSetCount = 0; if (!pStartChild && !bQuery) { m_pPageSetMap.Lookup(pPageSet, iPageSetCount); int32_t iMax = -1; CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur); if (pOccurNode) { pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE); } if (iMax >= 0 && iMax <= iPageSetCount) { return FALSE; } } FX_BOOL bRes = FALSE; CXFA_Node* pCurrentNode = pStartChild ? pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling) : pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); for (; pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) { if ((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) { if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) == NULL) { if (pTargetPageArea == pCurrentNode) { CreateMinPageRecord(pCurrentNode, TRUE); pTargetPageArea = NULL; } continue; } if (!bQuery) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(pCurrentNode, pStartChild == NULL); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); if (pTargetContentArea == NULL) { pTargetContentArea = pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } m_pCurPageArea = pCurrentNode; m_nCurPageCount = 1; bRes = TRUE; break; } if (!bQuery) { CreateMinPageRecord(pCurrentNode, FALSE); } } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) { if (FindPageAreaFromPageSet_Ordered(pCurrentNode, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) { bRes = TRUE; break; } if (!bQuery) { CreateMinPageSetRecord(pCurrentNode, TRUE); } } } if (!pStartChild && bRes && !bQuery) { m_pPageSetMap.SetAt(pPageSet, ++iPageSetCount); } return bRes; } FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex( CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery, XFA_ATTRIBUTEENUM ePreferredPosition) { const XFA_ATTRIBUTEENUM eFallbackPosition = XFA_ATTRIBUTEENUM_Any; CXFA_Node *pPreferredPageArea = NULL, *pFallbackPageArea = NULL; CXFA_Node* pCurrentNode = NULL; if (!pStartChild || pStartChild->GetClassID() == XFA_ELEMENT_PageArea) { pCurrentNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); } else { pCurrentNode = pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling); } for (; pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) { if (!MatchPageAreaOddOrEven(pCurrentNode, FALSE)) { continue; } XFA_ATTRIBUTEENUM eCurPagePosition = pCurrentNode->GetEnum(XFA_ATTRIBUTE_PagePosition); if (ePreferredPosition == XFA_ATTRIBUTEENUM_Last) { if (eCurPagePosition != ePreferredPosition) { continue; } if (m_ePageSetMode == XFA_ATTRIBUTEENUM_SimplexPaginated || pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == XFA_ATTRIBUTEENUM_Any) { pPreferredPageArea = pCurrentNode; break; } CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass( XFA_ELEMENT_ContentArea)); pPreferredPageArea = pCurrentNode; return FALSE; } else if (ePreferredPosition == XFA_ATTRIBUTEENUM_Only) { if (eCurPagePosition != ePreferredPosition) { continue; } if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated || pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == XFA_ATTRIBUTEENUM_Any) { pPreferredPageArea = pCurrentNode; break; } return FALSE; } if ((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) { if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) == NULL) { if (pTargetPageArea == pCurrentNode) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); pTargetPageArea = NULL; } continue; } if ((ePreferredPosition == XFA_ATTRIBUTEENUM_Rest && eCurPagePosition == XFA_ATTRIBUTEENUM_Any) || eCurPagePosition == ePreferredPosition) { pPreferredPageArea = pCurrentNode; break; } else if (eCurPagePosition == eFallbackPosition && !pFallbackPageArea) { pFallbackPageArea = pCurrentNode; } } else if (pTargetPageArea && !MatchPageAreaOddOrEven(pTargetPageArea, FALSE)) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass( XFA_ELEMENT_ContentArea)); } } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) { if (FindPageAreaFromPageSet_SimplexDuplex( pCurrentNode, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery, ePreferredPosition)) { break; } } } CXFA_Node* pCurPageArea = NULL; if (pPreferredPageArea) { pCurPageArea = pPreferredPageArea; } else if (pFallbackPageArea) { pCurPageArea = pFallbackPageArea; } if (!pCurPageArea) { return FALSE; } if (!bQuery) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurPageArea); if (pTargetContentArea == NULL) { pTargetContentArea = pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } m_pCurPageArea = pCurPageArea; return TRUE; } FX_BOOL CXFA_LayoutPageMgr::MatchPageAreaOddOrEven(CXFA_Node* pPageArea, FX_BOOL bLastMatch) { if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated) { return TRUE; } XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any; pPageArea->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven); if (eOddOrEven != XFA_ATTRIBUTEENUM_Any) { int32_t iPageCount = GetPageCount(); if (bLastMatch) { return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 1 : iPageCount % 2 == 0; } return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 0 : iPageCount % 2 == 1; } return TRUE; } CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery) { if (m_pCurPageArea == NULL) { FindPageAreaFromPageSet(m_pTemplatePageSetRoot, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery); ASSERT(m_pCurPageArea); return m_pCurPageArea; } if (pTargetPageArea == NULL || pTargetPageArea == m_pCurPageArea) { if (!bNewPage && GetNextContentArea(pTargetContentArea)) { return m_pCurPageArea; } if (IsPageSetRootOrderedOccurrence()) { int32_t iMax = -1; CXFA_Node* pOccurNode = m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur); if (pOccurNode) { pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE); } if ((iMax < 0 || m_nCurPageCount < iMax)) { if (!bQuery) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(m_pCurPageArea); AddPageAreaLayoutItem(pNewRecord, m_pCurPageArea); if (pTargetContentArea == NULL) { pTargetContentArea = m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } m_nCurPageCount++; return m_pCurPageArea; } } } if (!bQuery && IsPageSetRootOrderedOccurrence()) { CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE); } if (FindPageAreaFromPageSet(m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent), m_pCurPageArea, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) { return m_pCurPageArea; } CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent); while (TRUE) { if (FindPageAreaFromPageSet(pPageSet, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) { return m_pCurPageArea; } if (!bQuery && IsPageSetRootOrderedOccurrence()) { CreateMinPageSetRecord(pPageSet); } if (FindPageAreaFromPageSet(NULL, pPageSet, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) { return m_pCurPageArea; } if (pPageSet == m_pTemplatePageSetRoot) { break; } pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent); } return NULL; } static FX_BOOL XFA_LayoutPageMgr_CheckContentAreaNotUsed( CXFA_ContainerLayoutItem* pPageAreaLayoutItem, CXFA_Node* pContentArea, CXFA_ContainerLayoutItem*& pContentAreaLayoutItem) { for (CXFA_ContainerLayoutItem* pLayoutItem = (CXFA_ContainerLayoutItem*)pPageAreaLayoutItem->m_pFirstChild; pLayoutItem; pLayoutItem = (CXFA_ContainerLayoutItem*)pLayoutItem->m_pNextSibling) { if (pLayoutItem->m_pFormNode == pContentArea) { if (pLayoutItem->m_pFirstChild == NULL) { pContentAreaLayoutItem = pLayoutItem; return TRUE; } return FALSE; } } return TRUE; } FX_BOOL CXFA_LayoutPageMgr::GetNextContentArea(CXFA_Node* pContentArea) { CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode; if (pContentArea == NULL) { pContentArea = pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea); if (pContentArea == NULL) { return FALSE; } } else { if (pContentArea->GetNodeItem(XFA_NODEITEM_Parent) != m_pCurPageArea) { return FALSE; } CXFA_ContainerLayoutItem* pContentAreaLayout = NULL; if (!XFA_LayoutPageMgr_CheckContentAreaNotUsed( GetCurrentContainerRecord()->pCurPageArea, pContentArea, pContentAreaLayout)) { return FALSE; } if (pContentAreaLayout) { if (pContentAreaLayout->m_pFormNode != pCurContentNode) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); pNewRecord->pCurContentArea = pContentAreaLayout; return TRUE; } else { return FALSE; } } } CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddContentAreaLayoutItem(pNewRecord, pContentArea); return TRUE; } void CXFA_LayoutPageMgr::InitPageSetMap() { if (!IsPageSetRootOrderedOccurrence()) { return; } CXFA_NodeIterator sIterator(m_pTemplatePageSetRoot); for (CXFA_Node* pPageSetNode = sIterator.GetCurrent(); pPageSetNode; pPageSetNode = sIterator.MoveToNext()) { if (pPageSetNode->GetClassID() == XFA_ELEMENT_PageSet) { XFA_ATTRIBUTEENUM eRelation = pPageSetNode->GetEnum(XFA_ATTRIBUTE_Relation); if (eRelation == XFA_ATTRIBUTEENUM_OrderedOccurrence) { m_pPageSetMap.SetAt(pPageSetNode, 0); } } } } int32_t CXFA_LayoutPageMgr::CreateMinPageRecord(CXFA_Node* pPageArea, FX_BOOL bTargetPageArea, FX_BOOL bCreateLast) { if (pPageArea == NULL) { return 0; } CXFA_Node* pOccurNode = pPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur); int32_t iMin = 0; if ((pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) || bTargetPageArea) { CXFA_Node* pContentArea = pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea); if (iMin < 1 && bTargetPageArea && !pContentArea) { iMin = 1; } int32_t i = 0; if (bCreateLast) { i = m_nCurPageCount; } for (; i < iMin; i++) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pPageArea); AddContentAreaLayoutItem(pNewRecord, pContentArea); } } return iMin; } void CXFA_LayoutPageMgr::CreateMinPageSetRecord(CXFA_Node* pPageSet, FX_BOOL bCreateAll) { if (pPageSet == NULL) { return; } int32_t iCurSetCount = 0; if (!m_pPageSetMap.Lookup(pPageSet, iCurSetCount)) { return; } if (bCreateAll) { iCurSetCount = 0; } CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur); int32_t iMin = 0; if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) { if (iCurSetCount < iMin) { for (int32_t i = 0; i < iMin - iCurSetCount; i++) { for (CXFA_Node* pCurrentPageNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); pCurrentPageNode; pCurrentPageNode = pCurrentPageNode->GetNodeItem( XFA_NODEITEM_NextSibling)) { if (pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageArea) { CreateMinPageRecord(pCurrentPageNode, FALSE); } else if (pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageSet) { CreateMinPageSetRecord(pCurrentPageNode, TRUE); } } } m_pPageSetMap.SetAt(pPageSet, iMin); } } } void CXFA_LayoutPageMgr::CreateNextMinRecord(CXFA_Node* pRecordNode) { if (pRecordNode == NULL) { return; } for (CXFA_Node* pCurrentNode = pRecordNode->GetNodeItem(XFA_NODEITEM_NextSibling); pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) { CreateMinPageRecord(pCurrentNode, FALSE); } else if (pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) { CreateMinPageSetRecord(pCurrentNode, TRUE); } } } void CXFA_LayoutPageMgr::ProcessLastPageSet() { CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE); CreateNextMinRecord(m_pCurPageArea); CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent); while (TRUE) { CreateMinPageSetRecord(pPageSet); if (pPageSet == m_pTemplatePageSetRoot) { break; } CreateNextMinRecord(pPageSet); pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent); } } FX_BOOL CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight) { CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode; if (pCurContentNode == NULL) { return FALSE; } pCurContentNode = pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea); if (pCurContentNode) { FX_FLOAT fNextContentHeight = pCurContentNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); return fNextContentHeight > fChildHeight; } CXFA_Node* pPageNode = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode; CXFA_Node* pOccurNode = pPageNode->GetFirstChildByClass(XFA_ELEMENT_Occur); int32_t iMax = 0; if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE)) { if (m_nCurPageCount == iMax) { CXFA_Node* pSrcPage = m_pCurPageArea; int32_t nSrcPageCount = m_nCurPageCount; FX_POSITION psSrcRecord = m_rgProposedContainerRecord.GetTailPosition(); CXFA_Node* pNextPage = GetNextAvailPageArea(NULL, NULL, FALSE, TRUE); m_pCurPageArea = pSrcPage; m_nCurPageCount = nSrcPageCount; CXFA_ContainerRecord* pPrevRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext( psSrcRecord); while (psSrcRecord) { FX_POSITION psSaveRecord = psSrcRecord; CXFA_ContainerRecord* pInsertRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext( psSrcRecord); RemoveLayoutRecord(pInsertRecord, pPrevRecord); delete pInsertRecord; m_rgProposedContainerRecord.RemoveAt(psSaveRecord); } if (pNextPage) { CXFA_Node* pContentArea = pNextPage->GetFirstChildByClass(XFA_ELEMENT_ContentArea); if (pContentArea) { FX_FLOAT fNextContentHeight = pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); if (fNextContentHeight > fChildHeight) { return TRUE; } } } return FALSE; } } CXFA_Node* pContentArea = pPageNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea); FX_FLOAT fNextContentHeight = pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); if (fNextContentHeight < XFA_LAYOUT_FLOAT_PERCISION) { return TRUE; } if (fNextContentHeight > fChildHeight) { return TRUE; } return FALSE; } void CXFA_LayoutPageMgr::ClearData() { ClearRecordList(); } void CXFA_LayoutPageMgr::ClearRecordList() { if (!m_pTemplatePageSetRoot) { return; } if (m_rgProposedContainerRecord.GetCount() > 0) { FX_POSITION sPos; sPos = m_rgProposedContainerRecord.GetHeadPosition(); while (sPos) { CXFA_ContainerRecord* pRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(sPos); delete pRecord; } m_rgProposedContainerRecord.RemoveAll(); } m_pCurrentContainerRecord = NULL; m_pCurPageArea = NULL; m_nCurPageCount = 0; m_bCreateOverFlowPage = FALSE; m_pPageSetMap.RemoveAll(); } CXFA_LayoutItem* CXFA_LayoutPageMgr::FindOrCreateLayoutItem( CXFA_Node* pFormNode) { return pFormNode->GetDocument()->GetParser()->GetNotify()->OnCreateLayoutItem( pFormNode); } static void XFA_SyncRemoveLayoutItem(CXFA_LayoutItem* pParentLayoutItem, CXFA_FFNotify* pNotify, CXFA_LayoutProcessor* pDocLayout) { CXFA_LayoutItem* pNextLayoutItem; CXFA_LayoutItem* pCurLayoutItem = pParentLayoutItem->m_pFirstChild; while (pCurLayoutItem) { pNextLayoutItem = pCurLayoutItem->m_pNextSibling; if (pCurLayoutItem->m_pFirstChild) { XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout); } pNotify->OnLayoutEvent(pDocLayout, pCurLayoutItem, XFA_LAYOUTEVENT_ItemRemoving); delete pCurLayoutItem; pCurLayoutItem = pNextLayoutItem; } } void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItem* pParentLayoutItem) { CXFA_LayoutItem* pNextLayoutItem; CXFA_LayoutItem* pCurLayoutItem = pParentLayoutItem->m_pFirstChild; while (pCurLayoutItem) { pNextLayoutItem = pCurLayoutItem->m_pNextSibling; if (pCurLayoutItem->IsContentLayoutItem()) { uint32_t dwFlag = pCurLayoutItem->m_pFormNode->GetFlag(); if (dwFlag & (XFA_NODEFLAG_HasRemoved)) { CXFA_FFNotify* pNotify = m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify(); CXFA_LayoutProcessor* pDocLayout = m_pTemplatePageSetRoot->GetDocument()->GetDocLayout(); if (pCurLayoutItem->m_pFirstChild) { XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout); } pNotify->OnLayoutEvent(pDocLayout, pCurLayoutItem, XFA_LAYOUTEVENT_ItemRemoving); delete pCurLayoutItem; pCurLayoutItem = pNextLayoutItem; continue; } if (dwFlag & XFA_NODEFLAG_LayoutGeneratedNode) { CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pCurLayoutItem->m_pFormNode); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { pNode->SetFlag(XFA_NODEFLAG_UnusedNode, TRUE, FALSE); } } } if (pCurLayoutItem->m_pFirstChild) { SaveLayoutItem(pCurLayoutItem); } pCurLayoutItem->m_pParent = NULL; pCurLayoutItem->m_pNextSibling = NULL; pCurLayoutItem->m_pFirstChild = NULL; if (!pCurLayoutItem->IsContentLayoutItem() && pCurLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) { delete pCurLayoutItem; } pCurLayoutItem = pNextLayoutItem; } } CXFA_Node* CXFA_LayoutPageMgr::QueryOverflow( CXFA_Node* pFormNode, CXFA_LayoutContext* pLayoutContext) { for (CXFA_Node* pCurNode = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) { if (pCurNode->GetClassID() == XFA_ELEMENT_Break) { CFX_WideStringC wsOverflowLeader; CFX_WideStringC wsOverflowTarget; CFX_WideStringC wsOverflowTrailer; pCurNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader); pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer); pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget); if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || !wsOverflowTarget.IsEmpty()) { return pCurNode; } return NULL; } else if (pCurNode->GetClassID() == XFA_ELEMENT_Overflow) { return pCurNode; } } return NULL; } void CXFA_LayoutPageMgr::MergePageSetContents() { CXFA_Document* pDocument = m_pTemplatePageSetRoot->GetDocument(); CXFA_FFNotify* pNotify = pDocument->GetParser()->GetNotify(); CXFA_LayoutProcessor* pDocLayout = pDocument->GetDocLayout(); CXFA_ContainerLayoutItem* pRootLayout = GetRootLayoutItem(); { for (int32_t iIndex = 0; iIndex < pDocument->m_pPendingPageSet.GetSize(); iIndex++) { CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pDocument->m_pPendingPageSet.GetAt(iIndex)); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { if (pNode->IsContainerNode()) { CXFA_Node* pBindNode = pNode->GetBindData(); if (pBindNode) { pBindNode->RemoveBindItem(pNode); pNode->SetObject(XFA_ATTRIBUTE_BindingNode, NULL); } } pNode->SetFlag(XFA_NODEFLAG_UnusedNode); } } } int32_t iIndex = 0; CXFA_Node* pPendingPageSet = NULL; for (; pRootLayout; pRootLayout = (CXFA_ContainerLayoutItem*)pRootLayout->m_pNextSibling) { pPendingPageSet = NULL; CXFA_NodeIteratorTemplate< CXFA_ContainerLayoutItem, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iterator(pRootLayout); CXFA_ContainerLayoutItem* pRootPageSetContainerItem = iterator.GetCurrent(); ASSERT(pRootPageSetContainerItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet); if (iIndex < pDocument->m_pPendingPageSet.GetSize()) { pPendingPageSet = pDocument->m_pPendingPageSet.GetAt(iIndex); iIndex++; } if (!pPendingPageSet) { if (pRootPageSetContainerItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Template) { pPendingPageSet = pRootPageSetContainerItem->m_pFormNode->CloneTemplateToForm(FALSE); } else { pPendingPageSet = pRootPageSetContainerItem->m_pFormNode; } } if (pRootPageSetContainerItem->m_pFormNode->GetUserData( XFA_LAYOUTITEMKEY) == pRootPageSetContainerItem) { pRootPageSetContainerItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL); } pRootPageSetContainerItem->m_pFormNode = pPendingPageSet; pPendingPageSet->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE); for (CXFA_ContainerLayoutItem* pContainerItem = iterator.MoveToNext(); pContainerItem; pContainerItem = iterator.MoveToNext()) { CXFA_Node* pNode = pContainerItem->m_pFormNode; if (pNode->GetPacketID() != XFA_XDPPACKET_Template) { continue; } switch (pNode->GetClassID()) { case XFA_ELEMENT_PageSet: { CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode; pContainerItem->m_pFormNode = XFA_NodeMerge_CloneOrMergeContainer( pDocument, pParentNode, pContainerItem->m_pFormNode, TRUE); } break; case XFA_ELEMENT_PageArea: { CXFA_ContainerLayoutItem* pFormLayout = pContainerItem; CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode; FX_BOOL bIsExistForm = TRUE; for (int32_t iLevel = 0; iLevel < 3; iLevel++) { pFormLayout = (CXFA_ContainerLayoutItem*)pFormLayout->m_pFirstChild; if (iLevel == 2) { while (pFormLayout && !XFA_ItemLayoutProcessor_IsTakingSpace( pFormLayout->m_pFormNode)) { pFormLayout = (CXFA_ContainerLayoutItem*)pFormLayout->m_pNextSibling; } } if (pFormLayout == NULL) { bIsExistForm = FALSE; break; } } if (bIsExistForm) { CXFA_Node* pNewSubform = pFormLayout->m_pFormNode; if (pContainerItem->m_pOldSubform && pContainerItem->m_pOldSubform != pNewSubform) { CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance( pDocument, pContainerItem->m_pFormNode->GetClassID(), pContainerItem->m_pFormNode->GetNameHash(), pParentNode); CXFA_ContainerIterator sIterator(pExistingNode); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { if (pNode->GetClassID() != XFA_ELEMENT_ContentArea) { CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( pNode->GetUserData(XFA_LAYOUTITEMKEY)); if (pLayoutItem) { pNotify->OnLayoutEvent(pDocLayout, pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving); delete pLayoutItem; } } } if (pExistingNode) { pParentNode->RemoveChild(pExistingNode); } } pContainerItem->m_pOldSubform = pNewSubform; } pContainerItem->m_pFormNode = pDocument->DataMerge_CopyContainer( pContainerItem->m_pFormNode, pParentNode, ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)), TRUE); } break; case XFA_ELEMENT_ContentArea: { CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode; for (CXFA_Node* pChildNode = pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild); pChildNode; pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { if (pChildNode->GetTemplateNode() != pContainerItem->m_pFormNode) { continue; } pContainerItem->m_pFormNode = pChildNode; break; } } break; default: break; } } if (!pPendingPageSet->GetNodeItem(XFA_NODEITEM_Parent)) { CXFA_Node* pFormToplevelSubform = pDocument->GetXFAObject(XFA_HASHCODE_Form) ->AsNode() ->GetFirstChildByClass(XFA_ELEMENT_Subform); pFormToplevelSubform->InsertChild(pPendingPageSet); } pDocument->DataMerge_UpdateBindingRelations(pPendingPageSet); pPendingPageSet->SetFlag(XFA_NODEFLAG_Initialized); } pPendingPageSet = GetRootLayoutItem()->m_pFormNode; while (pPendingPageSet) { CXFA_Node* pNextPendingPageSet = pPendingPageSet->GetNextSameClassSibling(XFA_ELEMENT_PageSet); CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pPendingPageSet); CXFA_Node* pNode = sIterator.GetCurrent(); while (pNode) { if (pNode->HasFlag(XFA_NODEFLAG_UnusedNode)) { if (pNode->GetObjectType() == XFA_OBJECTTYPE_ContainerNode) { XFA_ELEMENT eCurId = pNode->GetClassID(); if (eCurId == XFA_ELEMENT_PageArea || eCurId == XFA_ELEMENT_PageSet) { CXFA_ContainerIterator iteChild(pNode); CXFA_Node* pChildNode = iteChild.MoveToNext(); for (; pChildNode; pChildNode = iteChild.MoveToNext()) { CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( pChildNode->GetUserData(XFA_LAYOUTITEMKEY)); if (pLayoutItem) { pNotify->OnLayoutEvent(pDocLayout, pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving); delete pLayoutItem; } } } else if (eCurId != XFA_ELEMENT_ContentArea) { CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( pNode->GetUserData(XFA_LAYOUTITEMKEY)); if (pLayoutItem) { pNotify->OnLayoutEvent(pDocLayout, pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving); delete pLayoutItem; } } CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext(); pNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pNode); pNode = pNext; } else { pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE); pNode->SetFlag(XFA_NODEFLAG_Initialized); pNode = sIterator.MoveToNext(); } } else { pNode->SetFlag(XFA_NODEFLAG_Initialized); pNode = sIterator.MoveToNext(); } } pPendingPageSet = pNextPendingPageSet; } } void CXFA_LayoutPageMgr::LayoutPageSetContents() { CXFA_ContainerLayoutItem* pRootLayoutItem = GetRootLayoutItem(); for (; pRootLayoutItem; pRootLayoutItem = (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling) { CXFA_NodeIteratorTemplate< CXFA_ContainerLayoutItem, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iterator(pRootLayoutItem); for (CXFA_ContainerLayoutItem* pContainerItem = iterator.GetCurrent(); pContainerItem; pContainerItem = iterator.MoveToNext()) { CXFA_Node* pNode = pContainerItem->m_pFormNode; switch (pNode->GetClassID()) { case XFA_ELEMENT_PageArea: m_pLayoutProcessor->GetRootRootItemLayoutProcessor() ->DoLayoutPageArea(pContainerItem); break; default: break; } } } } void XFA_SyncContainer(CXFA_FFNotify* pNotify, CXFA_LayoutProcessor* pDocLayout, CXFA_LayoutItem* pContainerItem, uint32_t dwRelevant, FX_BOOL bVisible, int32_t nPageIndex) { FX_BOOL bVisibleItem = FALSE; uint32_t dwStatus = 0; uint32_t dwRelevantContainer = 0; if (bVisible) { XFA_ATTRIBUTEENUM eAttributeValue = pContainerItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence); if (eAttributeValue == XFA_ATTRIBUTEENUM_Visible || eAttributeValue == XFA_ATTRIBUTEENUM_Unknown) { bVisibleItem = TRUE; } dwRelevantContainer = XFA_GetRelevant(pContainerItem->m_pFormNode, dwRelevant); dwStatus = (bVisibleItem ? XFA_LAYOUTSTATUS_Visible : 0) | dwRelevantContainer; } pNotify->OnLayoutEvent(pDocLayout, pContainerItem, XFA_LAYOUTEVENT_ItemAdded, (void*)(uintptr_t)nPageIndex, (void*)(uintptr_t)dwStatus); for (CXFA_LayoutItem* pChild = pContainerItem->m_pFirstChild; pChild; pChild = pChild->m_pNextSibling) { if (pChild->IsContentLayoutItem()) { XFA_SyncContainer(pNotify, pDocLayout, pChild, dwRelevantContainer, bVisibleItem, nPageIndex); } } } void CXFA_LayoutPageMgr::SyncLayoutData() { MergePageSetContents(); LayoutPageSetContents(); CXFA_FFNotify* pNotify = m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify(); int32_t nPageIdx = -1; CXFA_ContainerLayoutItem* pRootLayoutItem = GetRootLayoutItem(); for (; pRootLayoutItem; pRootLayoutItem = (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling) { CXFA_NodeIteratorTemplate< CXFA_ContainerLayoutItem, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iteratorParent(pRootLayoutItem); for (CXFA_ContainerLayoutItem* pContainerItem = iteratorParent.GetCurrent(); pContainerItem; pContainerItem = iteratorParent.MoveToNext()) { switch (pContainerItem->m_pFormNode->GetClassID()) { case XFA_ELEMENT_PageArea: { nPageIdx++; uint32_t dwRelevant = XFA_LAYOUTSTATUS_Viewable | XFA_LAYOUTSTATUS_Printable; CXFA_NodeIteratorTemplate<CXFA_LayoutItem, CXFA_TraverseStrategy_LayoutItem> iterator(pContainerItem); CXFA_LayoutItem* pChildLayoutItem = iterator.GetCurrent(); while (pChildLayoutItem) { CXFA_ContentLayoutItem* pContentItem = pChildLayoutItem->AsContentLayoutItem(); if (!pContentItem) { pChildLayoutItem = iterator.MoveToNext(); continue; } FX_BOOL bVisible = (pContentItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence) == XFA_ATTRIBUTEENUM_Visible); uint32_t dwRelevantChild = XFA_GetRelevant(pContentItem->m_pFormNode, dwRelevant); XFA_SyncContainer(pNotify, m_pLayoutProcessor, pContentItem, dwRelevantChild, bVisible, nPageIdx); pChildLayoutItem = iterator.SkipChildrenAndMoveToNext(); } } break; default: break; } } } int32_t nPage = m_PageArray.GetSize(); for (int32_t i = nPage - 1; i >= m_nAvailPages; i--) { CXFA_ContainerLayoutItem* pPage = m_PageArray[i]; m_PageArray.RemoveAt(i); pNotify->OnPageEvent(pPage, XFA_PAGEEVENT_PageRemoved); delete pPage; } ClearRecordList(); } void XFA_ReleaseLayoutItem_NoPageArea(CXFA_LayoutItem* pLayoutItem) { CXFA_LayoutItem *pNext, *pNode = pLayoutItem->m_pFirstChild; while (pNode) { pNext = pNode->m_pNextSibling; pNode->m_pParent = NULL; XFA_ReleaseLayoutItem_NoPageArea(pNode); pNode = pNext; } if (pLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) { delete pLayoutItem; } } void CXFA_LayoutPageMgr::PrepareLayout() { m_pPageSetCurRoot = NULL; m_ePageSetMode = XFA_ATTRIBUTEENUM_OrderedOccurrence; m_nAvailPages = 0; ClearRecordList(); if (!m_pPageSetLayoutItemRoot) { return; } CXFA_ContainerLayoutItem* pRootLayoutItem = m_pPageSetLayoutItemRoot; if (pRootLayoutItem && pRootLayoutItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Form) { CXFA_Node* pPageSetFormNode = pRootLayoutItem->m_pFormNode; pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.RemoveAll(); if (pPageSetFormNode->HasFlag(XFA_NODEFLAG_HasRemoved)) { XFA_ReleaseLayoutItem(pRootLayoutItem); m_pPageSetLayoutItemRoot = NULL; pRootLayoutItem = NULL; pPageSetFormNode = NULL; m_PageArray.RemoveAll(); } while (pPageSetFormNode) { CXFA_Node* pNextPageSet = pPageSetFormNode->GetNextSameClassSibling(XFA_ELEMENT_PageSet); pPageSetFormNode->GetNodeItem(XFA_NODEITEM_Parent) ->RemoveChild(pPageSetFormNode, FALSE); pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.Add( pPageSetFormNode); pPageSetFormNode = pNextPageSet; } } pRootLayoutItem = m_pPageSetLayoutItemRoot; CXFA_ContainerLayoutItem* pNextLayout = NULL; for (; pRootLayoutItem; pRootLayoutItem = pNextLayout) { pNextLayout = (CXFA_ContainerLayoutItem*)pRootLayoutItem->m_pNextSibling; SaveLayoutItem(pRootLayoutItem); delete pRootLayoutItem; } m_pPageSetLayoutItemRoot = NULL; }