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