Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* state used in reflow of block frames */
8 #ifndef nsBlockReflowState_h__
9 #define nsBlockReflowState_h__
11 #include "nsFloatManager.h"
12 #include "nsLineBox.h"
13 #include "nsHTMLReflowState.h"
15 class nsBlockFrame;
16 class nsFrameList;
17 class nsOverflowContinuationTracker;
19 // block reflow state flags
20 #define BRS_UNCONSTRAINEDHEIGHT 0x00000001
21 #define BRS_ISTOPMARGINROOT 0x00000002 // Is this frame a root for top/bottom margin collapsing?
22 #define BRS_ISBOTTOMMARGINROOT 0x00000004
23 #define BRS_APPLYTOPMARGIN 0x00000008 // See ShouldApplyTopMargin
24 #define BRS_ISFIRSTINFLOW 0x00000010
25 // Set when mLineAdjacentToTop is valid
26 #define BRS_HAVELINEADJACENTTOTOP 0x00000020
27 // Set when the block has the equivalent of NS_BLOCK_FLOAT_MGR
28 #define BRS_FLOAT_MGR 0x00000040
29 // Set when nsLineLayout::LineIsEmpty was true at the end of reflowing
30 // the current line
31 #define BRS_LINE_LAYOUT_EMPTY 0x00000080
32 #define BRS_ISOVERFLOWCONTAINER 0x00000100
33 // Our mPushedFloats list is stored on the blocks' proptable
34 #define BRS_PROPTABLE_FLOATCLIST 0x00000200
35 #define BRS_LASTFLAG BRS_PROPTABLE_FLOATCLIST
37 class nsBlockReflowState {
38 public:
39 nsBlockReflowState(const nsHTMLReflowState& aReflowState,
40 nsPresContext* aPresContext,
41 nsBlockFrame* aFrame,
42 bool aTopMarginRoot, bool aBottomMarginRoot,
43 bool aBlockNeedsFloatManager,
44 nscoord aConsumedHeight = NS_INTRINSICSIZE);
46 /**
47 * Get the available reflow space (the area not occupied by floats)
48 * for the current y coordinate. The available space is relative to
49 * our coordinate system, which is the content box, with (0, 0) in the
50 * upper left.
51 *
52 * Returns whether there are floats present at the given vertical
53 * coordinate and within the width of the content rect.
54 */
55 nsFlowAreaRect GetFloatAvailableSpace() const
56 { return GetFloatAvailableSpace(mY); }
57 nsFlowAreaRect GetFloatAvailableSpace(nscoord aY) const
58 { return GetFloatAvailableSpaceWithState(aY, nullptr); }
59 nsFlowAreaRect
60 GetFloatAvailableSpaceWithState(nscoord aY,
61 nsFloatManager::SavedState *aState) const;
62 nsFlowAreaRect
63 GetFloatAvailableSpaceForHeight(nscoord aY, nscoord aHeight,
64 nsFloatManager::SavedState *aState) const;
66 /*
67 * The following functions all return true if they were able to
68 * place the float, false if the float did not fit in available
69 * space.
70 * aLineLayout is null when we are reflowing pushed floats (because
71 * they are not associated with a line box).
72 */
73 bool AddFloat(nsLineLayout* aLineLayout,
74 nsIFrame* aFloat,
75 nscoord aAvailableWidth);
76 private:
77 bool CanPlaceFloat(nscoord aFloatWidth,
78 const nsFlowAreaRect& aFloatAvailableSpace);
79 public:
80 bool FlowAndPlaceFloat(nsIFrame* aFloat);
81 private:
82 void PushFloatPastBreak(nsIFrame* aFloat);
83 public:
84 void PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats,
85 nsLineBox* aLine);
87 // Returns the first coordinate >= aY that clears the
88 // floats indicated by aBreakType and has enough width between floats
89 // (or no floats remaining) to accomodate aReplacedBlock.
90 nscoord ClearFloats(nscoord aY, uint8_t aBreakType,
91 nsIFrame *aReplacedBlock = nullptr,
92 uint32_t aFlags = 0);
94 bool IsAdjacentWithTop() const {
95 return mY ==
96 ((mFlags & BRS_ISFIRSTINFLOW) ? mReflowState.ComputedPhysicalBorderPadding().top : 0);
97 }
99 /**
100 * Adjusts the border/padding to return 0 for the top if
101 * we are not the first in flow.
102 */
103 nsMargin BorderPadding() const {
104 nsMargin result = mReflowState.ComputedPhysicalBorderPadding();
105 if (!(mFlags & BRS_ISFIRSTINFLOW)) {
106 result.top = 0;
107 if (mFlags & BRS_ISOVERFLOWCONTAINER) {
108 result.bottom = 0;
109 }
110 }
111 return result;
112 }
114 /**
115 * Retrieve the height "consumed" by any previous-in-flows.
116 */
117 nscoord GetConsumedHeight();
119 // Reconstruct the previous bottom margin that goes above |aLine|.
120 void ReconstructMarginAbove(nsLineList::iterator aLine);
122 // Caller must have called GetAvailableSpace for the correct position
123 // (which need not be the current mY).
124 void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
125 const nsRect& aFloatAvailableSpace,
126 nscoord& aLeftResult,
127 nscoord& aRightResult);
129 // Caller must have called GetAvailableSpace for the current mY
130 void ComputeBlockAvailSpace(nsIFrame* aFrame,
131 const nsStyleDisplay* aDisplay,
132 const nsFlowAreaRect& aFloatAvailableSpace,
133 bool aBlockAvoidsFloats,
134 nsRect& aResult);
136 protected:
137 void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaY);
139 public:
140 void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY);
142 void AdvanceToNextLine() {
143 if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) {
144 SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
145 } else {
146 mLineNumber++;
147 }
148 }
150 //----------------------------------------
152 // This state is the "global" state computed once for the reflow of
153 // the block.
155 // The block frame that is using this object
156 nsBlockFrame* mBlock;
158 nsPresContext* mPresContext;
160 const nsHTMLReflowState& mReflowState;
162 nsFloatManager* mFloatManager;
164 // The coordinates within the float manager where the block is being
165 // placed <b>after</b> taking into account the blocks border and
166 // padding. This, therefore, represents the inner "content area" (in
167 // spacemanager coordinates) where child frames will be placed,
168 // including child blocks and floats.
169 nscoord mFloatManagerX, mFloatManagerY;
171 // XXX get rid of this
172 nsReflowStatus mReflowStatus;
174 // The float manager state as it was before the contents of this
175 // block. This is needed for positioning bullets, since we only want
176 // to move the bullet to flow around floats that were before this
177 // block, not floats inside of it.
178 nsFloatManager::SavedState mFloatManagerStateBefore;
180 nscoord mBottomEdge;
182 // The content area to reflow child frames within. This is within
183 // this frame's coordinate system, which means mContentArea.x ==
184 // BorderPadding().left and mContentArea.y == BorderPadding().top.
185 // The height may be NS_UNCONSTRAINEDSIZE, which indicates that there
186 // is no page/column boundary below (the common case).
187 // mContentArea.YMost() should only be called after checking that
188 // mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise
189 // coordinate overflow may occur.
190 nsRect mContentArea;
191 nscoord mContainerWidth;
193 // Continuation out-of-flow float frames that need to move to our
194 // next in flow are placed here during reflow. It's a pointer to
195 // a frame list stored in the block's property table.
196 nsFrameList *mPushedFloats;
197 // This method makes sure pushed floats are accessible to
198 // StealFrame. Call it before adding any frames to mPushedFloats.
199 void SetupPushedFloatList();
200 // Use this method to append to mPushedFloats.
201 void AppendPushedFloat(nsIFrame* aFloatCont);
203 // Track child overflow continuations.
204 nsOverflowContinuationTracker* mOverflowTracker;
206 //----------------------------------------
208 // This state is "running" state updated by the reflow of each line
209 // in the block. This same state is "recovered" when a line is not
210 // dirty and is passed over during incremental reflow.
212 // The current line being reflowed
213 // If it is mBlock->end_lines(), then it is invalid.
214 nsLineList::iterator mCurrentLine;
216 // When BRS_HAVELINEADJACENTTOTOP is set, this refers to a line
217 // which we know is adjacent to the top of the block (in other words,
218 // all lines before it are empty and do not have clearance. This line is
219 // always before the current line.
220 nsLineList::iterator mLineAdjacentToTop;
222 // The current Y coordinate in the block
223 nscoord mY;
225 // The overflow areas of all floats placed so far
226 nsOverflowAreas mFloatOverflowAreas;
228 nsFloatCacheFreeList mFloatCacheFreeList;
230 // Previous child. This is used when pulling up a frame to update
231 // the sibling list.
232 nsIFrame* mPrevChild;
234 // The previous child frames collapsed bottom margin value.
235 nsCollapsingMargin mPrevBottomMargin;
237 // The current next-in-flow for the block. When lines are pulled
238 // from a next-in-flow, this is used to know which next-in-flow to
239 // pull from. When a next-in-flow is emptied of lines, we advance
240 // this to the next next-in-flow.
241 nsBlockFrame* mNextInFlow;
243 //----------------------------------------
245 // Temporary line-reflow state. This state is used during the reflow
246 // of a given line, but doesn't have meaning before or after.
248 // The list of floats that are "current-line" floats. These are
249 // added to the line after the line has been reflowed, to keep the
250 // list fiddling from being N^2.
251 nsFloatCacheFreeList mCurrentLineFloats;
253 // The list of floats which are "below current-line"
254 // floats. These are reflowed/placed after the line is reflowed
255 // and placed. Again, this is done to keep the list fiddling from
256 // being N^2.
257 nsFloatCacheFreeList mBelowCurrentLineFloats;
259 nscoord mMinLineHeight;
261 int32_t mLineNumber;
263 int16_t mFlags;
265 uint8_t mFloatBreakType;
267 // The amount of computed height "consumed" by previous-in-flows.
268 nscoord mConsumedHeight;
270 void SetFlag(uint32_t aFlag, bool aValue)
271 {
272 NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
273 if (aValue) { // set flag
274 mFlags |= aFlag;
275 }
276 else { // unset flag
277 mFlags &= ~aFlag;
278 }
279 }
281 bool GetFlag(uint32_t aFlag) const
282 {
283 NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
284 return !!(mFlags & aFlag);
285 }
286 };
288 #endif // nsBlockReflowState_h__