blob: 7428374ae09342a283d89adaa72218c5ca219cad [file] [log] [blame]
// 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/xfa_layout_itemlayout.h"
class CXFA_ContainerRecord;
class CXFA_LayoutItem;
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,
CXFA_LayoutContext* pLayoutContext = nullptr);
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, bool bLastMatch);
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_