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