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 <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/base/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_ContentLayoutProcessor; 31 class CXFA_LayoutProcessor; 32 class CXFA_Node; 33 class CXFA_ViewLayoutItem; 34 class CXFA_ViewLayoutProcessor; 35 36 class CXFA_ContentLayoutProcessor 37 : public cppgc::GarbageCollected<CXFA_ContentLayoutProcessor> { 38 public: 39 enum class Result : uint8_t { 40 kDone, 41 kPageFullBreak, 42 kRowFullBreak, 43 kManualBreak, 44 }; 45 46 enum class Stage : uint8_t { 47 kNone, 48 kBookendLeader, 49 kBreakBefore, 50 kKeep, 51 kContainer, 52 kBreakAfter, 53 kBookendTrailer, 54 kDone, 55 }; 56 57 CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; 58 ~CXFA_ContentLayoutProcessor(); 59 60 void Trace(cppgc::Visitor* visitor) const; GetHeap()61 cppgc::Heap* GetHeap() const { return m_pHeap.Get(); } 62 63 Result DoLayout(bool bUseBreakControl, float fHeightLimit, float fRealHeight); 64 void DoLayoutPageArea(CXFA_ViewLayoutItem* pPageAreaLayoutItem); 65 GetFormNode()66 CXFA_Node* GetFormNode() { return m_pFormNode; } 67 CXFA_ContentLayoutItem* ExtractLayoutItem(); 68 69 private: 70 class Context { 71 CPPGC_STACK_ALLOCATED(); // Allows Raw/Unowned pointers. 72 73 public: 74 Context(); 75 ~Context(); 76 77 Optional<float> m_fCurColumnWidth; 78 UnownedPtr<std::vector<float>> m_prgSpecifiedColumnWidths; 79 UnownedPtr<CXFA_ContentLayoutProcessor> m_pOverflowProcessor; // OK, stack 80 UnownedPtr<CXFA_Node> m_pOverflowNode; // Ok, stack 81 }; 82 83 CXFA_ContentLayoutProcessor(cppgc::Heap* pHeap, 84 CXFA_Node* pNode, 85 CXFA_ViewLayoutProcessor* pViewLayoutProcessor); 86 87 Result DoLayoutInternal(bool bUseBreakControl, 88 float fHeightLimit, 89 float fRealHeight, 90 Context* pContext); 91 92 CFX_SizeF GetCurrentComponentSize(); HasLayoutItem()93 bool HasLayoutItem() const { return !!m_pLayoutItem; } 94 void SplitLayoutItem(float fSplitPos); 95 float FindSplitPos(float fProposedSplitPos); 96 bool ProcessKeepForSplit( 97 CXFA_ContentLayoutProcessor* pChildProcessor, 98 Result eRetValue, 99 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>* 100 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::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> ( 126 &rgCurLineLayoutItems)[3], 127 XFA_AttributeValue eFlowStrategy, 128 bool bContainerHeightAutoSize, 129 bool bContainerWidthAutoSize, 130 float* fContentCalculatedWidth, 131 float* fContentCalculatedHeight, 132 float* fContentCurRowY, 133 float fContentCurRowHeight, 134 float fContentWidthLimit, 135 bool bRootForceTb); 136 void ProcessUnUseBinds(CXFA_Node* pFormNode); 137 bool JudgePutNextPage(CXFA_ContentLayoutItem* pParentLayoutItem, 138 float fChildHeight, 139 std::vector<CXFA_ContentLayoutItem*>* pKeepItems); 140 141 void DoLayoutPositionedContainer(Context* pContext); 142 void DoLayoutTableContainer(CXFA_Node* pLayoutNode); 143 Result DoLayoutFlowedContainer(bool bUseBreakControl, 144 XFA_AttributeValue eFlowStrategy, 145 float fHeightLimit, 146 float fRealHeight, 147 Context* pContext, 148 bool bRootForceTb); 149 void DoLayoutField(); 150 151 void GotoNextContainerNodeSimple(bool bUsePageBreak); 152 153 // Return new stage and new action node. 154 std::pair<Stage, CXFA_Node*> GotoNextContainerNode( 155 Stage nCurStage, 156 bool bUsePageBreak, 157 CXFA_Node* pParentContainer, 158 CXFA_Node* pCurActionNode); 159 160 Optional<Stage> ProcessKeepNodesForCheckNext(CXFA_Node** pCurActionNode, 161 CXFA_Node** pNextContainer, 162 bool* pLastKeepNode); 163 164 Optional<Stage> ProcessKeepNodesForBreakBefore(CXFA_Node** pCurActionNode, 165 CXFA_Node* pContainerNode); 166 167 CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet); 168 169 void UpdatePendingItemLayout(CXFA_ContentLayoutItem* pLayoutItem); 170 void AddTrailerBeforeSplit(float fSplitPos, 171 CXFA_ContentLayoutItem* pTrailerLayoutItem, 172 bool bUseInherited); 173 void AddLeaderAfterSplit(CXFA_ContentLayoutItem* pLeaderLayoutItem); 174 void AddPendingNode(CXFA_Node* pPendingNode, bool bBreakPending); 175 float InsertPendingItems(CXFA_Node* pCurChildNode); 176 Result InsertFlowedItem( 177 CXFA_ContentLayoutProcessor* pProcessor, 178 bool bContainerWidthAutoSize, 179 bool bContainerHeightAutoSize, 180 float fContainerHeight, 181 XFA_AttributeValue eFlowStrategy, 182 uint8_t* uCurHAlignState, 183 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> ( 184 &rgCurLineLayoutItems)[3], 185 bool bUseBreakControl, 186 float fAvailHeight, 187 float fRealHeight, 188 float fContentWidthLimit, 189 float* fContentCurRowY, 190 float* fContentCurRowAvailWidth, 191 float* fContentCurRowHeight, 192 bool* bAddedItemInRow, 193 bool* bForceEndPage, 194 Context* pLayoutContext, 195 bool bNewRow); 196 197 Optional<Stage> HandleKeep(CXFA_Node* pBreakAfterNode, 198 CXFA_Node** pCurActionNode); 199 Optional<Stage> HandleBookendLeader(CXFA_Node* pParentContainer, 200 CXFA_Node** pCurActionNode); 201 Optional<Stage> HandleBreakBefore(CXFA_Node* pChildContainer, 202 CXFA_Node** pCurActionNode); 203 Optional<Stage> HandleBreakAfter(CXFA_Node* pChildContainer, 204 CXFA_Node** pCurActionNode); 205 Optional<Stage> HandleCheckNextChildContainer(CXFA_Node* pParentContainer, 206 CXFA_Node* pChildContainer, 207 CXFA_Node** pCurActionNode); 208 Optional<Stage> HandleBookendTrailer(CXFA_Node* pParentContainer, 209 CXFA_Node** pCurActionNode); 210 void ProcessKeepNodesEnd(); 211 void AdjustContainerSpecifiedSize(Context* pContext, 212 CFX_SizeF* pSize, 213 bool* pContainerWidthAutoSize, 214 bool* pContainerHeightAutoSize); 215 CXFA_ContentLayoutItem* FindLastContentLayoutItem( 216 XFA_AttributeValue eFlowStrategy); 217 CFX_SizeF CalculateLayoutItemSize(const CXFA_ContentLayoutItem* pLayoutChild); 218 219 Stage m_nCurChildNodeStage = Stage::kNone; 220 Result m_ePreProcessRs = Result::kDone; 221 bool m_bBreakPending = true; 222 bool m_bUseInherited = false; 223 bool m_bKeepBreakFinish = false; 224 bool m_bIsProcessKeep = false; 225 bool m_bHasAvailHeight = true; 226 float m_fUsedSize = 0; 227 float m_fLastRowWidth = 0; 228 float m_fLastRowY = 0; 229 float m_fWidthLimit = 0; 230 UnownedPtr<cppgc::Heap> m_pHeap; 231 cppgc::Member<CXFA_Node> const m_pFormNode; 232 cppgc::Member<CXFA_Node> m_pCurChildNode; 233 cppgc::Member<CXFA_Node> m_pKeepHeadNode; 234 cppgc::Member<CXFA_Node> m_pKeepTailNode; 235 cppgc::Member<CXFA_ContentLayoutItem> m_pLayoutItem; 236 cppgc::Member<CXFA_ContentLayoutItem> m_pOldLayoutItem; 237 cppgc::Member<CXFA_ViewLayoutProcessor> m_pViewLayoutProcessor; 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<CXFA_Node*, int32_t> m_PendingNodesCount; 242 cppgc::Member<CXFA_ContentLayoutProcessor> m_pCurChildPreprocessor; 243 }; 244 245 #endif // XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_ 246