text: // 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_XFA_LAYOUT_PAGEMGR_NEW_H_
  #define XFA_FXFA_PARSER_XFA_LAYOUT_PAGEMGR_NEW_H_
  
  #include "xfa/fxfa/parser/xfa_doclayout.h"
  #include "xfa/fxfa/parser/xfa_layout_itemlayout.h"
  
  class CXFA_ContainerRecord {
   public:
    CXFA_ContainerRecord(CXFA_ContainerLayoutItem* pPageSet = NULL,
                         CXFA_ContainerLayoutItem* pPageArea = NULL,
                         CXFA_ContainerLayoutItem* pContentArea = NULL)
        : pCurPageSet(pPageSet),
          pCurPageArea(pPageArea),
          pCurContentArea(pContentArea) {}
    CXFA_ContainerLayoutItem* pCurPageSet;
    CXFA_ContainerLayoutItem* pCurPageArea;
    CXFA_ContainerLayoutItem* pCurContentArea;
  };
  class CXFA_LayoutPageMgr {
   public:
    CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor);
    ~CXFA_LayoutPageMgr();
    FX_BOOL InitLayoutPage(CXFA_Node* pFormNode);
    FX_BOOL PrepareFirstPage(CXFA_Node* pRootSubform);
    FX_FLOAT GetAvailHeight();
    FX_BOOL GetNextAvailContentHeight(FX_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;
    }
    FX_BOOL ProcessBreakBeforeOrAfter(CXFA_Node* pBreakNode,
                                      FX_BOOL bBefore,
                                      CXFA_Node*& pBreakLeaderNode,
                                      CXFA_Node*& pBreakTrailerNode,
                                      FX_BOOL& bCreatePage);
    FX_BOOL ProcessOverflow(CXFA_Node* pFormNode,
                            CXFA_Node*& pLeaderNode,
                            CXFA_Node*& pTrailerNode,
                            FX_BOOL bDataMerge = FALSE,
                            FX_BOOL bCreatePage = TRUE);
    CXFA_Node* QueryOverflow(CXFA_Node* pFormNode,
                             CXFA_LayoutContext* pLayoutContext = NULL);
    FX_BOOL ProcessBookendLeaderOrTrailer(CXFA_Node* pBookendNode,
                                          FX_BOOL bLeader,
                                          CXFA_Node*& pBookendAppendNode);
    CXFA_LayoutItem* FindOrCreateLayoutItem(CXFA_Node* pFormNode);
  
   protected:
    FX_BOOL AppendNewPage(FX_BOOL bFirstTemPage = FALSE);
    void ReorderPendingLayoutRecordToTail(CXFA_ContainerRecord* pNewRecord,
                                          CXFA_ContainerRecord* pPrevRecord);
    void RemoveLayoutRecord(CXFA_ContainerRecord* pNewRecord,
                            CXFA_ContainerRecord* pPrevRecord);
    inline CXFA_ContainerRecord* GetCurrentContainerRecord() {
      CXFA_ContainerRecord* result =
          ((CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetAt(
              m_pCurrentContainerRecord));
      ASSERT(result);
      return result;
    }
    CXFA_ContainerRecord* CreateContainerRecord(CXFA_Node* pPageNode = NULL,
                                                FX_BOOL bCreateNew = FALSE);
    void AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord,
                               CXFA_Node* pNewPageArea);
    void AddContentAreaLayoutItem(CXFA_ContainerRecord* pNewRecord,
                                  CXFA_Node* pContentArea);
    FX_BOOL RunBreak(XFA_ELEMENT eBreakType,
                     XFA_ATTRIBUTEENUM eTargetType,
                     CXFA_Node* pTarget,
                     FX_BOOL bStartNew);
    CXFA_Node* BreakOverflow(CXFA_Node* pOverflowNode,
                             CXFA_Node*& pLeaderTemplate,
                             CXFA_Node*& pTrailerTemplate,
                             FX_BOOL bCreatePage = TRUE);
    FX_BOOL ResolveBookendLeaderOrTrailer(CXFA_Node* pBookendNode,
                                          FX_BOOL bLeader,
                                          CXFA_Node*& pBookendAppendTemplate);
    FX_BOOL ExecuteBreakBeforeOrAfter(CXFA_Node* pCurNode,
                                      FX_BOOL bBefore,
                                      CXFA_Node*& pBreakLeaderTemplate,
                                      CXFA_Node*& pBreakTrailerTemplate);
  
    int32_t CreateMinPageRecord(CXFA_Node* pPageArea,
                                FX_BOOL bTargetPageArea,
                                FX_BOOL bCreateLast = FALSE);
    void CreateMinPageSetRecord(CXFA_Node* pPageSet, FX_BOOL bCreateAll = FALSE);
    void CreateNextMinRecord(CXFA_Node* pRecordNode);
    FX_BOOL FindPageAreaFromPageSet(CXFA_Node* pPageSet,
                                    CXFA_Node* pStartChild,
                                    CXFA_Node* pTargetPageArea = NULL,
                                    CXFA_Node* pTargetContentArea = NULL,
                                    FX_BOOL bNewPage = FALSE,
                                    FX_BOOL bQuery = FALSE);
    FX_BOOL FindPageAreaFromPageSet_Ordered(CXFA_Node* pPageSet,
                                            CXFA_Node* pStartChild,
                                            CXFA_Node* pTargetPageArea = NULL,
                                            CXFA_Node* pTargetContentArea = NULL,
                                            FX_BOOL bNewPage = FALSE,
                                            FX_BOOL bQuery = FALSE);
    FX_BOOL FindPageAreaFromPageSet_SimplexDuplex(
        CXFA_Node* pPageSet,
        CXFA_Node* pStartChild,
        CXFA_Node* pTargetPageArea = NULL,
        CXFA_Node* pTargetContentArea = NULL,
        FX_BOOL bNewPage = FALSE,
        FX_BOOL bQuery = FALSE,
        XFA_ATTRIBUTEENUM ePreferredPosition = XFA_ATTRIBUTEENUM_First);
    FX_BOOL MatchPageAreaOddOrEven(CXFA_Node* pPageArea, FX_BOOL bLastMatch);
    CXFA_Node* GetNextAvailPageArea(CXFA_Node* pTargetPageArea,
                                    CXFA_Node* pTargetContentArea = NULL,
                                    FX_BOOL bNewPage = FALSE,
                                    FX_BOOL bQuery = FALSE);
    FX_BOOL GetNextContentArea(CXFA_Node* pTargetContentArea);
    void InitPageSetMap();
    void ProcessLastPageSet();
    inline FX_BOOL IsPageSetRootOrderedOccurrence() {
      return m_ePageSetMode == XFA_ATTRIBUTEENUM_OrderedOccurrence;
    }
    void ClearData();
    void ClearRecordList();
    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;
    FX_POSITION m_pCurrentContainerRecord;
    CFX_PtrList m_rgProposedContainerRecord;
    CXFA_Node* m_pCurPageArea;
    int32_t m_nAvailPages;
    int32_t m_nCurPageCount;
    XFA_ATTRIBUTEENUM m_ePageSetMode;
    FX_BOOL m_bCreateOverFlowPage;
    CFX_MapPtrTemplate<CXFA_Node*, int32_t> m_pPageSetMap;
    CFX_ArrayTemplate<CXFA_ContainerLayoutItem*> m_PageArray;
  };
  
  #endif  // XFA_FXFA_PARSER_XFA_LAYOUT_PAGEMGR_NEW_H_
  