xref: /aosp_15_r20/external/pdfium/xfa/fxfa/layout/cxfa_contentlayoutprocessor.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_CONTENTLAYOUTPROCESSOR_H_
8 #define XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_
9 
10 #include <float.h>
11 
12 #include <list>
13 #include <map>
14 #include <utility>
15 #include <vector>
16 
17 #include "core/fxcrt/fx_coordinates.h"
18 #include "core/fxcrt/unowned_ptr.h"
19 #include "fxjs/gc/heap.h"
20 #include "third_party/abseil-cpp/absl/types/optional.h"
21 #include "v8/include/cppgc/garbage-collected.h"
22 #include "v8/include/cppgc/macros.h"
23 #include "v8/include/cppgc/member.h"
24 #include "v8/include/cppgc/persistent.h"
25 #include "xfa/fxfa/fxfa_basic.h"
26 
27 constexpr float kXFALayoutPrecision = 0.0005f;
28 
29 class CXFA_ContentLayoutItem;
30 class CXFA_Node;
31 class CXFA_ViewLayoutItem;
32 class CXFA_ViewLayoutProcessor;
33 
34 class CXFA_ContentLayoutProcessor
35     : public cppgc::GarbageCollected<CXFA_ContentLayoutProcessor> {
36  public:
37   enum class Result : uint8_t {
38     kDone,
39     kPageFullBreak,
40     kRowFullBreak,
41     kManualBreak,
42   };
43 
44   enum class Stage : uint8_t {
45     kNone,
46     kBookendLeader,
47     kBreakBefore,
48     kKeep,
49     kContainer,
50     kBreakAfter,
51     kBookendTrailer,
52     kDone,
53   };
54 
55   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
56   ~CXFA_ContentLayoutProcessor();
57 
58   void Trace(cppgc::Visitor* visitor) const;
GetHeap()59   cppgc::Heap* GetHeap() const { return m_pHeap; }
60 
61   Result DoLayout(bool bUseBreakControl, float fHeightLimit, float fRealHeight);
62   void DoLayoutPageArea(CXFA_ViewLayoutItem* pPageAreaLayoutItem);
63 
GetFormNode()64   CXFA_Node* GetFormNode() { return m_pFormNode; }
65   CXFA_ContentLayoutItem* ExtractLayoutItem();
66 
67  private:
68   class Context {
69     CPPGC_STACK_ALLOCATED();  // Allows Raw/Unowned pointers.
70 
71    public:
72     Context();
73     ~Context();
74 
75     absl::optional<float> m_fCurColumnWidth;
76     UnownedPtr<std::vector<float>> m_prgSpecifiedColumnWidths;
77     UnownedPtr<CXFA_ContentLayoutProcessor> m_pOverflowProcessor;  // OK, stack
78     UnownedPtr<CXFA_Node> m_pOverflowNode;                         // Ok, stack
79   };
80 
81   CXFA_ContentLayoutProcessor(cppgc::Heap* pHeap,
82                               CXFA_Node* pNode,
83                               CXFA_ViewLayoutProcessor* pViewLayoutProcessor);
84 
85   Result DoLayoutInternal(bool bUseBreakControl,
86                           float fHeightLimit,
87                           float fRealHeight,
88                           Context* pContext);
89 
90   CFX_SizeF GetCurrentComponentSize();
HasLayoutItem()91   bool HasLayoutItem() const { return !!m_pLayoutItem; }
92   void SplitLayoutItem(float fSplitPos);
93   float FindSplitPos(float fProposedSplitPos);
94   bool ProcessKeepForSplit(
95       CXFA_ContentLayoutProcessor* pChildProcessor,
96       Result eRetValue,
97       std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>*
98           rgCurLineLayoutItem,
99       float* fContentCurRowAvailWidth,
100       float* fContentCurRowHeight,
101       float* fContentCurRowY,
102       bool* bAddedItemInRow,
103       bool* bForceEndPage,
104       Result* result);
105   void ProcessUnUseOverFlow(CXFA_Node* pLeaderNode,
106                             CXFA_Node* pTrailerNode,
107                             CXFA_ContentLayoutItem* pTrailerItem,
108                             CXFA_Node* pFormNode);
109   bool IsAddNewRowForTrailer(CXFA_ContentLayoutItem* pTrailerItem);
110   bool JudgeLeaderOrTrailerForOccur(CXFA_Node* pFormNode);
111 
112   // Object comes from GCed heap.
113   CXFA_ContentLayoutItem* CreateContentLayoutItem(CXFA_Node* pFormNode);
114 
115   void SetCurrentComponentPos(const CFX_PointF& pos);
116   void SetCurrentComponentSize(const CFX_SizeF& size);
117 
118   void SplitLayoutItem(CXFA_ContentLayoutItem* pLayoutItem,
119                        CXFA_ContentLayoutItem* pSecondParent,
120                        float fSplitPos);
121   float InsertKeepLayoutItems();
122   bool CalculateRowChildPosition(
123       std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> (
124           &rgCurLineLayoutItems)[3],
125       XFA_AttributeValue eFlowStrategy,
126       bool bContainerHeightAutoSize,
127       bool bContainerWidthAutoSize,
128       float* fContentCalculatedWidth,
129       float* fContentCalculatedHeight,
130       float* fContentCurRowY,
131       float fContentCurRowHeight,
132       float fContentWidthLimit,
133       bool bRootForceTb);
134   void ProcessUnUseBinds(CXFA_Node* pFormNode);
135   bool JudgePutNextPage(CXFA_ContentLayoutItem* pParentLayoutItem,
136                         float fChildHeight,
137                         std::vector<CXFA_ContentLayoutItem*>* pKeepItems);
138 
139   void DoLayoutPositionedContainer(Context* pContext);
140   void DoLayoutTableContainer(CXFA_Node* pLayoutNode);
141   Result DoLayoutFlowedContainer(bool bUseBreakControl,
142                                  XFA_AttributeValue eFlowStrategy,
143                                  float fHeightLimit,
144                                  float fRealHeight,
145                                  Context* pContext,
146                                  bool bRootForceTb);
147   void DoLayoutField();
148 
149   void GotoNextContainerNodeSimple();
150 
151   // Return new stage and new action node.
152   std::pair<Stage, CXFA_Node*> GotoNextContainerNode(
153       Stage nCurStage,
154       CXFA_Node* pParentContainer,
155       CXFA_Node* pCurActionNode);
156 
157   absl::optional<Stage> ProcessKeepNodesForCheckNext(CXFA_Node** pCurActionNode,
158                                                      CXFA_Node** pNextContainer,
159                                                      bool* pLastKeepNode);
160 
161   absl::optional<Stage> ProcessKeepNodesForBreakBefore(
162       CXFA_Node** pCurActionNode,
163       CXFA_Node* pContainerNode);
164 
165   CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet);
166 
167   void UpdatePendingItemLayout(CXFA_ContentLayoutItem* pLayoutItem);
168   void AddTrailerBeforeSplit(float fSplitPos,
169                              CXFA_ContentLayoutItem* pTrailerLayoutItem,
170                              bool bUseInherited);
171   void AddLeaderAfterSplit(CXFA_ContentLayoutItem* pLeaderLayoutItem);
172   void AddPendingNode(CXFA_Node* pPendingNode, bool bBreakPending);
173   float InsertPendingItems(CXFA_Node* pCurChildNode);
174   Result InsertFlowedItem(
175       CXFA_ContentLayoutProcessor* pProcessor,
176       bool bContainerWidthAutoSize,
177       bool bContainerHeightAutoSize,
178       float fContainerHeight,
179       XFA_AttributeValue eFlowStrategy,
180       uint8_t* uCurHAlignState,
181       std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> (
182           &rgCurLineLayoutItems)[3],
183       bool bUseBreakControl,
184       float fAvailHeight,
185       float fRealHeight,
186       float fContentWidthLimit,
187       float* fContentCurRowY,
188       float* fContentCurRowAvailWidth,
189       float* fContentCurRowHeight,
190       bool* bAddedItemInRow,
191       bool* bForceEndPage,
192       Context* pLayoutContext,
193       bool bNewRow);
194 
195   absl::optional<Stage> HandleKeep(CXFA_Node* pBreakAfterNode,
196                                    CXFA_Node** pCurActionNode);
197   absl::optional<Stage> HandleBookendLeader(CXFA_Node* pParentContainer,
198                                             CXFA_Node** pCurActionNode);
199   absl::optional<Stage> HandleBreakBefore(CXFA_Node* pChildContainer,
200                                           CXFA_Node** pCurActionNode);
201   absl::optional<Stage> HandleBreakAfter(CXFA_Node* pChildContainer,
202                                          CXFA_Node** pCurActionNode);
203   absl::optional<Stage> HandleCheckNextChildContainer(
204       CXFA_Node* pParentContainer,
205       CXFA_Node* pChildContainer,
206       CXFA_Node** pCurActionNode);
207   absl::optional<Stage> HandleBookendTrailer(CXFA_Node* pParentContainer,
208                                              CXFA_Node** pCurActionNode);
209   void ProcessKeepNodesEnd();
210   void AdjustContainerSpecifiedSize(Context* pContext,
211                                     CFX_SizeF* pSize,
212                                     bool* pContainerWidthAutoSize,
213                                     bool* pContainerHeightAutoSize);
214   CXFA_ContentLayoutItem* FindLastContentLayoutItem(
215       XFA_AttributeValue eFlowStrategy);
216   CFX_SizeF CalculateLayoutItemSize(const CXFA_ContentLayoutItem* pLayoutChild);
217 
218   Stage m_nCurChildNodeStage = Stage::kNone;
219   Result m_ePreProcessRs = Result::kDone;
220   bool m_bBreakPending = true;
221   bool m_bUseInherited = false;
222   bool m_bKeepBreakFinish = false;
223   bool m_bIsProcessKeep = false;
224   bool m_bHasAvailHeight = true;
225   float m_fUsedSize = 0;
226   float m_fLastRowWidth = 0;
227   float m_fLastRowY = 0;
228   float m_fWidthLimit = 0;
229   UnownedPtr<cppgc::Heap> m_pHeap;
230   cppgc::Member<CXFA_Node> const m_pFormNode;
231   cppgc::Member<CXFA_Node> m_pCurChildNode;
232   cppgc::Member<CXFA_Node> m_pKeepHeadNode;
233   cppgc::Member<CXFA_Node> m_pKeepTailNode;
234   cppgc::Member<CXFA_ContentLayoutItem> m_pLayoutItem;
235   cppgc::Member<CXFA_ContentLayoutItem> m_pOldLayoutItem;
236   cppgc::Member<CXFA_ViewLayoutProcessor> m_pViewLayoutProcessor;
237   std::vector<float> m_rgSpecifiedColumnWidths;
238   std::vector<cppgc::Member<CXFA_ContentLayoutItem>> m_ArrayKeepItems;
239   std::list<cppgc::Member<CXFA_Node>> m_PendingNodes;
240   std::map<cppgc::Member<CXFA_Node>, int32_t> m_PendingNodesCount;
241   cppgc::Member<CXFA_ContentLayoutProcessor> m_pCurChildPreprocessor;
242 };
243 
244 #endif  // XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_
245