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