1 // Copyright 2014 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef XFA_FXFA_LAYOUT_CXFA_VIEWLAYOUTPROCESSOR_H_ 8 #define XFA_FXFA_LAYOUT_CXFA_VIEWLAYOUTPROCESSOR_H_ 9 10 #include <iterator> 11 #include <list> 12 #include <map> 13 #include <vector> 14 15 #include "core/fxcrt/unowned_ptr.h" 16 #include "core/fxcrt/unowned_ptr_exclusion.h" 17 #include "fxjs/gc/heap.h" 18 #include "third_party/abseil-cpp/absl/types/optional.h" 19 #include "v8/include/cppgc/garbage-collected.h" 20 #include "v8/include/cppgc/member.h" 21 #include "v8/include/cppgc/prefinalizer.h" 22 #include "v8/include/cppgc/visitor.h" 23 #include "xfa/fxfa/layout/cxfa_contentlayoutprocessor.h" 24 25 class CXFA_LayoutItem; 26 class CXFA_LayoutProcessor; 27 class CXFA_Node; 28 29 class CXFA_ViewLayoutProcessor 30 : public cppgc::GarbageCollected<CXFA_ViewLayoutProcessor> { 31 CPPGC_USING_PRE_FINALIZER(CXFA_ViewLayoutProcessor, PreFinalize); 32 33 public: 34 struct BreakData { 35 CPPGC_STACK_ALLOCATED(); // Raw/Unowned pointers allowed. 36 public: 37 UNOWNED_PTR_EXCLUSION CXFA_Node* pLeader; // POD struct. 38 UNOWNED_PTR_EXCLUSION CXFA_Node* pTrailer; // POD struct. 39 bool bCreatePage; 40 }; 41 42 struct OverflowData { 43 CPPGC_STACK_ALLOCATED(); // Raw/Unowned pointers allowed. 44 public: 45 UNOWNED_PTR_EXCLUSION CXFA_Node* pLeader; // POD struct. 46 UNOWNED_PTR_EXCLUSION CXFA_Node* pTrailer; // POD struct. 47 }; 48 49 CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; 50 ~CXFA_ViewLayoutProcessor(); 51 52 void PreFinalize(); 53 void Trace(cppgc::Visitor* visitor) const; GetHeap()54 cppgc::Heap* GetHeap() const { return m_pHeap; } 55 56 bool InitLayoutPage(CXFA_Node* pFormNode); 57 bool PrepareFirstPage(CXFA_Node* pRootSubform); 58 float GetAvailHeight(); 59 bool GetNextAvailContentHeight(float fChildHeight); 60 void SubmitContentItem(CXFA_ContentLayoutItem* pContentLayoutItem, 61 CXFA_ContentLayoutProcessor::Result eStatus); 62 void FinishPaginatedPageSets(); 63 void SyncLayoutData(); 64 int32_t GetPageCount() const; 65 CXFA_ViewLayoutItem* GetPage(int32_t index) const; 66 int32_t GetPageIndex(const CXFA_ViewLayoutItem* pPage) const; GetRootLayoutItem()67 CXFA_ViewLayoutItem* GetRootLayoutItem() const { 68 return m_pPageSetRootLayoutItem; 69 } 70 absl::optional<BreakData> ProcessBreakBefore(const CXFA_Node* pBreakNode); 71 absl::optional<BreakData> ProcessBreakAfter(const CXFA_Node* pBreakNode); 72 absl::optional<OverflowData> ProcessOverflow(CXFA_Node* pFormNode, 73 bool bCreatePage); 74 CXFA_Node* QueryOverflow(CXFA_Node* pFormNode); 75 CXFA_Node* ProcessBookendLeader(const CXFA_Node* pBookendNode); 76 CXFA_Node* ProcessBookendTrailer(const CXFA_Node* pBookendNode); 77 78 private: 79 class CXFA_ViewRecord : public cppgc::GarbageCollected<CXFA_ViewRecord> { 80 public: 81 CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; 82 ~CXFA_ViewRecord(); 83 84 void Trace(cppgc::Visitor* visitor) const; 85 86 cppgc::Member<CXFA_ViewLayoutItem> pCurPageSet; 87 cppgc::Member<CXFA_ViewLayoutItem> pCurPageArea; 88 cppgc::Member<CXFA_ViewLayoutItem> pCurContentArea; 89 90 private: 91 CXFA_ViewRecord(); 92 }; 93 94 CXFA_ViewLayoutProcessor(cppgc::Heap* pHeap, 95 CXFA_LayoutProcessor* pLayoutProcessor); 96 97 bool AppendNewPage(bool bFirstTemPage); 98 void RemoveLayoutRecord(CXFA_ViewRecord* pNewRecord, 99 CXFA_ViewRecord* pPrevRecord); HasCurrentViewRecord()100 bool HasCurrentViewRecord() const { 101 return m_CurrentViewRecordIter != m_ProposedViewRecords.end(); 102 } GetCurrentViewRecord()103 CXFA_ViewRecord* GetCurrentViewRecord() { 104 return HasCurrentViewRecord() ? m_CurrentViewRecordIter->Get() : nullptr; 105 } GetCurrentViewRecord()106 const CXFA_ViewRecord* GetCurrentViewRecord() const { 107 return HasCurrentViewRecord() ? m_CurrentViewRecordIter->Get() : nullptr; 108 } ResetToFirstViewRecord()109 void ResetToFirstViewRecord() { 110 m_CurrentViewRecordIter = m_ProposedViewRecords.begin(); 111 } GetTailPosition()112 std::list<cppgc::Member<CXFA_ViewRecord>>::iterator GetTailPosition() { 113 auto iter = m_ProposedViewRecords.end(); 114 return !m_ProposedViewRecords.empty() ? std::prev(iter) : iter; 115 } 116 void AppendNewRecord(CXFA_ViewRecord* pNewRecord); 117 CXFA_ViewRecord* CreateViewRecord(CXFA_Node* pPageNode, bool bCreateNew); 118 CXFA_ViewRecord* CreateViewRecordSimple(); 119 void AddPageAreaLayoutItem(CXFA_ViewRecord* pNewRecord, 120 CXFA_Node* pNewPageArea); 121 void AddContentAreaLayoutItem(CXFA_ViewRecord* pNewRecord, 122 CXFA_Node* pContentArea); 123 bool RunBreak(XFA_Element eBreakType, 124 XFA_AttributeValue eTargetType, 125 CXFA_Node* pTarget, 126 bool bStartNew); 127 bool ShouldGetNextPageArea(CXFA_Node* pTarget, bool bStartNew) const; 128 bool BreakOverflow(const CXFA_Node* pOverflowNode, 129 bool bCreatePage, 130 CXFA_Node** pLeaderTemplate, 131 CXFA_Node** pTrailerTemplate); 132 CXFA_Node* ProcessBookendLeaderOrTrailer(const CXFA_Node* pBookendNode, 133 bool bLeader); 134 CXFA_Node* ResolveBookendLeaderOrTrailer(const CXFA_Node* pBookendNode, 135 bool bLeader); 136 absl::optional<BreakData> ProcessBreakBeforeOrAfter( 137 const CXFA_Node* pBreakNode, 138 bool bBefore); 139 BreakData ExecuteBreakBeforeOrAfter(const CXFA_Node* pCurNode, bool bBefore); 140 141 int32_t CreateMinPageRecord(CXFA_Node* pPageArea, 142 bool bTargetPageArea, 143 bool bCreateLast); 144 void CreateMinPageSetRecord(CXFA_Node* pPageSet, bool bCreateAll); 145 void CreateNextMinRecord(CXFA_Node* pRecordNode); 146 bool FindPageAreaFromPageSet(CXFA_Node* pPageSet, 147 CXFA_Node* pStartChild, 148 CXFA_Node* pTargetPageArea, 149 CXFA_Node* pTargetContentArea, 150 bool bNewPage, 151 bool bQuery); 152 bool FindPageAreaFromPageSet_Ordered(CXFA_Node* pPageSet, 153 CXFA_Node* pStartChild, 154 CXFA_Node* pTargetPageArea, 155 CXFA_Node* pTargetContentArea, 156 bool bNewPage, 157 bool bQuery); 158 bool FindPageAreaFromPageSet_SimplexDuplex( 159 CXFA_Node* pPageSet, 160 CXFA_Node* pStartChild, 161 CXFA_Node* pTargetPageArea, 162 CXFA_Node* pTargetContentArea, 163 bool bNewPage, 164 bool bQuery, 165 XFA_AttributeValue ePreferredPosition); 166 bool MatchPageAreaOddOrEven(CXFA_Node* pPageArea); 167 CXFA_Node* GetNextAvailPageArea(CXFA_Node* pTargetPageArea, 168 CXFA_Node* pTargetContentArea, 169 bool bNewPage, 170 bool bQuery); 171 bool GetNextContentArea(CXFA_Node* pTargetContentArea); 172 void InitPageSetMap(); 173 void ProcessLastPageSet(); IsPageSetRootOrderedOccurrence()174 bool IsPageSetRootOrderedOccurrence() const { 175 return m_ePageSetMode == XFA_AttributeValue::OrderedOccurrence; 176 } 177 void ClearData(); 178 void MergePageSetContents(); 179 void LayoutPageSetContents(); 180 void PrepareLayout(); 181 void SaveLayoutItemChildren(CXFA_LayoutItem* pParentLayoutItem); 182 void ProcessSimplexOrDuplexPageSets(CXFA_ViewLayoutItem* pPageSetLayoutItem, 183 bool bIsSimplex); 184 185 UnownedPtr<cppgc::Heap> m_pHeap; 186 cppgc::Member<CXFA_LayoutProcessor> m_pLayoutProcessor; 187 cppgc::Member<CXFA_Node> m_pPageSetNode; 188 cppgc::Member<CXFA_Node> m_pCurPageArea; 189 cppgc::Member<CXFA_ViewLayoutItem> m_pPageSetRootLayoutItem; 190 cppgc::Member<CXFA_ViewLayoutItem> m_pPageSetCurLayoutItem; 191 std::list<cppgc::Member<CXFA_ViewRecord>> m_ProposedViewRecords; 192 std::list<cppgc::Member<CXFA_ViewRecord>>::iterator m_CurrentViewRecordIter; 193 int32_t m_nAvailPages = 0; 194 int32_t m_nCurPageCount = 0; 195 XFA_AttributeValue m_ePageSetMode = XFA_AttributeValue::OrderedOccurrence; 196 bool m_bCreateOverFlowPage = false; 197 std::map<cppgc::Member<CXFA_Node>, int32_t> m_pPageSetMap; 198 std::vector<cppgc::Member<CXFA_ViewLayoutItem>> m_PageArray; 199 }; 200 201 #endif // XFA_FXFA_LAYOUT_CXFA_VIEWLAYOUTPROCESSOR_H_ 202