Bug 1294628 - Replace block reflow input flags with a bit fields struct. r=dholbert

MozReview-Commit-ID: 2ZSm9hTrsuh

--HG--
extra : rebase_source : 2d44e6c8e1856274d466ed1c523ff6cbf793b4e7
This commit is contained in:
Ting-Yu Lin 2016-08-12 15:28:45 +08:00
parent d8ad3d3bc3
commit 151d2fc6c8
4 changed files with 118 additions and 113 deletions

View File

@ -44,7 +44,6 @@ BlockReflowInput::BlockReflowInput(const ReflowInput& aReflowInput,
mBorderPadding(mReflowInput.ComputedLogicalBorderPadding()),
mPrevBEndMargin(),
mLineNumber(0),
mFlags(0),
mFloatBreakType(NS_STYLE_CLEAR_NONE),
mConsumedBSize(aConsumedBSize)
{
@ -53,11 +52,11 @@ BlockReflowInput::BlockReflowInput(const ReflowInput& aReflowInput,
Preferences::AddBoolVarCache(&sFloatFragmentsInsideColumnEnabled,
"layout.float-fragments-inside-column.enabled");
}
SetFlag(BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED, sFloatFragmentsInsideColumnEnabled);
mFlags.mFloatFragmentsInsideColumnEnabled = sFloatFragmentsInsideColumnEnabled;
WritingMode wm = aReflowInput.GetWritingMode();
SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nullptr);
SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame));
mFlags.mIsFirstInflow = !aFrame->GetPrevInFlow();
mFlags.mIsOverflowContainer = IS_TRUE_OVERFLOW_CONTAINER(aFrame);
nsIFrame::LogicalSides logicalSkipSides =
aFrame->GetLogicalSkipSides(&aReflowInput);
@ -87,17 +86,17 @@ BlockReflowInput::BlockReflowInput(const ReflowInput& aReflowInput,
if ((aBStartMarginRoot && !logicalSkipSides.BStart()) ||
0 != mBorderPadding.BStart(wm)) {
SetFlag(BRS_ISBSTARTMARGINROOT, true);
SetFlag(BRS_APPLYBSTARTMARGIN, true);
mFlags.mIsBStartMarginRoot = true;
mFlags.mShouldApplyBStartMargin = true;
}
if ((aBEndMarginRoot && !logicalSkipSides.BEnd()) ||
0 != mBorderPadding.BEnd(wm)) {
SetFlag(BRS_ISBENDMARGINROOT, true);
mFlags.mIsBEndMarginRoot = true;
}
if (aBlockNeedsFloatManager) {
SetFlag(BRS_FLOAT_MGR, true);
mFlags.mBlockNeedsFloatManager = true;
}
mFloatManager = aReflowInput.mFloatManager;
NS_ASSERTION(mFloatManager,
@ -133,8 +132,8 @@ BlockReflowInput::BlockReflowInput(const ReflowInput& aReflowInput,
}
else {
// When we are not in a paginated situation then we always use
// an constrained height.
SetFlag(BRS_UNCONSTRAINEDBSIZE, true);
// a constrained height.
mFlags.mHasUnconstrainedBSize = true;
mContentArea.BSize(wm) = mBEndEdge = NS_UNCONSTRAINEDSIZE;
}
mContentArea.IStart(wm) = mBorderPadding.IStart(wm);
@ -234,7 +233,7 @@ BlockReflowInput::ComputeBlockAvailSpace(nsIFrame* aFrame,
#endif
WritingMode wm = mReflowInput.GetWritingMode();
aResult.BStart(wm) = mBCoord;
aResult.BSize(wm) = GetFlag(BRS_UNCONSTRAINEDBSIZE)
aResult.BSize(wm) = mFlags.mHasUnconstrainedBSize
? NS_UNCONSTRAINEDSIZE
: mReflowInput.AvailableBSize() - mBCoord
- GetBEndMarginClone(aFrame, mReflowInput.mRenderingContext, mContentArea, wm);
@ -431,7 +430,7 @@ BlockReflowInput::ReconstructMarginBefore(nsLineList::iterator aLine)
if (aLine == firstLine) {
// If the top margin was carried out (and thus already applied),
// set it to zero. Either way, we're done.
if (!GetFlag(BRS_ISBSTARTMARGINROOT)) {
if (!mFlags.mIsBStartMarginRoot) {
mPrevBEndMargin.Zero();
}
break;
@ -442,9 +441,9 @@ BlockReflowInput::ReconstructMarginBefore(nsLineList::iterator aLine)
void
BlockReflowInput::SetupPushedFloatList()
{
MOZ_ASSERT(!GetFlag(BRS_PROPTABLE_FLOATCLIST) == !mPushedFloats,
MOZ_ASSERT(!mFlags.mIsFloatListInBlockPropertyTable == !mPushedFloats,
"flag mismatch");
if (!GetFlag(BRS_PROPTABLE_FLOATCLIST)) {
if (!mFlags.mIsFloatListInBlockPropertyTable) {
// If we're being re-Reflow'd without our next-in-flow having been
// reflowed, some pushed floats from our previous reflow might
// still be on our pushed floats list. However, that's
@ -453,7 +452,7 @@ BlockReflowInput::SetupPushedFloatList()
// (nsBlockFrame::ReflowDirtyLines ensures that any lines with
// pushed floats are reflowed.)
mPushedFloats = mBlock->EnsurePushedFloats();
SetFlag(BRS_PROPTABLE_FLOATCLIST, true);
mFlags.mIsFloatListInBlockPropertyTable = true;
}
}
@ -918,7 +917,7 @@ BlockReflowInput::FlowAndPlaceFloat(nsIFrame* aFloat)
// its entirety to the next page (NS_FRAME_IS_TRUNCATED or
// NS_INLINE_IS_BREAK_BEFORE), we need to do the same.
if ((ContentBSize() != NS_UNCONSTRAINEDSIZE &&
!GetFlag(BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED) &&
!mFlags.mFloatFragmentsInsideColumnEnabled &&
adjustedAvailableSpace.BSize(wm) == NS_UNCONSTRAINEDSIZE &&
!mustPlaceFloat &&
aFloat->BSize(wm) + floatMargin.BStartEnd(wm) >

View File

@ -16,68 +16,91 @@ class nsBlockFrame;
class nsFrameList;
class nsOverflowContinuationTracker;
// Block reflow state flags.
//
// BRS_UNCONSTRAINEDBSIZE is set in the BlockReflowInput constructor when the
// frame being reflowed has been given NS_UNCONSTRAINEDSIZE as its available
// BSize in the ReflowInput. If set, NS_UNCONSTRAINEDSIZE is passed to
// nsLineLayout as the available BSize.
#define BRS_UNCONSTRAINEDBSIZE 0x00000001
// BRS_ISBSTARTMARGINROOT is set in the BlockReflowInput constructor when
// reflowing a "block margin root" frame (i.e. a frame with the
// NS_BLOCK_MARGIN_ROOT flag set, for which margins apply by default).
//
// The flag is also set when reflowing a frame whose computed BStart border
// padding is non-zero.
#define BRS_ISBSTARTMARGINROOT 0x00000002
// BRS_ISBENDMARGINROOT is set in the BlockReflowInput constructor when
// reflowing a "block margin root" frame (i.e. a frame with the
// NS_BLOCK_MARGIN_ROOT flag set, for which margins apply by default).
//
// The flag is also set when reflowing a frame whose computed BEnd border
// padding is non-zero.
#define BRS_ISBENDMARGINROOT 0x00000004
// BRS_APPLYBSTARTMARGIN is set if the BStart margin should be considered when
// placing a linebox that contains a block frame. It may be set as a side-effect
// of calling nsBlockFrame::ShouldApplyBStartMargin(); once set,
// ShouldApplyBStartMargin() uses it as a fast-path way to return whether the
// BStart margin should apply.
//
// If the flag hasn't been set in the block reflow state, then
// ShouldApplyBStartMargin() will crawl the line list to see if a block frame
// precedes the specified frame. If so, the BStart margin should be applied, and
// the flag is set to cache the result. (If not, the BStart margin will be
// applied as a result of the generational margin collapsing logic in
// nsBlockReflowContext::ComputeCollapsedBStartMargin(). In this case, the flag
// won't be set, so subsequent calls to ShouldApplyBStartMargin() will continue
// crawl the line list.)
//
// This flag is also set in the BlockReflowInput constructor if
// BRS_ISBSTARTMARGINROOT is set; that is, the frame being reflowed is a margin
// root by default.
#define BRS_APPLYBSTARTMARGIN 0x00000008
#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
namespace mozilla {
// BlockReflowInput contains additional reflow state information that the
// BlockReflowInput contains additional reflow input information that the
// block frame uses along with ReflowInput. Like ReflowInput, this
// is read-only data that is passed down from a parent frame to its children.
class BlockReflowInput {
using ReflowInput = mozilla::ReflowInput;
// Block reflow input flags.
struct Flags {
Flags()
: mHasUnconstrainedBSize(false)
, mIsBStartMarginRoot(false)
, mIsBEndMarginRoot(false)
, mShouldApplyBStartMargin(false)
, mIsFirstInflow(false)
, mHasLineAdjacentToTop(false)
, mBlockNeedsFloatManager(false)
, mIsLineLayoutEmpty(false)
, mIsOverflowContainer(false)
, mIsFloatListInBlockPropertyTable(false)
, mFloatFragmentsInsideColumnEnabled(false)
{}
// Set in the BlockReflowInput constructor when the frame being reflowed has
// been given NS_UNCONSTRAINEDSIZE as its available BSize in the
// ReflowInput. If set, NS_UNCONSTRAINEDSIZE is passed to nsLineLayout as
// the available BSize.
bool mHasUnconstrainedBSize : 1;
// Set in the BlockReflowInput constructor when reflowing a "block margin
// root" frame (i.e. a frame with the NS_BLOCK_MARGIN_ROOT flag set, for
// which margins apply by default).
//
// The flag is also set when reflowing a frame whose computed BStart border
// padding is non-zero.
bool mIsBStartMarginRoot : 1;
// Set in the BlockReflowInput constructor when reflowing a "block margin
// root" frame (i.e. a frame with the NS_BLOCK_MARGIN_ROOT flag set, for
// which margins apply by default).
//
// The flag is also set when reflowing a frame whose computed BEnd border
// padding is non-zero.
bool mIsBEndMarginRoot : 1;
// Set if the BStart margin should be considered when placing a linebox that
// contains a block frame. It may be set as a side-effect of calling
// nsBlockFrame::ShouldApplyBStartMargin(); once set,
// ShouldApplyBStartMargin() uses it as a fast-path way to return whether
// the BStart margin should apply.
//
// If the flag hasn't been set in the block reflow input, then
// ShouldApplyBStartMargin() will crawl the line list to see if a block frame
// precedes the specified frame. If so, the BStart margin should be applied, and
// the flag is set to cache the result. (If not, the BStart margin will be
// applied as a result of the generational margin collapsing logic in
// nsBlockReflowContext::ComputeCollapsedBStartMargin(). In this case, the flag
// won't be set, so subsequent calls to ShouldApplyBStartMargin() will continue
// crawl the line list.)
//
// This flag is also set in the BlockReflowInput constructor if
// mIsBStartMarginRoot is set; that is, the frame being reflowed is a margin
// root by default.
bool mShouldApplyBStartMargin : 1;
bool mIsFirstInflow : 1;
// Set when mLineAdjacentToTop is valid.
bool mHasLineAdjacentToTop : 1;
// Set when the block has the equivalent of NS_BLOCK_FLOAT_MGR.
bool mBlockNeedsFloatManager : 1;
// Set when nsLineLayout::LineIsEmpty was true at the end of reflowing
// the current line.
bool mIsLineLayoutEmpty : 1;
bool mIsOverflowContainer : 1;
// Set when our mPushedFloats list is stored on the block's property table.
bool mIsFloatListInBlockPropertyTable : 1;
// Set when the pref layout.float-fragments-inside-column.enabled is true.
bool mFloatFragmentsInsideColumnEnabled : 1;
};
public:
BlockReflowInput(const ReflowInput& aReflowInput,
@ -192,8 +215,8 @@ public:
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
void AdvanceToNextLine() {
if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) {
SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
if (mFlags.mIsLineLayoutEmpty) {
mFlags.mIsLineLayoutEmpty = false;
} else {
mLineNumber++;
}
@ -297,7 +320,7 @@ public:
// If it is mBlock->end_lines(), then it is invalid.
nsLineList::iterator mCurrentLine;
// When BRS_HAVELINEADJACENTTOTOP is set, this refers to a line
// When mHasLineAdjacentToTop 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.
@ -347,30 +370,13 @@ public:
int32_t mLineNumber;
int16_t mFlags;
Flags 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);
}
private:
bool CanPlaceFloat(nscoord aFloatISize,
const nsFlowAreaRect& aFloatAvailableSpace);

View File

@ -1489,7 +1489,7 @@ nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput,
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
printf(": mBCoord=%d mIsBEndMarginRoot=%s mPrevBEndMargin=%d bp=%d,%d\n",
aState.mBCoord, aState.GetFlag(BRS_ISBENDMARGINROOT) ? "yes" : "no",
aState.mBCoord, aState.mFlags.mIsBEndMarginRoot ? "yes" : "no",
aState.mPrevBEndMargin.get(),
borderPadding.BStart(wm), borderPadding.BEnd(wm));
#endif
@ -1507,7 +1507,7 @@ nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput,
//NS_ASSERTION(aMetrics.mCarriedOutBEndMargin.IsZero(),
// "someone else set the margin");
nscoord nonCarriedOutBDirMargin = 0;
if (!aState.GetFlag(BRS_ISBENDMARGINROOT)) {
if (!aState.mFlags.mIsBEndMarginRoot) {
// Apply rule from CSS 2.1 section 8.3.1. If we have some empty
// line with clearance and a non-zero block-start margin and all
// subsequent lines are empty, then we do not allow our children's
@ -1526,7 +1526,7 @@ nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput,
nscoord blockEndEdgeOfChildren = aState.mBCoord + nonCarriedOutBDirMargin;
// Shrink wrap our height around our contents.
if (aState.GetFlag(BRS_ISBENDMARGINROOT) ||
if (aState.mFlags.mIsBEndMarginRoot ||
NS_UNCONSTRAINEDSIZE != aReflowInput.ComputedBSize()) {
// When we are a block-end-margin root make sure that our last
// childs block-end margin is fully applied. We also do this when
@ -1542,7 +1542,7 @@ nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput,
aState.mReflowInput.AvailableBSize());
}
}
if (aState.GetFlag(BRS_FLOAT_MGR)) {
if (aState.mFlags.mBlockNeedsFloatManager) {
// Include the float manager's state to properly account for the
// block-end margin of any floated elements; e.g., inside a table cell.
nscoord floatHeight =
@ -3076,7 +3076,7 @@ nsBlockFrame::ShouldApplyBStartMargin(BlockReflowInput& aState,
nsLineBox* aLine,
nsIFrame* aChildFrame)
{
if (aState.GetFlag(BRS_APPLYBSTARTMARGIN)) {
if (aState.mFlags.mShouldApplyBStartMargin) {
// Apply short-circuit check to avoid searching the line list
return true;
}
@ -3087,26 +3087,26 @@ nsBlockFrame::ShouldApplyBStartMargin(BlockReflowInput& aState,
// If we aren't at the start block-coordinate then something of non-zero
// height must have been placed. Therefore the childs block-start margin
// applies.
aState.SetFlag(BRS_APPLYBSTARTMARGIN, true);
aState.mFlags.mShouldApplyBStartMargin = true;
return true;
}
// Determine if this line is "essentially" the first line
line_iterator line = begin_lines();
if (aState.GetFlag(BRS_HAVELINEADJACENTTOTOP)) {
if (aState.mFlags.mHasLineAdjacentToTop) {
line = aState.mLineAdjacentToTop;
}
while (line != aLine) {
if (!line->CachedIsEmpty() || line->HasClearance()) {
// A line which precedes aLine is non-empty, or has clearance,
// so therefore the block-start margin applies.
aState.SetFlag(BRS_APPLYBSTARTMARGIN, true);
aState.mFlags.mShouldApplyBStartMargin = true;
return true;
}
// No need to apply the block-start margin if the line has floats. We
// should collapse anyway (bug 44419)
++line;
aState.SetFlag(BRS_HAVELINEADJACENTTOTOP, true);
aState.mFlags.mHasLineAdjacentToTop = true;
aState.mLineAdjacentToTop = line;
}
@ -3841,7 +3841,7 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
nscoord iStart = lineRect.IStart(lineWM);
nscoord availISize = lineRect.ISize(lineWM);
nscoord availBSize;
if (aState.GetFlag(BRS_UNCONSTRAINEDBSIZE)) {
if (aState.mFlags.mHasUnconstrainedBSize) {
availBSize = NS_UNCONSTRAINEDSIZE;
}
else {
@ -3859,7 +3859,7 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
false, /*XXX isTopOfPage*/
lineWM, aState.mContainerSize);
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
aState.mFlags.mIsLineLayoutEmpty = false;
// XXX Unfortunately we need to know this before reflowing the first
// inline frame in the line. FIX ME.
@ -3938,13 +3938,13 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
}
}
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, aLineLayout.LineIsEmpty());
aState.mFlags.mIsLineLayoutEmpty = aLineLayout.LineIsEmpty();
// We only need to backup if the line isn't going to be reflowed again anyway
bool needsBackup = aLineLayout.NeedsBackup() &&
(lineReflowStatus == LINE_REFLOW_STOP || lineReflowStatus == LINE_REFLOW_OK);
if (needsBackup && aLineLayout.HaveForcedBreakPosition()) {
NS_WARNING("We shouldn't be backing up more than once! "
NS_WARNING("We shouldn't be backing up more than once! "
"Someone must have set a break opportunity beyond the available width, "
"even though there were better break opportunities before it");
needsBackup = false;
@ -4538,8 +4538,8 @@ nsBlockFrame::PlaceLine(BlockReflowInput& aState,
// coordinate (it was applied in ReflowInlineFrames speculatively)
// since the line is empty.
// We already called |ShouldApplyBStartMargin|, and if we applied it
// then BRS_APPLYBSTARTMARGIN is set.
nscoord dy = aState.GetFlag(BRS_APPLYBSTARTMARGIN)
// then mShouldApplyBStartMargin is set.
nscoord dy = aState.mFlags.mShouldApplyBStartMargin
? -aState.mPrevBEndMargin.get() : 0;
newBCoord = aState.mBCoord + dy;
}
@ -6072,7 +6072,7 @@ nsBlockFrame::AdjustFloatAvailableSpace(BlockReflowInput& aState,
: std::max(0, aState.ContentBEnd() - aState.mBCoord);
if (availBSize != NS_UNCONSTRAINEDSIZE &&
!aState.GetFlag(BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED) &&
!aState.mFlags.mFloatFragmentsInsideColumnEnabled &&
nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::columnSetFrame)) {
// Tell the float it has unrestricted block-size, so it won't break.
// If the float doesn't actually fit in the column it will fail to be

View File

@ -465,7 +465,7 @@ FRAME_STATE_BIT(Block, 21, NS_BLOCK_HAS_PUSHED_FLOATS)
// nsBlockFrame::IsMarginRoot().
//
// This causes the BlockReflowInput's constructor to set the
// BRS_ISBSTARTMARGINROOT and BRS_ISBENDMARGINROOT flags.
// mIsBStartMarginRoot and mIsBEndMarginRoot flags.
FRAME_STATE_BIT(Block, 22, NS_BLOCK_MARGIN_ROOT)
// This indicates that a block frame should create its own float manager. This