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