summaryrefslogtreecommitdiffstats
path: root/layout/generic/ReflowInput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/ReflowInput.cpp')
-rw-r--r--layout/generic/ReflowInput.cpp219
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) {