Bug 1686603 Part 4 - Use StyleSizeOverrides to revise flex base size resolution. r=dholbert

Differential Revision: https://phabricator.services.mozilla.com/D101795
This commit is contained in:
Ting-Yu Lin 2021-01-25 22:25:57 +00:00
Родитель 6d16aa20ce
Коммит 902b99ce81
4 изменённых файлов: 76 добавлений и 100 удалений

Просмотреть файл

@ -567,8 +567,10 @@ LogicalSize nsTextControlFrame::ComputeAutoSize(
// Note: nsContainerFrame::ComputeAutoSize only computes the inline-size (and
// only for 'auto'), the block-size it returns is always NS_UNCONSTRAINEDSIZE.
const auto& iSizeCoord = StylePosition()->ISize(aWM);
if (iSizeCoord.IsAuto()) {
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize
: StylePosition()->ISize(aWM);
if (styleISize.IsAuto()) {
if (aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize)) {
// CalcIntrinsicSize isn't aware of grid-item margin-box clamping, so we
// fall back to nsContainerFrame's ComputeAutoSize to handle that.

Просмотреть файл

@ -986,16 +986,10 @@ LogicalSize nsContainerFrame::ComputeAutoSize(
if (aFlags.contains(ComputeSizeFlag::ShrinkWrap) ||
IsFrameOfType(eReplaced)) {
// Only bother computing our 'auto' ISize if the result will be used.
// It'll be used under two scenarios:
// - If our ISize property is itself 'auto'.
// - If we're using flex-basis in place of our ISize property (i.e. we're a
// flex item with our inline axis being the main axis), AND we have
// flex-basis:content.
const nsStylePosition* pos = StylePosition();
if (pos->ISize(aWM).IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize) ||
(pos->mFlexBasis.IsContent() && IsFlexItem() &&
nsFlexContainerFrame::IsItemInlineAxisMainAxis(this))) {
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize
: StylePosition()->ISize(aWM);
if (styleISize.IsAuto() || aFlags.contains(ComputeSizeFlag::UseAutoISize)) {
result.ISize(aWM) =
ShrinkWidthToFit(aRenderingContext, availBased, aFlags);
}
@ -2394,8 +2388,12 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
const nsStylePosition* stylePos = StylePosition();
const auto* inlineStyleCoord = &stylePos->ISize(aWM);
const auto* blockStyleCoord = &stylePos->BSize(aWM);
const auto* inlineStyleCoord = aSizeOverrides.mStyleISize
? aSizeOverrides.mStyleISize.ptr()
: &stylePos->ISize(aWM);
const auto* blockStyleCoord = aSizeOverrides.mStyleBSize
? aSizeOverrides.mStyleBSize.ptr()
: &stylePos->BSize(aWM);
auto* parentFrame = GetParent();
const bool isGridItem = IsGridItem();
const bool isFlexItem =
@ -2432,45 +2430,6 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
} else {
blockStyleCoord = imposedMainSizeStyleCoord.ptr();
}
} else {
// Flex items use their "flex-basis" property in place of their main-size
// property (e.g. "width") for sizing purposes, *unless* they have
// "flex-basis:auto", in which case they use their main-size property
// after all.
// NOTE: The logic here should match the similar chunk for updating
// mainAxisCoord in nsIFrame::ComputeSize() (aside from using a different
// dummy value in the IsUsedFlexBasisContent() case).
const auto* flexBasis = &stylePos->mFlexBasis;
auto& mainAxisCoord =
(flexMainAxis == eLogicalAxisInline ? inlineStyleCoord
: blockStyleCoord);
if (nsFlexContainerFrame::IsUsedFlexBasisContent(*flexBasis,
*mainAxisCoord)) {
// If we get here, we're resolving the flex base size for a flex item,
// and we fall into the flexbox spec section 9.2 step 3, substep C (if
// we have a definite cross size) or E (if not). And specifically:
//
// * If we have a definite cross size, we're supposed to resolve our
// main-size based on that and our intrinsic ratio.
// * Otherwise, we're supposed to produce our max-content size.
//
// Conveniently, we can handle both of those scenarios (regardless of
// which substep we fall into) by using the 'auto' keyword for our
// main-axis coordinate here. (This makes sense, because the spec is
// effectively trying to produce the 'auto' sizing behavior).
static const StyleSize autoSize(StyleSize::Auto());
mainAxisCoord = &autoSize;
} else if (flexBasis->IsSize() && !flexBasis->IsAuto()) {
// For all other non-'auto' flex-basis values, we just swap in the
// flex-basis itself for the main-size property.
mainAxisCoord = &flexBasis->AsSize();
} else {
MOZ_ASSERT(flexBasis->IsAuto());
// else: flex-basis is 'auto', which is deferring to some explicit
// value in mainAxisCoord. So we proceed w/o touching mainAxisCoord.
}
}
}

Просмотреть файл

@ -1287,12 +1287,61 @@ FlexItem* nsFlexContainerFrame::GenerateFlexItemForChild(
FlexLine& aLine, nsIFrame* aChildFrame,
const ReflowInput& aParentReflowInput,
const FlexboxAxisTracker& aAxisTracker, bool aHasLineClampEllipsis) {
const auto flexWM = aAxisTracker.GetWritingMode();
const auto childWM = aChildFrame->GetWritingMode();
const auto* stylePos = aChildFrame->StylePosition();
// Construct a StyleSizeOverrides for this flex item so that its ReflowInput
// below will use and resolve its flex base size rather than its corresponding
// preferred main size property (only for modern CSS flexbox).
StyleSizeOverrides sizeOverrides;
if (!IsLegacyBox(this)) {
Maybe<StyleSize> styleFlexBaseSize;
// When resolving flex base size, flex items use their 'flex-basis' property
// in place of their preferred main size (e.g. 'width') for sizing purposes,
// *unless* they have 'flex-basis:auto' in which case they use their
// preferred main size after all.
const auto& flexBasis = stylePos->mFlexBasis;
const auto& styleMainSize = stylePos->Size(aAxisTracker.MainAxis(), flexWM);
if (IsUsedFlexBasisContent(flexBasis, styleMainSize)) {
// If we get here, we're resolving the flex base size for a flex item, and
// we fall into the flexbox spec section 9.2 step 3, substep C (if we have
// a definite cross size) or E (if not).
if (aChildFrame->GetAspectRatio()) {
// FIXME: This is a workaround. Once bug 1670151 is fixed, aspect-ratio
// will be considered when resolving flex item's flex base size with the
// value 'max-content'.
styleFlexBaseSize.emplace(StyleSize::Auto());
} else {
styleFlexBaseSize.emplace(
StyleSize::ExtremumLength(StyleExtremumLength::MaxContent));
}
} else if (flexBasis.IsSize() && !flexBasis.IsAuto()) {
// For all other non-'auto' flex-basis values, we just swap in the
// flex-basis itself for the preferred main-size property.
styleFlexBaseSize.emplace(flexBasis.AsSize());
} else {
// else: flex-basis is 'auto', which is deferring to some explicit value
// in the preferred main size, so we proceed without emplacing
// styleFlexBaseSize.
MOZ_ASSERT(flexBasis.IsAuto());
}
// Provide the size override for the preferred main size property.
if (aAxisTracker.IsInlineAxisMainAxis(childWM)) {
sizeOverrides.mStyleISize = std::move(styleFlexBaseSize);
} else {
sizeOverrides.mStyleBSize = std::move(styleFlexBaseSize);
}
}
// Create temporary reflow input just for sizing -- to get hypothetical
// main-size and the computed values of min / max main-size property.
// (This reflow input will _not_ be used for reflow.)
ReflowInput childRI(
PresContext(), aParentReflowInput, aChildFrame,
aParentReflowInput.ComputedSize(aChildFrame->GetWritingMode()));
ReflowInput childRI(PresContext(), aParentReflowInput, aChildFrame,
aParentReflowInput.ComputedSize(childWM), Nothing(), {},
sizeOverrides);
childRI.mFlags.mInsideLineClamp = GetLineClampValue() != 0;
// FLEX GROW & SHRINK WEIGHTS
@ -1306,14 +1355,10 @@ FlexItem* nsFlexContainerFrame::GenerateFlexItemForChild(
flexGrow = flexShrink = aChildFrame->StyleXUL()->mBoxFlex;
}
} else {
const nsStylePosition* stylePos = aChildFrame->StylePosition();
flexGrow = stylePos->mFlexGrow;
flexShrink = stylePos->mFlexShrink;
}
const auto childWM = childRI.GetWritingMode();
const auto flexWM = aAxisTracker.GetWritingMode();
// MAIN SIZES (flex base size, min/max size)
// -----------------------------------------
nscoord flexBaseSize = GET_MAIN_COMPONENT_LOGICAL(

Просмотреть файл

@ -6095,8 +6095,12 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
aBorderPadding.ISize(aWM) -
boxSizingAdjust.ISize(aWM);
const auto* inlineStyleCoord = &stylePos->ISize(aWM);
const auto* blockStyleCoord = &stylePos->BSize(aWM);
const auto* inlineStyleCoord = aSizeOverrides.mStyleISize
? aSizeOverrides.mStyleISize.ptr()
: &stylePos->ISize(aWM);
const auto* blockStyleCoord = aSizeOverrides.mStyleBSize
? aSizeOverrides.mStyleBSize.ptr()
: &stylePos->BSize(aWM);
auto parentFrame = GetParent();
auto alignCB = parentFrame;
@ -6129,22 +6133,10 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
Maybe<StyleSize> imposedMainSizeStyleCoord;
if (isFlexItem) {
// Flex items use their "flex-basis" property in place of their main-size
// property for sizing purposes, *unless* they have "flex-basis:auto", in
// which case they use their main-size property after all.
flexMainAxis = nsFlexContainerFrame::IsItemInlineAxisMainAxis(this)
? eLogicalAxisInline
: eLogicalAxisBlock;
// NOTE: The logic here should match the similar chunk for updating
// mainAxisCoord in nsContainerFrame::ComputeSizeWithIntrinsicDimensions()
// (aside from using a different dummy value in the IsUsedFlexBasisContent()
// case).
const auto* flexBasis = &stylePos->mFlexBasis;
auto& mainAxisCoord =
(flexMainAxis == eLogicalAxisInline ? inlineStyleCoord
: blockStyleCoord);
// If FlexItemMainSizeOverride frame-property is set, then that means the
// flex container is imposing a main-size on this flex item for it to use
// as its size in the container's main axis.
@ -6159,30 +6151,6 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
} else {
blockStyleCoord = imposedMainSizeStyleCoord.ptr();
}
} else {
// NOTE: If we're a table-wrapper frame, we skip this clause and just
// stick with 'main-size:auto' behavior (which -- unlike 'content' i.e.
// 'max-content' -- will give us the ability to honor percent sizes on our
// table-box child when resolving the flex base size). The flexbox spec
// doesn't call for this special case, but webcompat &
// regression-avoidance seems to require it, for the time being... Tables
// sure are special.
if (nsFlexContainerFrame::IsUsedFlexBasisContent(*flexBasis,
*mainAxisCoord) &&
MOZ_LIKELY(!IsTableWrapperFrame())) {
static const StyleSize maxContStyleCoord(
StyleSize::ExtremumLength(StyleExtremumLength::MaxContent));
mainAxisCoord = &maxContStyleCoord;
// (Note: if our main axis is the block axis, then this 'max-content'
// value will be treated like 'auto', via the IsAutoBSize() call below.)
} else if (flexBasis->IsSize() && !flexBasis->IsAuto()) {
// For all other non-'auto' flex-basis values, we just swap in the
// flex-basis itself for the main-size property.
mainAxisCoord = &flexBasis->AsSize();
} else {
// else: flex-basis is 'auto', or 'content' in a table wrapper frame
// which we ignore. So we proceed w/o touching mainAxisCoord.
}
}
}
@ -6438,8 +6406,10 @@ LogicalSize nsIFrame::ComputeAutoSize(
LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE);
// don't bother setting it if the result won't be used
if (StylePosition()->ISize(aWM).IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize)) {
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize
: StylePosition()->ISize(aWM);
if (styleISize.IsAuto() || aFlags.contains(ComputeSizeFlag::UseAutoISize)) {
nscoord availBased =
aAvailableISize - aMargin.ISize(aWM) - aBorderPadding.ISize(aWM);
result.ISize(aWM) = ShrinkWidthToFit(aRenderingContext, availBased, aFlags);