nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, nsPresContext* aPresContext, nsBlockFrame* aFrame, bool aBStartMarginRoot, bool aBEndMarginRoot, bool aBlockNeedsFloatManager, nscoord aConsumedBSize) : mBlock(aFrame), mPresContext(aPresContext), mReflowState(aReflowState), mContentArea(aReflowState.GetWritingMode()), mPushedFloats(nullptr), mOverflowTracker(nullptr), mBorderPadding(mReflowState.ComputedLogicalBorderPadding()), mPrevBEndMargin(), mLineNumber(0), mFlags(0), mFloatBreakType(NS_STYLE_CLEAR_NONE), mConsumedBSize(aConsumedBSize) { if (!sFloatFragmentsInsideColumnPrefCached) { sFloatFragmentsInsideColumnPrefCached = true; Preferences::AddBoolVarCache(&sFloatFragmentsInsideColumnEnabled, "layout.float-fragments-inside-column.enabled"); } SetFlag(BRS_FLOAT_FRAGMENTS_INSIDE_COLUMN_ENABLED, sFloatFragmentsInsideColumnEnabled); WritingMode wm = aReflowState.GetWritingMode(); SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nullptr); SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame)); nsIFrame::LogicalSides logicalSkipSides = aFrame->GetLogicalSkipSides(&aReflowState); mBorderPadding.ApplySkipSides(logicalSkipSides); // Note that mContainerSize is the physical size, needed to // convert logical block-coordinates in vertical-rl writing mode // (measured from a RHS origin) to physical coordinates within the // containing block. // If aReflowState doesn't have a constrained ComputedWidth(), we set // mContainerSize.width to zero, which means lines will be positioned // (physically) incorrectly; we will fix them up at the end of // nsBlockFrame::Reflow, after we know the total block-size of the // frame. mContainerSize.width = aReflowState.ComputedWidth(); if (mContainerSize.width == NS_UNCONSTRAINEDSIZE) { mContainerSize.width = 0; } mContainerSize.width += mBorderPadding.LeftRight(wm); // For now at least, we don't do that fix-up for mContainerHeight. // It's only used in nsBidiUtils::ReorderFrames for vertical rtl // writing modes, which aren't fully supported for the time being. mContainerSize.height = aReflowState.ComputedHeight() + mBorderPadding.TopBottom(wm); if ((aBStartMarginRoot && !logicalSkipSides.BStart()) || 0 != mBorderPadding.BStart(wm)) { SetFlag(BRS_ISBSTARTMARGINROOT, true); SetFlag(BRS_APPLYBSTARTMARGIN, true); } if ((aBEndMarginRoot && !logicalSkipSides.BEnd()) || 0 != mBorderPadding.BEnd(wm)) { SetFlag(BRS_ISBENDMARGINROOT, true); } if (aBlockNeedsFloatManager) { SetFlag(BRS_FLOAT_MGR, true); } mFloatManager = aReflowState.mFloatManager; NS_ASSERTION(mFloatManager, "FloatManager should be set in nsBlockReflowState" ); if (mFloatManager) { // Save the coordinate system origin for later. mFloatManager->GetTranslation(mFloatManagerI, mFloatManagerB); mFloatManager->PushState(&mFloatManagerStateBefore); // never popped } mReflowStatus = NS_FRAME_COMPLETE; mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow()); LAYOUT_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedISize(), "have unconstrained width; this should only result " "from very large sizes, not attempts at intrinsic " "width calculation"); mContentArea.ISize(wm) = aReflowState.ComputedISize(); // Compute content area height. Unlike the width, if we have a // specified style height we ignore it since extra content is // managed by the "overflow" property. When we don't have a // specified style height then we may end up limiting our height if // the availableHeight is constrained (this situation occurs when we // are paginated). if (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableBSize()) { // We are in a paginated situation. The bottom edge is just inside // the bottom border and padding. The content area height doesn't // include either border or padding edge. mBEndEdge = aReflowState.AvailableBSize() - mBorderPadding.BEnd(wm); mContentArea.BSize(wm) = std::max(0, mBEndEdge - mBorderPadding.BStart(wm)); } else { // When we are not in a paginated situation then we always use // an constrained height. SetFlag(BRS_UNCONSTRAINEDBSIZE, true); mContentArea.BSize(wm) = mBEndEdge = NS_UNCONSTRAINEDSIZE; } mContentArea.IStart(wm) = mBorderPadding.IStart(wm); mBCoord = mContentArea.BStart(wm) = mBorderPadding.BStart(wm); mPrevChild = nullptr; mCurrentLine = aFrame->end_lines(); mMinLineHeight = aReflowState.CalcLineHeight(); }
void BRFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("BRFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); WritingMode wm = aReflowState.GetWritingMode(); LogicalSize finalSize(wm); finalSize.BSize(wm) = 0; // BR frames with block size 0 are ignored in quirks // mode by nsLineLayout::VerticalAlignFrames . // However, it's not always 0. See below. finalSize.ISize(wm) = 0; aMetrics.SetBlockStartAscent(0); // Only when the BR is operating in a line-layout situation will it // behave like a BR. Additionally, we suppress breaks from BR inside // of ruby frames. To determine if we're inside ruby, we have to rely // on the *parent's* ShouldSuppressLineBreak() method, instead of our // own, because we may have custom "display" value that makes our // ShouldSuppressLineBreak() return false. nsLineLayout* ll = aReflowState.mLineLayout; if (ll && !GetParent()->StyleContext()->ShouldSuppressLineBreak()) { // Note that the compatibility mode check excludes AlmostStandards // mode, since this is the inline box model. See bug 161691. if ( ll->LineIsEmpty() || aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) { // The line is logically empty; any whitespace is trimmed away. // // If this frame is going to terminate the line we know // that nothing else will go on the line. Therefore, in this // case, we provide some height for the BR frame so that it // creates some vertical whitespace. It's necessary to use the // line-height rather than the font size because the // quirks-mode fix that doesn't apply the block's min // line-height makes this necessary to make BR cause a line // of the full line-height // We also do this in strict mode because BR should act like a // normal inline frame. That line-height is used is important // here for cases where the line-height is less than 1. RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetInflatedFontMetricsForFrame(this); if (fm) { nscoord logicalHeight = aReflowState.CalcLineHeight(); finalSize.BSize(wm) = logicalHeight; aMetrics.SetBlockStartAscent(nsLayoutUtils::GetCenteredFontBaseline( fm, logicalHeight, wm.IsLineInverted())); } else { aMetrics.SetBlockStartAscent(aMetrics.BSize(wm) = 0); } // XXX temporary until I figure out a better solution; see the // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY // if the width is zero. // XXX This also fixes bug 10036! // Warning: nsTextControlFrame::CalculateSizeStandard depends on // the following line, see bug 228752. // The code below in AddInlinePrefISize also adds 1 appunit to width finalSize.ISize(wm) = 1; } // Return our reflow status uint32_t breakType = aReflowState.mStyleDisplay->PhysicalBreakType(wm); if (NS_STYLE_CLEAR_NONE == breakType) { breakType = NS_STYLE_CLEAR_LINE; } aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType); ll->SetLineEndsInBR(true); } else { aStatus = NS_FRAME_COMPLETE; } aMetrics.SetSize(wm, finalSize); aMetrics.SetOverflowAreasToDesiredBounds(); mAscent = aMetrics.BlockStartAscent(); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); }
nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, nsPresContext* aPresContext, nsBlockFrame* aFrame, const nsHTMLReflowMetrics& aMetrics, bool aTopMarginRoot, bool aBottomMarginRoot, bool aBlockNeedsFloatManager) : mBlock(aFrame), mPresContext(aPresContext), mReflowState(aReflowState), mPushedFloats(nsnull), mOverflowTracker(nsnull), mPrevBottomMargin(), mLineNumber(0), mFlags(0), mFloatBreakType(NS_STYLE_CLEAR_NONE) { SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nsnull); SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame)); const nsMargin& borderPadding = BorderPadding(); if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) { SetFlag(BRS_ISTOPMARGINROOT, true); } if (aBottomMarginRoot || 0 != aReflowState.mComputedBorderPadding.bottom) { SetFlag(BRS_ISBOTTOMMARGINROOT, true); } if (GetFlag(BRS_ISTOPMARGINROOT)) { SetFlag(BRS_APPLYTOPMARGIN, true); } if (aBlockNeedsFloatManager) { SetFlag(BRS_FLOAT_MGR, true); } mFloatManager = aReflowState.mFloatManager; NS_ASSERTION(mFloatManager, "FloatManager should be set in nsBlockReflowState" ); if (mFloatManager) { // Save the coordinate system origin for later. mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY); mFloatManager->PushState(&mFloatManagerStateBefore); // never popped } mReflowStatus = NS_FRAME_COMPLETE; mPresContext = aPresContext; mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow()); NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(), "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); mContentArea.width = aReflowState.ComputedWidth(); // Compute content area height. Unlike the width, if we have a // specified style height we ignore it since extra content is // managed by the "overflow" property. When we don't have a // specified style height then we may end up limiting our height if // the availableHeight is constrained (this situation occurs when we // are paginated). if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) { // We are in a paginated situation. The bottom edge is just inside // the bottom border and padding. The content area height doesn't // include either border or padding edge. mBottomEdge = aReflowState.availableHeight - borderPadding.bottom; mContentArea.height = NS_MAX(0, mBottomEdge - borderPadding.top); } else { // When we are not in a paginated situation then we always use // an constrained height. SetFlag(BRS_UNCONSTRAINEDHEIGHT, true); mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE; } mContentArea.x = borderPadding.left; mY = mContentArea.y = borderPadding.top; mPrevChild = nsnull; mCurrentLine = aFrame->end_lines(); mMinLineHeight = aReflowState.CalcLineHeight(); }
nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, nsPresContext* aPresContext, nsBlockFrame* aFrame, bool aBStartMarginRoot, bool aBEndMarginRoot, bool aBlockNeedsFloatManager, nscoord aConsumedBSize) : mBlock(aFrame), mPresContext(aPresContext), mReflowState(aReflowState), mContentArea(aReflowState.GetWritingMode()), mPushedFloats(nullptr), mOverflowTracker(nullptr), mBorderPadding(mReflowState.ComputedLogicalBorderPadding()), mPrevBEndMargin(), mLineNumber(0), mFlags(0), mFloatBreakType(NS_STYLE_CLEAR_NONE), mConsumedBSize(aConsumedBSize) { WritingMode wm = aReflowState.GetWritingMode(); SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nullptr); SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame)); nsIFrame::LogicalSides logicalSkipSides = aFrame->GetLogicalSkipSides(&aReflowState); mBorderPadding.ApplySkipSides(logicalSkipSides); // Note that mContainerWidth is the physical width! mContainerWidth = aReflowState.ComputedWidth() + mBorderPadding.LeftRight(wm); if ((aBStartMarginRoot && !logicalSkipSides.BStart()) || 0 != mBorderPadding.BStart(wm)) { SetFlag(BRS_ISBSTARTMARGINROOT, true); SetFlag(BRS_APPLYBSTARTMARGIN, true); } if ((aBEndMarginRoot && !logicalSkipSides.BEnd()) || 0 != mBorderPadding.BEnd(wm)) { SetFlag(BRS_ISBENDMARGINROOT, true); } if (aBlockNeedsFloatManager) { SetFlag(BRS_FLOAT_MGR, true); } mFloatManager = aReflowState.mFloatManager; NS_ASSERTION(mFloatManager, "FloatManager should be set in nsBlockReflowState" ); if (mFloatManager) { // Save the coordinate system origin for later. mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY); mFloatManager->PushState(&mFloatManagerStateBefore); // never popped } mReflowStatus = NS_FRAME_COMPLETE; mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow()); NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedISize(), "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); mContentArea.ISize(wm) = aReflowState.ComputedISize(); // Compute content area height. Unlike the width, if we have a // specified style height we ignore it since extra content is // managed by the "overflow" property. When we don't have a // specified style height then we may end up limiting our height if // the availableHeight is constrained (this situation occurs when we // are paginated). if (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableBSize()) { // We are in a paginated situation. The bottom edge is just inside // the bottom border and padding. The content area height doesn't // include either border or padding edge. mBEndEdge = aReflowState.AvailableBSize() - mBorderPadding.BEnd(wm); mContentArea.BSize(wm) = std::max(0, mBEndEdge - mBorderPadding.BStart(wm)); } else { // When we are not in a paginated situation then we always use // an constrained height. SetFlag(BRS_UNCONSTRAINEDBSIZE, true); mContentArea.BSize(wm) = mBEndEdge = NS_UNCONSTRAINEDSIZE; } mContentArea.IStart(wm) = mBorderPadding.IStart(wm); mBCoord = mContentArea.BStart(wm) = mBorderPadding.BStart(wm); mPrevChild = nullptr; mCurrentLine = aFrame->end_lines(); mMinLineHeight = aReflowState.CalcLineHeight(); }