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