From 151d2fc6c810bc4a8784c6f8266f0c3ddc844a88 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Fri, 12 Aug 2016 15:28:45 +0800 Subject: [PATCH] Bug 1294628 - Replace block reflow input flags with a bit fields struct. r=dholbert MozReview-Commit-ID: 2ZSm9hTrsuh --HG-- extra : rebase_source : 2d44e6c8e1856274d466ed1c523ff6cbf793b4e7 --- layout/generic/BlockReflowInput.cpp | 35 +++--- layout/generic/BlockReflowInput.h | 162 ++++++++++++++-------------- layout/generic/nsBlockFrame.cpp | 32 +++--- layout/generic/nsFrameStateBits.h | 2 +- 4 files changed, 118 insertions(+), 113 deletions(-) diff --git a/layout/generic/BlockReflowInput.cpp b/layout/generic/BlockReflowInput.cpp index c131dbf22900..afb9cd6f7891 100644 --- a/layout/generic/BlockReflowInput.cpp +++ b/layout/generic/BlockReflowInput.cpp @@ -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) > diff --git a/layout/generic/BlockReflowInput.h b/layout/generic/BlockReflowInput.h index 0f70d3cabb86..ba7dd96787eb 100644 --- a/layout/generic/BlockReflowInput.h +++ b/layout/generic/BlockReflowInput.h @@ -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); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 7ee96471fe00..d422d31523ba 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -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 diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h index cd880492618e..bd5344fbaf65 100644 --- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -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