• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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