xref: /aosp_15_r20/external/pdfium/xfa/fxfa/layout/cxfa_viewlayoutprocessor.h (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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