This repository has been archived by the owner on Aug 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathnsBlockReflowState.h
342 lines (285 loc) · 12.7 KB
/
nsBlockReflowState.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* state used in reflow of block frames */
#ifndef nsBlockReflowState_h__
#define nsBlockReflowState_h__
#include "nsFloatManager.h"
#include "nsLineBox.h"
#include "nsHTMLReflowState.h"
class nsBlockFrame;
class nsFrameList;
class nsOverflowContinuationTracker;
// block reflow state flags
#define BRS_UNCONSTRAINEDBSIZE 0x00000001
#define BRS_ISBSTARTMARGINROOT 0x00000002 // Is this frame a root for block
#define BRS_ISBENDMARGINROOT 0x00000004 // direction start/end margin collapsing?
#define BRS_APPLYBSTARTMARGIN 0x00000008 // See ShouldApplyTopMargin
#define BRS_ISFIRSTINFLOW 0x00000010
// Set when mLineAdjacentToTop is valid
#define BRS_HAVELINEADJACENTTOTOP 0x00000020
// Set when the block has the equivalent of NS_BLOCK_FLOAT_MGR
#define BRS_FLOAT_MGR 0x00000040
// Set when nsLineLayout::LineIsEmpty was true at the end of reflowing
// the current line
#define BRS_LINE_LAYOUT_EMPTY 0x00000080
#define BRS_ISOVERFLOWCONTAINER 0x00000100
// Our mPushedFloats list is stored on the blocks' proptable
#define BRS_PROPTABLE_FLOATCLIST 0x00000200
// Set when the pref layout.float-fragments-inside-column.enabled is true.
#define BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED 0x00000400
#define BRS_LASTFLAG BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED
class nsBlockReflowState {
public:
nsBlockReflowState(const nsHTMLReflowState& aReflowState,
nsPresContext* aPresContext,
nsBlockFrame* aFrame,
bool aBStartMarginRoot, bool aBEndMarginRoot,
bool aBlockNeedsFloatManager,
nscoord aConsumedBSize = NS_INTRINSICSIZE);
/**
* Get the available reflow space (the area not occupied by floats)
* for the current y coordinate. The available space is relative to
* our coordinate system, which is the content box, with (0, 0) in the
* upper left.
*
* Returns whether there are floats present at the given block-direction
* coordinate and within the inline size of the content rect.
*/
nsFlowAreaRect GetFloatAvailableSpace() const
{ return GetFloatAvailableSpace(mBCoord); }
nsFlowAreaRect GetFloatAvailableSpace(nscoord aBCoord) const
{ return GetFloatAvailableSpaceWithState(aBCoord, nullptr); }
nsFlowAreaRect
GetFloatAvailableSpaceWithState(nscoord aBCoord,
nsFloatManager::SavedState *aState) const;
nsFlowAreaRect
GetFloatAvailableSpaceForBSize(nscoord aBCoord, nscoord aBSize,
nsFloatManager::SavedState *aState) const;
/*
* The following functions all return true if they were able to
* place the float, false if the float did not fit in available
* space.
* aLineLayout is null when we are reflowing pushed floats (because
* they are not associated with a line box).
*/
bool AddFloat(nsLineLayout* aLineLayout,
nsIFrame* aFloat,
nscoord aAvailableISize);
private:
bool CanPlaceFloat(nscoord aFloatISize,
const nsFlowAreaRect& aFloatAvailableSpace);
public:
bool FlowAndPlaceFloat(nsIFrame* aFloat);
private:
void PushFloatPastBreak(nsIFrame* aFloat);
public:
void PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats,
nsLineBox* aLine);
// Returns the first coordinate >= aBCoord that clears the
// floats indicated by aBreakType and has enough inline size between floats
// (or no floats remaining) to accomodate aReplacedBlock.
nscoord ClearFloats(nscoord aBCoord, uint8_t aBreakType,
nsIFrame *aReplacedBlock = nullptr,
uint32_t aFlags = 0);
// Advances to the next band, i.e., the next horizontal stripe in
// which there is a different set of floats.
// Return false if it did not advance, which only happens for
// constrained heights (and means that we should get pushed to the
// next column/page).
bool AdvanceToNextBand(const mozilla::LogicalRect& aFloatAvailableSpace,
nscoord *aBCoord) const {
mozilla::WritingMode wm = mReflowState.GetWritingMode();
if (aFloatAvailableSpace.BSize(wm) > 0) {
// See if there's room in the next band.
*aBCoord += aFloatAvailableSpace.BSize(wm);
} else {
if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
// Stop trying to clear here; we'll just get pushed to the
// next column or page and try again there.
return false;
}
NS_NOTREACHED("avail space rect with zero height!");
*aBCoord += 1;
}
return true;
}
bool ReplacedBlockFitsInAvailSpace(nsIFrame* aReplacedBlock,
const nsFlowAreaRect& aFloatAvailableSpace) const;
bool IsAdjacentWithTop() const {
return mBCoord == mBorderPadding.BStart(mReflowState.GetWritingMode());
}
/**
* Return mBlock's computed physical border+padding with GetSkipSides applied.
*/
const mozilla::LogicalMargin& BorderPadding() const {
return mBorderPadding;
}
/**
* Retrieve the block-direction size "consumed" by any previous-in-flows.
*/
nscoord GetConsumedBSize();
// Reconstruct the previous block-end margin that goes before |aLine|.
void ReconstructMarginBefore(nsLineList::iterator aLine);
// Caller must have called GetAvailableSpace for the correct position
// (which need not be the current mBCoord).
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
const mozilla::LogicalRect& aFloatAvailableSpace,
nscoord& aIStartResult,
nscoord& aIEndResult) const;
// Caller must have called GetAvailableSpace for the current mBCoord
void ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay,
const nsFlowAreaRect& aFloatAvailableSpace,
bool aBlockAvoidsFloats,
mozilla::LogicalRect& aResult);
protected:
void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaBCoord);
public:
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
void AdvanceToNextLine() {
if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) {
SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
} else {
mLineNumber++;
}
}
//----------------------------------------
// This state is the "global" state computed once for the reflow of
// the block.
// The block frame that is using this object
nsBlockFrame* mBlock;
nsPresContext* mPresContext;
const nsHTMLReflowState& mReflowState;
nsFloatManager* mFloatManager;
// The coordinates within the float manager where the block is being
// placed <b>after</b> taking into account the blocks border and
// padding. This, therefore, represents the inner "content area" (in
// spacemanager coordinates) where child frames will be placed,
// including child blocks and floats.
nscoord mFloatManagerI, mFloatManagerB;
// XXX get rid of this
nsReflowStatus mReflowStatus;
// The float manager state as it was before the contents of this
// block. This is needed for positioning bullets, since we only want
// to move the bullet to flow around floats that were before this
// block, not floats inside of it.
nsFloatManager::SavedState mFloatManagerStateBefore;
nscoord mBEndEdge;
// The content area to reflow child frames within. This is within
// this frame's coordinate system and writing mode, which means
// mContentArea.IStart == BorderPadding().IStart and
// mContentArea.BStart == BorderPadding().BStart.
// The block size may be NS_UNCONSTRAINEDSIZE, which indicates that there
// is no page/column boundary below (the common case).
// mContentArea.BEnd() should only be called after checking that
// mContentArea.BSize is not NS_UNCONSTRAINEDSIZE; otherwise
// coordinate overflow may occur.
mozilla::LogicalRect mContentArea;
nscoord ContentIStart() const {
return mContentArea.IStart(mReflowState.GetWritingMode());
}
nscoord ContentISize() const {
return mContentArea.ISize(mReflowState.GetWritingMode());
}
nscoord ContentIEnd() const {
return mContentArea.IEnd(mReflowState.GetWritingMode());
}
nscoord ContentBStart() const {
return mContentArea.BStart(mReflowState.GetWritingMode());
}
nscoord ContentBSize() const {
return mContentArea.BSize(mReflowState.GetWritingMode());
}
nscoord ContentBEnd() const {
return mContentArea.BEnd(mReflowState.GetWritingMode());
}
mozilla::LogicalSize ContentSize(mozilla::WritingMode aWM) const {
mozilla::WritingMode wm = mReflowState.GetWritingMode();
return mContentArea.Size(wm).ConvertTo(aWM, wm);
}
// Physical size. Use only for physical <-> logical coordinate conversion.
nsSize mContainerSize;
const nsSize& ContainerSize() const { return mContainerSize; }
// Continuation out-of-flow float frames that need to move to our
// next in flow are placed here during reflow. It's a pointer to
// a frame list stored in the block's property table.
nsFrameList *mPushedFloats;
// This method makes sure pushed floats are accessible to
// StealFrame. Call it before adding any frames to mPushedFloats.
void SetupPushedFloatList();
/**
* Append aFloatCont and its next-in-flows within the same block to
* mPushedFloats. aFloatCont should not be on any child list when
* making this call. Its next-in-flows will be removed from
* mBlock using StealFrame() before being added to mPushedFloats.
* All appended frames will be marked NS_FRAME_IS_PUSHED_FLOAT.
*/
void AppendPushedFloatChain(nsIFrame* aFloatCont);
// Track child overflow continuations.
nsOverflowContinuationTracker* mOverflowTracker;
//----------------------------------------
// This state is "running" state updated by the reflow of each line
// in the block. This same state is "recovered" when a line is not
// dirty and is passed over during incremental reflow.
// The current line being reflowed
// If it is mBlock->end_lines(), then it is invalid.
nsLineList::iterator mCurrentLine;
// When BRS_HAVELINEADJACENTTOTOP is set, this refers to a line
// which we know is adjacent to the top of the block (in other words,
// all lines before it are empty and do not have clearance. This line is
// always before the current line.
nsLineList::iterator mLineAdjacentToTop;
// The current block-direction coordinate in the block
nscoord mBCoord;
// mBlock's computed physical border+padding with GetSkipSides applied.
mozilla::LogicalMargin mBorderPadding;
// The overflow areas of all floats placed so far
nsOverflowAreas mFloatOverflowAreas;
nsFloatCacheFreeList mFloatCacheFreeList;
// Previous child. This is used when pulling up a frame to update
// the sibling list.
nsIFrame* mPrevChild;
// The previous child frames collapsed bottom margin value.
nsCollapsingMargin mPrevBEndMargin;
// The current next-in-flow for the block. When lines are pulled
// from a next-in-flow, this is used to know which next-in-flow to
// pull from. When a next-in-flow is emptied of lines, we advance
// this to the next next-in-flow.
nsBlockFrame* mNextInFlow;
//----------------------------------------
// Temporary line-reflow state. This state is used during the reflow
// of a given line, but doesn't have meaning before or after.
// The list of floats that are "current-line" floats. These are
// added to the line after the line has been reflowed, to keep the
// list fiddling from being N^2.
nsFloatCacheFreeList mCurrentLineFloats;
// The list of floats which are "below current-line"
// floats. These are reflowed/placed after the line is reflowed
// and placed. Again, this is done to keep the list fiddling from
// being N^2.
nsFloatCacheFreeList mBelowCurrentLineFloats;
nscoord mMinLineHeight;
int32_t mLineNumber;
int16_t mFlags;
uint8_t mFloatBreakType;
// The amount of computed block-direction size "consumed" by previous-in-flows.
nscoord mConsumedBSize;
void SetFlag(uint32_t aFlag, bool aValue)
{
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
if (aValue) { // set flag
mFlags |= aFlag;
}
else { // unset flag
mFlags &= ~aFlag;
}
}
bool GetFlag(uint32_t aFlag) const
{
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
return !!(mFlags & aFlag);
}
};
#endif // nsBlockReflowState_h__