1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsBlockReflowState.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,288 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* state used in reflow of block frames */ 1.10 + 1.11 +#ifndef nsBlockReflowState_h__ 1.12 +#define nsBlockReflowState_h__ 1.13 + 1.14 +#include "nsFloatManager.h" 1.15 +#include "nsLineBox.h" 1.16 +#include "nsHTMLReflowState.h" 1.17 + 1.18 +class nsBlockFrame; 1.19 +class nsFrameList; 1.20 +class nsOverflowContinuationTracker; 1.21 + 1.22 + // block reflow state flags 1.23 +#define BRS_UNCONSTRAINEDHEIGHT 0x00000001 1.24 +#define BRS_ISTOPMARGINROOT 0x00000002 // Is this frame a root for top/bottom margin collapsing? 1.25 +#define BRS_ISBOTTOMMARGINROOT 0x00000004 1.26 +#define BRS_APPLYTOPMARGIN 0x00000008 // See ShouldApplyTopMargin 1.27 +#define BRS_ISFIRSTINFLOW 0x00000010 1.28 +// Set when mLineAdjacentToTop is valid 1.29 +#define BRS_HAVELINEADJACENTTOTOP 0x00000020 1.30 +// Set when the block has the equivalent of NS_BLOCK_FLOAT_MGR 1.31 +#define BRS_FLOAT_MGR 0x00000040 1.32 +// Set when nsLineLayout::LineIsEmpty was true at the end of reflowing 1.33 +// the current line 1.34 +#define BRS_LINE_LAYOUT_EMPTY 0x00000080 1.35 +#define BRS_ISOVERFLOWCONTAINER 0x00000100 1.36 +// Our mPushedFloats list is stored on the blocks' proptable 1.37 +#define BRS_PROPTABLE_FLOATCLIST 0x00000200 1.38 +#define BRS_LASTFLAG BRS_PROPTABLE_FLOATCLIST 1.39 + 1.40 +class nsBlockReflowState { 1.41 +public: 1.42 + nsBlockReflowState(const nsHTMLReflowState& aReflowState, 1.43 + nsPresContext* aPresContext, 1.44 + nsBlockFrame* aFrame, 1.45 + bool aTopMarginRoot, bool aBottomMarginRoot, 1.46 + bool aBlockNeedsFloatManager, 1.47 + nscoord aConsumedHeight = NS_INTRINSICSIZE); 1.48 + 1.49 + /** 1.50 + * Get the available reflow space (the area not occupied by floats) 1.51 + * for the current y coordinate. The available space is relative to 1.52 + * our coordinate system, which is the content box, with (0, 0) in the 1.53 + * upper left. 1.54 + * 1.55 + * Returns whether there are floats present at the given vertical 1.56 + * coordinate and within the width of the content rect. 1.57 + */ 1.58 + nsFlowAreaRect GetFloatAvailableSpace() const 1.59 + { return GetFloatAvailableSpace(mY); } 1.60 + nsFlowAreaRect GetFloatAvailableSpace(nscoord aY) const 1.61 + { return GetFloatAvailableSpaceWithState(aY, nullptr); } 1.62 + nsFlowAreaRect 1.63 + GetFloatAvailableSpaceWithState(nscoord aY, 1.64 + nsFloatManager::SavedState *aState) const; 1.65 + nsFlowAreaRect 1.66 + GetFloatAvailableSpaceForHeight(nscoord aY, nscoord aHeight, 1.67 + nsFloatManager::SavedState *aState) const; 1.68 + 1.69 + /* 1.70 + * The following functions all return true if they were able to 1.71 + * place the float, false if the float did not fit in available 1.72 + * space. 1.73 + * aLineLayout is null when we are reflowing pushed floats (because 1.74 + * they are not associated with a line box). 1.75 + */ 1.76 + bool AddFloat(nsLineLayout* aLineLayout, 1.77 + nsIFrame* aFloat, 1.78 + nscoord aAvailableWidth); 1.79 +private: 1.80 + bool CanPlaceFloat(nscoord aFloatWidth, 1.81 + const nsFlowAreaRect& aFloatAvailableSpace); 1.82 +public: 1.83 + bool FlowAndPlaceFloat(nsIFrame* aFloat); 1.84 +private: 1.85 + void PushFloatPastBreak(nsIFrame* aFloat); 1.86 +public: 1.87 + void PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats, 1.88 + nsLineBox* aLine); 1.89 + 1.90 + // Returns the first coordinate >= aY that clears the 1.91 + // floats indicated by aBreakType and has enough width between floats 1.92 + // (or no floats remaining) to accomodate aReplacedBlock. 1.93 + nscoord ClearFloats(nscoord aY, uint8_t aBreakType, 1.94 + nsIFrame *aReplacedBlock = nullptr, 1.95 + uint32_t aFlags = 0); 1.96 + 1.97 + bool IsAdjacentWithTop() const { 1.98 + return mY == 1.99 + ((mFlags & BRS_ISFIRSTINFLOW) ? mReflowState.ComputedPhysicalBorderPadding().top : 0); 1.100 + } 1.101 + 1.102 + /** 1.103 + * Adjusts the border/padding to return 0 for the top if 1.104 + * we are not the first in flow. 1.105 + */ 1.106 + nsMargin BorderPadding() const { 1.107 + nsMargin result = mReflowState.ComputedPhysicalBorderPadding(); 1.108 + if (!(mFlags & BRS_ISFIRSTINFLOW)) { 1.109 + result.top = 0; 1.110 + if (mFlags & BRS_ISOVERFLOWCONTAINER) { 1.111 + result.bottom = 0; 1.112 + } 1.113 + } 1.114 + return result; 1.115 + } 1.116 + 1.117 + /** 1.118 + * Retrieve the height "consumed" by any previous-in-flows. 1.119 + */ 1.120 + nscoord GetConsumedHeight(); 1.121 + 1.122 + // Reconstruct the previous bottom margin that goes above |aLine|. 1.123 + void ReconstructMarginAbove(nsLineList::iterator aLine); 1.124 + 1.125 + // Caller must have called GetAvailableSpace for the correct position 1.126 + // (which need not be the current mY). 1.127 + void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame, 1.128 + const nsRect& aFloatAvailableSpace, 1.129 + nscoord& aLeftResult, 1.130 + nscoord& aRightResult); 1.131 + 1.132 + // Caller must have called GetAvailableSpace for the current mY 1.133 + void ComputeBlockAvailSpace(nsIFrame* aFrame, 1.134 + const nsStyleDisplay* aDisplay, 1.135 + const nsFlowAreaRect& aFloatAvailableSpace, 1.136 + bool aBlockAvoidsFloats, 1.137 + nsRect& aResult); 1.138 + 1.139 +protected: 1.140 + void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaY); 1.141 + 1.142 +public: 1.143 + void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY); 1.144 + 1.145 + void AdvanceToNextLine() { 1.146 + if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) { 1.147 + SetFlag(BRS_LINE_LAYOUT_EMPTY, false); 1.148 + } else { 1.149 + mLineNumber++; 1.150 + } 1.151 + } 1.152 + 1.153 + //---------------------------------------- 1.154 + 1.155 + // This state is the "global" state computed once for the reflow of 1.156 + // the block. 1.157 + 1.158 + // The block frame that is using this object 1.159 + nsBlockFrame* mBlock; 1.160 + 1.161 + nsPresContext* mPresContext; 1.162 + 1.163 + const nsHTMLReflowState& mReflowState; 1.164 + 1.165 + nsFloatManager* mFloatManager; 1.166 + 1.167 + // The coordinates within the float manager where the block is being 1.168 + // placed <b>after</b> taking into account the blocks border and 1.169 + // padding. This, therefore, represents the inner "content area" (in 1.170 + // spacemanager coordinates) where child frames will be placed, 1.171 + // including child blocks and floats. 1.172 + nscoord mFloatManagerX, mFloatManagerY; 1.173 + 1.174 + // XXX get rid of this 1.175 + nsReflowStatus mReflowStatus; 1.176 + 1.177 + // The float manager state as it was before the contents of this 1.178 + // block. This is needed for positioning bullets, since we only want 1.179 + // to move the bullet to flow around floats that were before this 1.180 + // block, not floats inside of it. 1.181 + nsFloatManager::SavedState mFloatManagerStateBefore; 1.182 + 1.183 + nscoord mBottomEdge; 1.184 + 1.185 + // The content area to reflow child frames within. This is within 1.186 + // this frame's coordinate system, which means mContentArea.x == 1.187 + // BorderPadding().left and mContentArea.y == BorderPadding().top. 1.188 + // The height may be NS_UNCONSTRAINEDSIZE, which indicates that there 1.189 + // is no page/column boundary below (the common case). 1.190 + // mContentArea.YMost() should only be called after checking that 1.191 + // mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise 1.192 + // coordinate overflow may occur. 1.193 + nsRect mContentArea; 1.194 + nscoord mContainerWidth; 1.195 + 1.196 + // Continuation out-of-flow float frames that need to move to our 1.197 + // next in flow are placed here during reflow. It's a pointer to 1.198 + // a frame list stored in the block's property table. 1.199 + nsFrameList *mPushedFloats; 1.200 + // This method makes sure pushed floats are accessible to 1.201 + // StealFrame. Call it before adding any frames to mPushedFloats. 1.202 + void SetupPushedFloatList(); 1.203 + // Use this method to append to mPushedFloats. 1.204 + void AppendPushedFloat(nsIFrame* aFloatCont); 1.205 + 1.206 + // Track child overflow continuations. 1.207 + nsOverflowContinuationTracker* mOverflowTracker; 1.208 + 1.209 + //---------------------------------------- 1.210 + 1.211 + // This state is "running" state updated by the reflow of each line 1.212 + // in the block. This same state is "recovered" when a line is not 1.213 + // dirty and is passed over during incremental reflow. 1.214 + 1.215 + // The current line being reflowed 1.216 + // If it is mBlock->end_lines(), then it is invalid. 1.217 + nsLineList::iterator mCurrentLine; 1.218 + 1.219 + // When BRS_HAVELINEADJACENTTOTOP is set, this refers to a line 1.220 + // which we know is adjacent to the top of the block (in other words, 1.221 + // all lines before it are empty and do not have clearance. This line is 1.222 + // always before the current line. 1.223 + nsLineList::iterator mLineAdjacentToTop; 1.224 + 1.225 + // The current Y coordinate in the block 1.226 + nscoord mY; 1.227 + 1.228 + // The overflow areas of all floats placed so far 1.229 + nsOverflowAreas mFloatOverflowAreas; 1.230 + 1.231 + nsFloatCacheFreeList mFloatCacheFreeList; 1.232 + 1.233 + // Previous child. This is used when pulling up a frame to update 1.234 + // the sibling list. 1.235 + nsIFrame* mPrevChild; 1.236 + 1.237 + // The previous child frames collapsed bottom margin value. 1.238 + nsCollapsingMargin mPrevBottomMargin; 1.239 + 1.240 + // The current next-in-flow for the block. When lines are pulled 1.241 + // from a next-in-flow, this is used to know which next-in-flow to 1.242 + // pull from. When a next-in-flow is emptied of lines, we advance 1.243 + // this to the next next-in-flow. 1.244 + nsBlockFrame* mNextInFlow; 1.245 + 1.246 + //---------------------------------------- 1.247 + 1.248 + // Temporary line-reflow state. This state is used during the reflow 1.249 + // of a given line, but doesn't have meaning before or after. 1.250 + 1.251 + // The list of floats that are "current-line" floats. These are 1.252 + // added to the line after the line has been reflowed, to keep the 1.253 + // list fiddling from being N^2. 1.254 + nsFloatCacheFreeList mCurrentLineFloats; 1.255 + 1.256 + // The list of floats which are "below current-line" 1.257 + // floats. These are reflowed/placed after the line is reflowed 1.258 + // and placed. Again, this is done to keep the list fiddling from 1.259 + // being N^2. 1.260 + nsFloatCacheFreeList mBelowCurrentLineFloats; 1.261 + 1.262 + nscoord mMinLineHeight; 1.263 + 1.264 + int32_t mLineNumber; 1.265 + 1.266 + int16_t mFlags; 1.267 + 1.268 + uint8_t mFloatBreakType; 1.269 + 1.270 + // The amount of computed height "consumed" by previous-in-flows. 1.271 + nscoord mConsumedHeight; 1.272 + 1.273 + void SetFlag(uint32_t aFlag, bool aValue) 1.274 + { 1.275 + NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag"); 1.276 + if (aValue) { // set flag 1.277 + mFlags |= aFlag; 1.278 + } 1.279 + else { // unset flag 1.280 + mFlags &= ~aFlag; 1.281 + } 1.282 + } 1.283 + 1.284 + bool GetFlag(uint32_t aFlag) const 1.285 + { 1.286 + NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag"); 1.287 + return !!(mFlags & aFlag); 1.288 + } 1.289 +}; 1.290 + 1.291 +#endif // nsBlockReflowState_h__