// 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 #ifndef XFA_FXFA_PARSER_CXFA_LAYOUTPAGEMGR_H_ #define XFA_FXFA_PARSER_CXFA_LAYOUTPAGEMGR_H_ #include <iterator> #include <list> #include <map> #include <vector> #include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h" class CXFA_ContainerRecord; class CXFA_LayoutItem; class CXFA_Node; class CXFA_LayoutPageMgr { public: explicit CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor); ~CXFA_LayoutPageMgr(); bool InitLayoutPage(CXFA_Node* pFormNode); bool PrepareFirstPage(CXFA_Node* pRootSubform); float GetAvailHeight(); bool GetNextAvailContentHeight(float fChildHeight); void SubmitContentItem(CXFA_ContentLayoutItem* pContentLayoutItem, XFA_ItemLayoutProcessorResult eStatus); void FinishPaginatedPageSets(); void SyncLayoutData(); int32_t GetPageCount() const; CXFA_ContainerLayoutItem* GetPage(int32_t index) const; int32_t GetPageIndex(const CXFA_ContainerLayoutItem* pPage) const; inline CXFA_ContainerLayoutItem* GetRootLayoutItem() const { return m_pPageSetLayoutItemRoot; } bool ProcessBreakBeforeOrAfter(CXFA_Node* pBreakNode, bool bBefore, CXFA_Node*& pBreakLeaderNode, CXFA_Node*& pBreakTrailerNode, bool& bCreatePage); bool ProcessOverflow(CXFA_Node* pFormNode, CXFA_Node*& pLeaderNode, CXFA_Node*& pTrailerNode, bool bDataMerge = false, bool bCreatePage = true); CXFA_Node* QueryOverflow(CXFA_Node* pFormNode); bool ProcessBookendLeaderOrTrailer(CXFA_Node* pBookendNode, bool bLeader, CXFA_Node*& pBookendAppendNode); private: bool AppendNewPage(bool bFirstTemPage = false); void ReorderPendingLayoutRecordToTail(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord); void RemoveLayoutRecord(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord); CXFA_ContainerRecord* GetCurrentContainerRecord() { return *m_CurrentContainerRecordIter; } std::list<CXFA_ContainerRecord*>::iterator GetTailPosition() { auto iter = m_ProposedContainerRecords.end(); return !m_ProposedContainerRecords.empty() ? std::prev(iter) : iter; } CXFA_ContainerRecord* CreateContainerRecord(CXFA_Node* pPageNode = nullptr, bool bCreateNew = false); void AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pNewPageArea); void AddContentAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pContentArea); bool RunBreak(XFA_Element eBreakType, XFA_AttributeEnum eTargetType, CXFA_Node* pTarget, bool bStartNew); CXFA_Node* BreakOverflow(CXFA_Node* pOverflowNode, CXFA_Node*& pLeaderTemplate, CXFA_Node*& pTrailerTemplate, bool bCreatePage = true); bool ResolveBookendLeaderOrTrailer(CXFA_Node* pBookendNode, bool bLeader, CXFA_Node*& pBookendAppendTemplate); bool ExecuteBreakBeforeOrAfter(CXFA_Node* pCurNode, bool bBefore, CXFA_Node*& pBreakLeaderTemplate, CXFA_Node*& pBreakTrailerTemplate); int32_t CreateMinPageRecord(CXFA_Node* pPageArea, bool bTargetPageArea, bool bCreateLast = false); void CreateMinPageSetRecord(CXFA_Node* pPageSet, bool bCreateAll = false); void CreateNextMinRecord(CXFA_Node* pRecordNode); bool FindPageAreaFromPageSet(CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea = nullptr, CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, bool bQuery = false); bool FindPageAreaFromPageSet_Ordered(CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea = nullptr, CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, bool bQuery = false); bool FindPageAreaFromPageSet_SimplexDuplex( CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea = nullptr, CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, bool bQuery = false, XFA_AttributeEnum ePreferredPosition = XFA_AttributeEnum::First); bool MatchPageAreaOddOrEven(CXFA_Node* pPageArea); CXFA_Node* GetNextAvailPageArea(CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, bool bQuery = false); bool GetNextContentArea(CXFA_Node* pTargetContentArea); void InitPageSetMap(); void ProcessLastPageSet(); bool IsPageSetRootOrderedOccurrence() const { return m_ePageSetMode == XFA_AttributeEnum::OrderedOccurrence; } void ClearData(); void MergePageSetContents(); void LayoutPageSetContents(); void PrepareLayout(); void SaveLayoutItem(CXFA_LayoutItem* pParentLayoutItem); CXFA_LayoutProcessor* m_pLayoutProcessor; CXFA_Node* m_pTemplatePageSetRoot; CXFA_ContainerLayoutItem* m_pPageSetLayoutItemRoot; CXFA_ContainerLayoutItem* m_pPageSetCurRoot; std::list<CXFA_ContainerRecord*> m_ProposedContainerRecords; std::list<CXFA_ContainerRecord*>::iterator m_CurrentContainerRecordIter; CXFA_Node* m_pCurPageArea; int32_t m_nAvailPages; int32_t m_nCurPageCount; XFA_AttributeEnum m_ePageSetMode; bool m_bCreateOverFlowPage; std::map<CXFA_Node*, int32_t> m_pPageSetMap; std::vector<CXFA_ContainerLayoutItem*> m_PageArray; }; #endif // XFA_FXFA_PARSER_CXFA_LAYOUTPAGEMGR_H_