diff options
Diffstat (limited to 'layout/generic/ReflowInput.cpp')
-rw-r--r-- | layout/generic/ReflowInput.cpp | 219 |
1 files changed, 126 insertions, 93 deletions
diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index ed7dbd2656..bdfd39aff1 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -13,10 +13,8 @@ #include "CounterStyleManager.h" #include "LayoutLogging.h" #include "mozilla/dom/HTMLInputElement.h" -#include "mozilla/StaticPrefs_layout.h" #include "mozilla/WritingModes.h" #include "nsBlockFrame.h" -#include "nsCSSAnonBoxes.h" #include "nsFlexContainerFrame.h" #include "nsFontInflationData.h" #include "nsFontMetrics.h" @@ -31,7 +29,6 @@ #include "nsLineBox.h" #include "nsPresContext.h" #include "nsStyleConsts.h" -#include "nsTableCellFrame.h" #include "nsTableFrame.h" #include "StickyScrollContainer.h" @@ -956,21 +953,10 @@ void ReflowInput::ApplyRelativePositioning(nsIFrame* aFrame, const nsStyleDisplay* display = aFrame->StyleDisplay(); if (StylePositionProperty::Relative == display->mPosition) { *aPosition += nsPoint(aComputedOffsets.left, aComputedOffsets.top); - } else if (StylePositionProperty::Sticky == display->mPosition && - !aFrame->GetNextContinuation() && !aFrame->GetPrevContinuation() && - !aFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) { - // Sticky positioning for elements with multiple frames needs to be - // computed all at once. We can't safely do that here because we might be - // partway through (re)positioning the frames, so leave it until the scroll - // container reflows and calls StickyScrollContainer::UpdatePositions. - // For single-frame sticky positioned elements, though, go ahead and apply - // it now to avoid unnecessary overflow updates later. - StickyScrollContainer* ssc = - StickyScrollContainer::GetStickyScrollContainerForFrame(aFrame); - if (ssc) { - *aPosition = ssc->ComputePosition(aFrame); - } } + // For sticky positioned elements, we'll leave them until the scroll container + // reflows and calls StickyScrollContainer::UpdatePositions() to update their + // positions. } // static @@ -1126,9 +1112,9 @@ void ReflowInput::CalculateBorderPaddingMargin( nscoord* aOutsideBoxSizing) const { WritingMode wm = GetWritingMode(); mozilla::Side startSide = - wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeStart)); + wm.PhysicalSide(MakeLogicalSide(aAxis, LogicalEdge::Start)); mozilla::Side endSide = - wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeEnd)); + wm.PhysicalSide(MakeLogicalSide(aAxis, LogicalEdge::End)); nsMargin styleBorder = mStyleBorder->GetComputedBorder(); nscoord borderStartEnd = @@ -1231,18 +1217,18 @@ static bool AxisPolarityFlipped(LogicalAxis aThisAxis, WritingMode aThisWm, aThisWm.PhysicalAxis(aThisAxis) == aOtherWm.PhysicalAxis(otherAxis), "Physical axes must match!"); Side thisStartSide = - aThisWm.PhysicalSide(MakeLogicalSide(aThisAxis, eLogicalEdgeStart)); + aThisWm.PhysicalSide(MakeLogicalSide(aThisAxis, LogicalEdge::Start)); Side otherStartSide = - aOtherWm.PhysicalSide(MakeLogicalSide(otherAxis, eLogicalEdgeStart)); + aOtherWm.PhysicalSide(MakeLogicalSide(otherAxis, LogicalEdge::Start)); return thisStartSide != otherStartSide; } static bool InlinePolarityFlipped(WritingMode aThisWm, WritingMode aOtherWm) { - return AxisPolarityFlipped(eLogicalAxisInline, aThisWm, aOtherWm); + return AxisPolarityFlipped(LogicalAxis::Inline, aThisWm, aOtherWm); } static bool BlockPolarityFlipped(WritingMode aThisWm, WritingMode aOtherWm) { - return AxisPolarityFlipped(eLogicalAxisBlock, aThisWm, aOtherWm); + return AxisPolarityFlipped(LogicalAxis::Block, aThisWm, aOtherWm); } // Calculate the position of the hypothetical box that the element would have @@ -1292,7 +1278,6 @@ void ReflowInput::CalculateHypotheticalPosition( // For non-replaced inline-level elements the 'inline size' property // doesn't apply, so we don't know what the inline size would have // been without reflowing it - } else { // It's either a replaced inline-level element or a block-level element @@ -1301,17 +1286,17 @@ void ReflowInput::CalculateHypotheticalPosition( // been in the flow. Note that we ignore any 'auto' and 'inherit' // values nscoord insideBoxISizing, outsideBoxISizing; - CalculateBorderPaddingMargin(eLogicalAxisInline, blockContentSize.ISize(wm), - &insideBoxISizing, &outsideBoxISizing); + CalculateBorderPaddingMargin(LogicalAxis::Inline, + blockContentSize.ISize(wm), &insideBoxISizing, + &outsideBoxISizing); if (mFlags.mIsReplaced && isAutoISize) { - // It's a replaced element with an 'auto' inline size so the box - // inline size is its intrinsic size plus any border/padding/margin + // It's a replaced element with an 'auto' inline size so the box inline + // size is its intrinsic size plus any border/padding/margin if (intrinsicSize) { boxISize.emplace(LogicalSize(wm, *intrinsicSize).ISize(wm) + outsideBoxISizing + insideBoxISizing); } - } else if (isAutoISize) { // The box inline size is the containing block inline size boxISize.emplace(blockContentSize.ISize(wm)); @@ -1320,7 +1305,7 @@ void ReflowInput::CalculateHypotheticalPosition( // percentage based this computed value may be different from the computed // value calculated using the absolute containing block width nscoord insideBoxBSizing, dummy; - CalculateBorderPaddingMargin(eLogicalAxisBlock, + CalculateBorderPaddingMargin(LogicalAxis::Block, blockContentSize.ISize(wm), &insideBoxBSizing, &dummy); boxISize.emplace( @@ -1500,7 +1485,7 @@ void ReflowInput::CalculateHypotheticalPosition( // been in the flow. Note that we ignore any 'auto' and 'inherit' // values. nscoord insideBoxSizing, outsideBoxSizing; - CalculateBorderPaddingMargin(eLogicalAxisBlock, blockContentSize.BSize(wm), + CalculateBorderPaddingMargin(LogicalAxis::Block, blockContentSize.BSize(wm), &insideBoxSizing, &outsideBoxSizing); nscoord boxBSize; @@ -1627,7 +1612,7 @@ LogicalSize ReflowInput::CalculateAbsoluteSizeWithResolvedAutoBlockSize( : LogicalSize(wm); auto transferredISize = mStylePosition->mAspectRatio.ToLayoutRatio().ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, wm, aAutoBSize, boxSizingAdjust); + LogicalAxis::Inline, wm, aAutoBSize, boxSizingAdjust); resultSize.ISize(wm) = ApplyMinMaxISize(transferredISize); MOZ_ASSERT(mFlags.mIsBSizeSetByAspectRatio, @@ -2167,8 +2152,6 @@ void ReflowInput::InitConstraints( WritingMode wm = GetWritingMode(); LogicalSize cbSize = aContainingBlockSize.valueOr( LogicalSize(mWritingMode, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)); - DISPLAY_INIT_CONSTRAINTS(mFrame, this, cbSize.ISize(wm), cbSize.BSize(wm), - aBorder, aPadding); // If this is a reflow root, then set the computed width and // height equal to the available space @@ -2239,7 +2222,7 @@ void ReflowInput::InitConstraints( // eStyleUnit_Auto;" used to be called exclusively. if (mFlags.mIsReplaced && mStyleDisplay->IsInlineOutsideStyle()) { // Get the containing block's reflow input - NS_ASSERTION(nullptr != cbri, "no containing block"); + NS_ASSERTION(cbri, "no containing block"); // in quirks mode, get the cb height using the special quirk method if (!wm.IsVertical() && eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) { @@ -2359,46 +2342,79 @@ void ReflowInput::InitConstraints( } else { AutoMaybeDisableFontInflation an(mFrame); - const bool isBlockLevel = - ((!mStyleDisplay->IsInlineOutsideStyle() && - // internal table values on replaced elements behaves as inline - // https://drafts.csswg.org/css-tables-3/#table-structure - // "... it is handled instead as though the author had declared - // either 'block' (for 'table' display) or 'inline' (for all - // other values)" - !(mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() || - mStyleDisplay->DisplayOutside() == - StyleDisplayOutside::TableCaption))) || - // The inner table frame always fills its outer wrapper table frame, - // even for 'inline-table'. - mFrame->IsTableFrame()) && - // XXX abs.pos. continuations treated like blocks, see comment in - // the else-if condition above. - (!mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) || - mStyleDisplay->IsAbsolutelyPositionedStyle()); - - if (!isBlockLevel) { - mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; - } + nsIFrame* const alignCB = [&] { + nsIFrame* cb = mFrame->GetParent(); + if (cb->IsTableWrapperFrame()) { + nsIFrame* alignCBParent = cb->GetParent(); + if (alignCBParent && alignCBParent->IsGridContainerFrame()) { + return alignCBParent; + } + } + return cb; + }(); - nsIFrame* alignCB = mFrame->GetParent(); - if (alignCB->IsTableWrapperFrame()) { - nsIFrame* alignCBParent = alignCB->GetParent(); - if (alignCBParent && alignCBParent->IsGridContainerFrame()) { - alignCB = alignCBParent; + const bool isInlineLevel = [&] { + if (mFrame->IsTableFrame()) { + // An inner table frame is not inline-level, even if it happens to + // have 'display:inline-table'. (That makes its table-wrapper frame be + // inline-level, but not the inner table frame) + return false; } - } - if (!alignCB->IsGridContainerFrame()) { - // Shrink-wrap blocks that are orthogonal to their container. - if (isBlockLevel && mCBReflowInput && + if (mStyleDisplay->IsInlineOutsideStyle()) { + return true; + } + if (mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() || + mStyleDisplay->DisplayOutside() == + StyleDisplayOutside::TableCaption)) { + // Internal table values on replaced elements behave as inline + // https://drafts.csswg.org/css-tables-3/#table-structure + // + // ... it is handled instead as though the author had declared + // either 'block' (for 'table' display) or 'inline' (for all + // other values)" + // + // FIXME(emilio): The only test that covers this is + // table-anonymous-objects-211.xht, which fails on other browsers (but + // differently to us, if you just remove this condition). + return true; + } + if (mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && + !mStyleDisplay->IsAbsolutelyPositionedStyle()) { + // Floats are treated as inline-level and also shrink-wrap. + return true; + } + return false; + }(); + + const bool shouldShrinkWrap = [&] { + if (isInlineLevel) { + return true; + } + if (mFlags.mIsReplaced && !alignCB->IsFlexOrGridContainer()) { + // Shrink-wrap replaced elements when in-flow (out of flows are + // handled above). We exclude replaced elements in grid or flex + // contexts, where we don't want to shrink-wrap unconditionally (so + // that stretching can happen). When grid/flex explicitly want + // shrink-wrapping, they can request it directly using the relevant + // flag. + return true; + } + if (!alignCB->IsGridContainerFrame() && mCBReflowInput && mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) { - mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; + // Shrink-wrap blocks that are orthogonal to their container (unless + // we're in a grid?) + return true; } + return false; + }(); + + if (shouldShrinkWrap) { + mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; } if (cbSize.ISize(wm) == NS_UNCONSTRAINEDSIZE) { - // For orthogonal flows, where we found a parent orthogonal-limit - // for AvailableISize() in Init(), we'll use the same here as well. + // For orthogonal flows, where we found a parent orthogonal-limit for + // AvailableISize() in Init(), we'll use the same here as well. cbSize.ISize(wm) = AvailableISize(); } @@ -2418,10 +2434,7 @@ void ReflowInput::InitConstraints( size.mAspectRatioUsage == nsIFrame::AspectRatioUsage::ToComputeBSize; const bool shouldCalculateBlockSideMargins = [&]() { - if (!isBlockLevel) { - return false; - } - if (mStyleDisplay->mDisplay == StyleDisplay::InlineTable) { + if (isInlineLevel) { return false; } if (mFrame->IsTableFrame()) { @@ -2475,7 +2488,6 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, const Maybe<LogicalMargin>& aBorder, const Maybe<LogicalMargin>& aPadding, const nsStyleDisplay* aDisplay) { - DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aCBWM, aBorder, aPadding); nsPresContext* presContext = mFrame->PresContext(); // Compute margins from the specified margin style information. These @@ -2526,14 +2538,14 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, NS_ASSERTION(val != nscoord(0), "zero in this property is useless"); LogicalSide side; if (val > 0) { - side = MakeLogicalSide(aAxis, eLogicalEdgeStart); + side = MakeLogicalSide(aAxis, LogicalEdge::Start); } else { - side = MakeLogicalSide(aAxis, eLogicalEdgeEnd); + side = MakeLogicalSide(aAxis, LogicalEdge::End); val = -val; } mComputedPadding.Side(side, wm) += val; needPaddingProp = true; - if (aAxis == eLogicalAxisBlock && val > 0) { + if (aAxis == LogicalAxis::Block && val > 0) { // We have a baseline-adjusted block-axis start padding, so // we need this to mark lines dirty when mIsBResize is true: this->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE); @@ -2541,10 +2553,10 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, } }; if (!aFlags.contains(ComputeSizeFlag::IsGridMeasuringReflow)) { - ApplyBaselinePadding(eLogicalAxisBlock, nsIFrame::BBaselinePadProperty()); + ApplyBaselinePadding(LogicalAxis::Block, nsIFrame::BBaselinePadProperty()); } if (!aFlags.contains(ComputeSizeFlag::ShrinkWrap)) { - ApplyBaselinePadding(eLogicalAxisInline, nsIFrame::IBaselinePadProperty()); + ApplyBaselinePadding(LogicalAxis::Inline, nsIFrame::IBaselinePadProperty()); } LogicalMargin border(wm); @@ -2719,27 +2731,28 @@ void ReflowInput::CalculateBlockSideMargins() { // zeros, we should compensate this by creating extra (external) leading. // This is necessary because without this compensation, normal line height might // look too tight. -constexpr float kNormalLineHeightFactor = 1.2f; static nscoord GetNormalLineHeight(nsFontMetrics* aFontMetrics) { MOZ_ASSERT(aFontMetrics, "no font metrics"); nscoord externalLeading = aFontMetrics->ExternalLeading(); nscoord internalLeading = aFontMetrics->InternalLeading(); nscoord emHeight = aFontMetrics->EmHeight(); if (!internalLeading && !externalLeading) { - return NSToCoordRound(emHeight * kNormalLineHeightFactor); + return NSToCoordRound(static_cast<float>(emHeight) * + ReflowInput::kNormalLineHeightFactor); } return emHeight + internalLeading + externalLeading; } static inline nscoord ComputeLineHeight(const StyleLineHeight& aLh, - const nsStyleFont& aRelativeToFont, + const nsFont& aFont, nsAtom* aLanguage, + bool aExplicitLanguage, nsPresContext* aPresContext, bool aIsVertical, nscoord aBlockBSize, float aFontSizeInflation) { if (aLh.IsLength()) { nscoord result = aLh.AsLength().ToAppUnits(); if (aFontSizeInflation != 1.0f) { - result = NSToCoordRound(result * aFontSizeInflation); + result = NSToCoordRound(static_cast<float>(result) * aFontSizeInflation); } return result; } @@ -2748,8 +2761,7 @@ static inline nscoord ComputeLineHeight(const StyleLineHeight& aLh, // For factor units the computed value of the line-height property // is found by multiplying the factor by the font's computed size // (adjusted for min-size prefs and text zoom). - return aRelativeToFont.mFont.size - .ScaledBy(aLh.AsNumber() * aFontSizeInflation) + return aFont.size.ScaledBy(aLh.AsNumber() * aFontSizeInflation) .ToAppUnits(); } @@ -2758,17 +2770,25 @@ static inline nscoord ComputeLineHeight(const StyleLineHeight& aLh, return aBlockBSize; } - auto size = aRelativeToFont.mFont.size; + auto size = aFont.size; size.ScaleBy(aFontSizeInflation); if (aPresContext) { - RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor( - aPresContext, aIsVertical, &aRelativeToFont, size, - /* aUseUserFontSet = */ true); + nsFont font = aFont; + font.size = size; + nsFontMetrics::Params params; + params.language = aLanguage; + params.explicitLanguage = aExplicitLanguage; + params.orientation = + aIsVertical ? nsFontMetrics::eVertical : nsFontMetrics::eHorizontal; + params.userFontSet = aPresContext->GetUserFontSet(); + params.textPerf = aPresContext->GetTextPerfMetrics(); + params.featureValueLookup = aPresContext->GetFontFeatureValuesLookup(); + RefPtr<nsFontMetrics> fm = aPresContext->GetMetricsFor(font, params); return GetNormalLineHeight(fm); } // If we don't have a pres context, use a 1.2em fallback. - size.ScaleBy(kNormalLineHeightFactor); + size.ScaleBy(ReflowInput::kNormalLineHeightFactor); return size.ToAppUnits(); } @@ -2816,8 +2836,9 @@ nscoord ReflowInput::CalcLineHeight( nsPresContext* aPresContext, bool aIsVertical, const nsIContent* aContent, nscoord aBlockBSize, float aFontSizeInflation) { nscoord lineHeight = - ComputeLineHeight(aLh, aRelativeToFont, aPresContext, aIsVertical, - aBlockBSize, aFontSizeInflation); + ComputeLineHeight(aLh, aRelativeToFont.mFont, aRelativeToFont.mLanguage, + aRelativeToFont.mExplicitLanguage, aPresContext, + aIsVertical, aBlockBSize, aFontSizeInflation); NS_ASSERTION(lineHeight >= 0, "ComputeLineHeight screwed up"); @@ -2827,8 +2848,9 @@ nscoord ReflowInput::CalcLineHeight( // have a line-height smaller than 'normal'. if (!aLh.IsNormal()) { nscoord normal = ComputeLineHeight( - StyleLineHeight::Normal(), aRelativeToFont, aPresContext, aIsVertical, - aBlockBSize, aFontSizeInflation); + StyleLineHeight::Normal(), aRelativeToFont.mFont, + aRelativeToFont.mLanguage, aRelativeToFont.mExplicitLanguage, + aPresContext, aIsVertical, aBlockBSize, aFontSizeInflation); if (lineHeight < normal) { lineHeight = normal; } @@ -2838,6 +2860,17 @@ nscoord ReflowInput::CalcLineHeight( return lineHeight; } +nscoord ReflowInput::CalcLineHeightForCanvas(const StyleLineHeight& aLh, + const nsFont& aRelativeToFont, + nsAtom* aLanguage, + bool aExplicitLanguage, + nsPresContext* aPresContext, + mozilla::WritingMode aWM) { + return ComputeLineHeight(aLh, aRelativeToFont, aLanguage, aExplicitLanguage, + aPresContext, aWM.IsVertical() && !aWM.IsSideways(), + NS_UNCONSTRAINEDSIZE, 1.0f); +} + bool SizeComputationInput::ComputeMargin(WritingMode aCBWM, nscoord aPercentBasis, LayoutFrameType aFrameType) { |