Bug 1300369 part 8 - Move nsLayoutUtils::ComputeSizeWithIntrinsicDimensions to a nsFrame method (idempotent patch). r=dholbert

This commit is contained in:
Mats Palmgren 2016-11-05 02:57:06 +01:00
Родитель e54d8218a4
Коммит ddb49488f0
10 изменённых файлов: 396 добавлений и 418 удалений

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

@ -5432,366 +5432,6 @@ nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize(nsIFrame* aFrame)
} while (stack.Length() != 0);
}
/* static */
LogicalSize
nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(WritingMode aWM,
nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
const IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio,
const mozilla::LogicalSize& aCBSize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding)
{
const nsStylePosition* stylePos = aFrame->StylePosition();
const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
const nsIAtom* parentFrameType =
aFrame->GetParent() ? aFrame->GetParent()->GetType() : nullptr;
const bool isGridItem = (parentFrameType == nsGkAtoms::gridContainerFrame &&
!(aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW));
const bool isFlexItem = (parentFrameType == nsGkAtoms::flexContainerFrame &&
!(aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW));
bool isInlineFlexItem = false;
Maybe<nsStyleCoord> imposedMainSizeStyleCoord;
// If this is a flex item, and we're measuring its cross size after flexing
// to resolve its main size, then we need to use the resolved main size
// that the container provides to us *instead of* the main-size coordinate
// from our style struct. (Otherwise, we'll be using an irrelevant value in
// the aspect-ratio calculations below.)
if (isFlexItem) {
uint32_t flexDirection =
aFrame->GetParent()->StylePosition()->mFlexDirection;
isInlineFlexItem =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
// 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.
FrameProperties props = aFrame->Properties();
bool didImposeMainSize;
nscoord imposedMainSize =
props.Get(nsIFrame::FlexItemMainSizeOverride(), &didImposeMainSize);
if (didImposeMainSize) {
imposedMainSizeStyleCoord.emplace(imposedMainSize,
nsStyleCoord::CoordConstructor);
if (isInlineFlexItem) {
inlineStyleCoord = imposedMainSizeStyleCoord.ptr();
} 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 determining
// inlineStyleCoord and blockStyleCoord in nsFrame::ComputeSize().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
if (isInlineFlexItem) {
inlineStyleCoord = flexBasis;
} else {
// One caveat for vertical flex items: We don't support enumerated
// values (e.g. "max-content") for height properties yet. So, if our
// computed flex-basis is an enumerated value, we'll just behave as if
// it were "auto", which means "use the main-size property after all"
// (which is "height", in this case).
// NOTE: Once we support intrinsic sizing keywords for "height",
// we should remove this check.
if (flexBasis->GetUnit() != eStyleUnit_Enumerated) {
blockStyleCoord = flexBasis;
}
}
}
}
}
// Handle intrinsic sizes and their interaction with
// {min-,max-,}{width,height} according to the rules in
// http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
// Note: throughout the following section of the function, I avoid
// a * (b / c) because of its reduced accuracy relative to a * b / c
// or (a * b) / c (which are equivalent).
const bool isAutoISize = inlineStyleCoord->GetUnit() == eStyleUnit_Auto;
const bool isAutoBSize = IsAutoBSize(*blockStyleCoord, aCBSize.BSize(aWM));
LogicalSize boxSizingAdjust(aWM);
if (stylePos->mBoxSizing == StyleBoxSizing::Border) {
boxSizingAdjust = aBorder + aPadding;
}
nscoord boxSizingToMarginEdgeISize =
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
boxSizingAdjust.ISize(aWM);
nscoord iSize, minISize, maxISize, bSize, minBSize, maxBSize;
// true if we are stretching a Grid item in the inline dimension
bool stretchI = false;
// true if we are stretching a Grid item in the block dimension
bool stretchB = false;
if (!isAutoISize) {
iSize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
aFrame, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, *inlineStyleCoord);
} else if (MOZ_UNLIKELY(isGridItem)) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(aFrame));
// 'auto' inline-size for grid-level box - apply 'stretch' as needed:
auto cbSize = aCBSize.ISize(aWM);
if (cbSize != NS_UNCONSTRAINEDSIZE &&
!aFrame->StyleMargin()->HasInlineAxisAuto(aWM)) {
auto inlineAxisAlignment =
aWM.IsOrthogonalTo(aFrame->GetParent()->GetWritingMode()) ?
stylePos->UsedAlignSelf(aFrame->GetParent()->StyleContext()) :
stylePos->UsedJustifySelf(aFrame->GetParent()->StyleContext());
stretchI = inlineAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
inlineAxisAlignment == NS_STYLE_ALIGN_STRETCH;
if (stretchI) {
iSize = std::max(nscoord(0), cbSize -
aPadding.ISize(aWM) -
aBorder.ISize(aWM) -
aMargin.ISize(aWM));
}
}
}
const nsStyleCoord& maxISizeCoord = stylePos->MaxISize(aWM);
if (maxISizeCoord.GetUnit() != eStyleUnit_None &&
!(isFlexItem && isInlineFlexItem)) {
maxISize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
aFrame, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, maxISizeCoord);
} else {
maxISize = nscoord_MAX;
}
// NOTE: Flex items ignore their min & max sizing properties in their
// flex container's main-axis. (Those properties get applied later in
// the flexbox algorithm.)
const nsStyleCoord& minISizeCoord = stylePos->MinISize(aWM);
if (minISizeCoord.GetUnit() != eStyleUnit_Auto &&
!(isFlexItem && isInlineFlexItem)) {
minISize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
aFrame, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, minISizeCoord);
} else {
// Treat "min-width: auto" as 0.
// NOTE: Technically, "auto" is supposed to behave like "min-content" on
// flex items. However, we don't need to worry about that here, because
// flex items' min-sizes are intentionally ignored until the flex
// container explicitly considers them during space distribution.
minISize = 0;
}
if (!isAutoBSize) {
bSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
*blockStyleCoord);
} else if (MOZ_UNLIKELY(isGridItem)) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(aFrame));
// 'auto' block-size for grid-level box - apply 'stretch' as needed:
auto cbSize = aCBSize.BSize(aWM);
if (cbSize != NS_AUTOHEIGHT &&
!aFrame->StyleMargin()->HasBlockAxisAuto(aWM)) {
auto blockAxisAlignment =
!aWM.IsOrthogonalTo(aFrame->GetParent()->GetWritingMode()) ?
stylePos->UsedAlignSelf(aFrame->GetParent()->StyleContext()) :
stylePos->UsedJustifySelf(aFrame->GetParent()->StyleContext());
stretchB = blockAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
blockAxisAlignment == NS_STYLE_ALIGN_STRETCH;
if (stretchB) {
bSize = std::max(nscoord(0), cbSize -
aPadding.BSize(aWM) -
aBorder.BSize(aWM) -
aMargin.BSize(aWM));
}
}
}
const nsStyleCoord& maxBSizeCoord = stylePos->MaxBSize(aWM);
if (!IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
maxBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), maxBSizeCoord);
} else {
maxBSize = nscoord_MAX;
}
const nsStyleCoord& minBSizeCoord = stylePos->MinBSize(aWM);
if (!IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
minBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), minBSizeCoord);
} else {
minBSize = 0;
}
// Resolve percentage intrinsic iSize/bSize as necessary:
NS_ASSERTION(aCBSize.ISize(aWM) != NS_UNCONSTRAINEDSIZE,
"Our containing block must not have unconstrained inline-size!");
const bool isVertical = aWM.IsVertical();
const nsStyleCoord& isizeCoord =
isVertical ? aIntrinsicSize.height : aIntrinsicSize.width;
const nsStyleCoord& bsizeCoord =
isVertical ? aIntrinsicSize.width : aIntrinsicSize.height;
bool hasIntrinsicISize, hasIntrinsicBSize;
nscoord intrinsicISize, intrinsicBSize;
if (isizeCoord.GetUnit() == eStyleUnit_Coord) {
hasIntrinsicISize = true;
intrinsicISize = isizeCoord.GetCoordValue();
if (intrinsicISize < 0)
intrinsicISize = 0;
} else {
NS_ASSERTION(isizeCoord.GetUnit() == eStyleUnit_None,
"unexpected unit");
hasIntrinsicISize = false;
intrinsicISize = 0;
}
if (bsizeCoord.GetUnit() == eStyleUnit_Coord) {
hasIntrinsicBSize = true;
intrinsicBSize = bsizeCoord.GetCoordValue();
if (intrinsicBSize < 0)
intrinsicBSize = 0;
} else {
NS_ASSERTION(bsizeCoord.GetUnit() == eStyleUnit_None,
"unexpected unit");
hasIntrinsicBSize = false;
intrinsicBSize = 0;
}
NS_ASSERTION(aIntrinsicRatio.width >= 0 && aIntrinsicRatio.height >= 0,
"Intrinsic ratio has a negative component!");
LogicalSize logicalRatio(aWM, aIntrinsicRatio);
// Now calculate the used values for iSize and bSize:
if (isAutoISize) {
if (isAutoBSize) {
// 'auto' iSize, 'auto' bSize
// Get tentative values - CSS 2.1 sections 10.3.2 and 10.6.2:
nscoord tentISize, tentBSize;
if (hasIntrinsicISize) {
tentISize = intrinsicISize;
} else if (hasIntrinsicBSize && logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(intrinsicBSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
} else if (logicalRatio.ISize(aWM) > 0) {
tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar?
if (tentISize < 0) tentISize = 0;
} else {
tentISize = nsPresContext::CSSPixelsToAppUnits(300);
}
if (hasIntrinsicBSize) {
tentBSize = intrinsicBSize;
} else if (logicalRatio.ISize(aWM) > 0) {
tentBSize = NSCoordMulDiv(tentISize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
} else {
tentBSize = nsPresContext::CSSPixelsToAppUnits(150);
}
if (aIntrinsicRatio != nsSize(0, 0)) {
if (stretchI || stretchB) {
// Stretch within the CB size with preserved intrinsic ratio.
if (stretchI && tentISize != iSize) {
tentISize = iSize; // fill the CB iSize
if (logicalRatio.ISize(aWM) > 0) {
tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
if (tentBSize > bSize && stretchB) {
// We're stretching in both dimensions and the bSize calculated
// from the iSize / ratio would overflow the CB bSize, so stretch
// the bSize instead and derive the iSize which will then fit.
tentBSize = bSize; // fill the CB bSize
if (logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
}
}
} else if (stretchB && tentBSize != bSize) {
tentBSize = bSize; // fill the CB bSize
if (logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
}
}
nsSize autoSize =
ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize,
maxISize, maxBSize,
tentISize, tentBSize);
// The nsSize that ComputeAutoSizeWithIntrinsicDimensions returns will
// actually contain logical values if the parameters passed to it were
// logical coordinates, so we do NOT perform a physical-to-logical
// conversion here, but just assign the fields directly to our result.
iSize = autoSize.width;
bSize = autoSize.height;
} else {
// No intrinsic ratio, so just clamp the dimensions
// independently without calling
// ComputeAutoSizeWithIntrinsicDimensions, which deals with
// propagating these changes to the other dimension (and would
// be incorrect when there is no intrinsic ratio).
iSize = NS_CSS_MINMAX(tentISize, minISize, maxISize);
bSize = NS_CSS_MINMAX(tentBSize, minBSize, maxBSize);
}
} else {
// 'auto' iSize, non-'auto' bSize
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
if (logicalRatio.BSize(aWM) > 0) {
iSize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
} else if (hasIntrinsicISize) {
iSize = intrinsicISize;
} else {
iSize = nsPresContext::CSSPixelsToAppUnits(300);
}
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
}
} else {
if (isAutoBSize) {
// non-'auto' iSize, 'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
if (logicalRatio.ISize(aWM) > 0) {
bSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
} else if (hasIntrinsicBSize) {
bSize = intrinsicBSize;
} else {
bSize = nsPresContext::CSSPixelsToAppUnits(150);
}
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
} else {
// non-'auto' iSize, non-'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
}
}
return LogicalSize(aWM, iSize, bSize);
}
nsSize
nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord minHeight,
nscoord maxWidth, nscoord maxHeight,

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

@ -1526,21 +1526,6 @@ public:
static void MarkIntrinsicISizesDirtyIfDependentOnBSize(nsIFrame* aFrame);
/*
* Calculate the used values for 'width' and 'height' for a replaced element.
*
* http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
*/
static mozilla::LogicalSize
ComputeSizeWithIntrinsicDimensions(mozilla::WritingMode aWM,
nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
const mozilla::IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio,
const mozilla::LogicalSize& aCBSize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding);
/*
* Calculate the used values for 'width' and 'height' when width
* and height are 'auto'. The tentWidth and tentHeight arguments should be

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

@ -1464,7 +1464,7 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
// -------------------------------------------------------------
// Indicates whether the cross-size property is set to something definite.
// The logic here should be similar to the logic for isAutoWidth/isAutoHeight
// in nsLayoutUtils::ComputeSizeWithIntrinsicDimensions().
// in nsFrame::ComputeSizeWithIntrinsicDimensions().
static bool
IsCrossSizeDefinite(const ReflowInput& aItemReflowInput,
const FlexboxAxisTracker& aAxisTracker)
@ -4089,7 +4089,7 @@ private:
// Class to let us temporarily provide an override value for the the main-size
// CSS property ('width' or 'height') on a flex item, for use in
// nsLayoutUtils::ComputeSizeWithIntrinsicDimensions.
// nsFrame::ComputeSizeWithIntrinsicDimensions.
// (We could use this overridden size more broadly, too, but it's probably
// better to avoid property-table accesses. So, where possible, we communicate
// the resolved main-size to the child via modifying its reflow state directly,

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

@ -4650,7 +4650,7 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
{
MOZ_ASSERT(GetIntrinsicRatio() == nsSize(0,0),
"Please override this method and call "
"nsLayoutUtils::ComputeSizeWithIntrinsicDimensions instead.");
"nsFrame::ComputeSizeWithIntrinsicDimensions instead.");
LogicalSize result = ComputeAutoSize(aRenderingContext, aWM,
aCBSize, aAvailableISize,
aMargin, aBorder, aPadding,
@ -4686,7 +4686,7 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
// NOTE: The logic here should match the similar chunk for determining
// inlineStyleCoord and blockStyleCoord in
// nsLayoutUtils::ComputeSizeWithIntrinsicDimensions().
// nsFrame::ComputeSizeWithIntrinsicDimensions().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
if (isInlineFlexItem) {
@ -4856,6 +4856,366 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
return result;
}
LogicalSize
nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingContext,
WritingMode aWM,
const IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio,
const LogicalSize& aCBSize,
const LogicalSize& aMargin,
const LogicalSize& aBorder,
const LogicalSize& aPadding)
{
const nsStylePosition* stylePos = StylePosition();
const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
const nsIAtom* parentFrameType =
GetParent() ? GetParent()->GetType() : nullptr;
const bool isGridItem = (parentFrameType == nsGkAtoms::gridContainerFrame &&
!(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
const bool isFlexItem = (parentFrameType == nsGkAtoms::flexContainerFrame &&
!(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
bool isInlineFlexItem = false;
Maybe<nsStyleCoord> imposedMainSizeStyleCoord;
// If this is a flex item, and we're measuring its cross size after flexing
// to resolve its main size, then we need to use the resolved main size
// that the container provides to us *instead of* the main-size coordinate
// from our style struct. (Otherwise, we'll be using an irrelevant value in
// the aspect-ratio calculations below.)
if (isFlexItem) {
uint32_t flexDirection =
GetParent()->StylePosition()->mFlexDirection;
isInlineFlexItem =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
// 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.
FrameProperties props = Properties();
bool didImposeMainSize;
nscoord imposedMainSize =
props.Get(nsIFrame::FlexItemMainSizeOverride(), &didImposeMainSize);
if (didImposeMainSize) {
imposedMainSizeStyleCoord.emplace(imposedMainSize,
nsStyleCoord::CoordConstructor);
if (isInlineFlexItem) {
inlineStyleCoord = imposedMainSizeStyleCoord.ptr();
} 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 determining
// inlineStyleCoord and blockStyleCoord in nsFrame::ComputeSize().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
if (isInlineFlexItem) {
inlineStyleCoord = flexBasis;
} else {
// One caveat for vertical flex items: We don't support enumerated
// values (e.g. "max-content") for height properties yet. So, if our
// computed flex-basis is an enumerated value, we'll just behave as if
// it were "auto", which means "use the main-size property after all"
// (which is "height", in this case).
// NOTE: Once we support intrinsic sizing keywords for "height",
// we should remove this check.
if (flexBasis->GetUnit() != eStyleUnit_Enumerated) {
blockStyleCoord = flexBasis;
}
}
}
}
}
// Handle intrinsic sizes and their interaction with
// {min-,max-,}{width,height} according to the rules in
// http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
// Note: throughout the following section of the function, I avoid
// a * (b / c) because of its reduced accuracy relative to a * b / c
// or (a * b) / c (which are equivalent).
const bool isAutoISize = inlineStyleCoord->GetUnit() == eStyleUnit_Auto;
const bool isAutoBSize =
nsLayoutUtils::IsAutoBSize(*blockStyleCoord, aCBSize.BSize(aWM));
LogicalSize boxSizingAdjust(aWM);
if (stylePos->mBoxSizing == StyleBoxSizing::Border) {
boxSizingAdjust = aBorder + aPadding;
}
nscoord boxSizingToMarginEdgeISize =
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
boxSizingAdjust.ISize(aWM);
nscoord iSize, minISize, maxISize, bSize, minBSize, maxBSize;
// true if we are stretching a Grid item in the inline dimension
bool stretchI = false;
// true if we are stretching a Grid item in the block dimension
bool stretchB = false;
if (!isAutoISize) {
iSize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
this, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, *inlineStyleCoord);
} else if (MOZ_UNLIKELY(isGridItem)) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(this));
// 'auto' inline-size for grid-level box - apply 'stretch' as needed:
auto cbSize = aCBSize.ISize(aWM);
if (cbSize != NS_UNCONSTRAINEDSIZE &&
!StyleMargin()->HasInlineAxisAuto(aWM)) {
auto inlineAxisAlignment =
aWM.IsOrthogonalTo(GetParent()->GetWritingMode()) ?
stylePos->UsedAlignSelf(GetParent()->StyleContext()) :
stylePos->UsedJustifySelf(GetParent()->StyleContext());
stretchI = inlineAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
inlineAxisAlignment == NS_STYLE_ALIGN_STRETCH;
if (stretchI) {
iSize = std::max(nscoord(0), cbSize -
aPadding.ISize(aWM) -
aBorder.ISize(aWM) -
aMargin.ISize(aWM));
}
}
}
const nsStyleCoord& maxISizeCoord = stylePos->MaxISize(aWM);
if (maxISizeCoord.GetUnit() != eStyleUnit_None &&
!(isFlexItem && isInlineFlexItem)) {
maxISize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
this, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, maxISizeCoord);
} else {
maxISize = nscoord_MAX;
}
// NOTE: Flex items ignore their min & max sizing properties in their
// flex container's main-axis. (Those properties get applied later in
// the flexbox algorithm.)
const nsStyleCoord& minISizeCoord = stylePos->MinISize(aWM);
if (minISizeCoord.GetUnit() != eStyleUnit_Auto &&
!(isFlexItem && isInlineFlexItem)) {
minISize = nsLayoutUtils::ComputeISizeValue(aRenderingContext,
this, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, minISizeCoord);
} else {
// Treat "min-width: auto" as 0.
// NOTE: Technically, "auto" is supposed to behave like "min-content" on
// flex items. However, we don't need to worry about that here, because
// flex items' min-sizes are intentionally ignored until the flex
// container explicitly considers them during space distribution.
minISize = 0;
}
if (!isAutoBSize) {
bSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
*blockStyleCoord);
} else if (MOZ_UNLIKELY(isGridItem)) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(this));
// 'auto' block-size for grid-level box - apply 'stretch' as needed:
auto cbSize = aCBSize.BSize(aWM);
if (cbSize != NS_AUTOHEIGHT &&
!StyleMargin()->HasBlockAxisAuto(aWM)) {
auto blockAxisAlignment =
!aWM.IsOrthogonalTo(GetParent()->GetWritingMode()) ?
stylePos->UsedAlignSelf(GetParent()->StyleContext()) :
stylePos->UsedJustifySelf(GetParent()->StyleContext());
stretchB = blockAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
blockAxisAlignment == NS_STYLE_ALIGN_STRETCH;
if (stretchB) {
bSize = std::max(nscoord(0), cbSize -
aPadding.BSize(aWM) -
aBorder.BSize(aWM) -
aMargin.BSize(aWM));
}
}
}
const nsStyleCoord& maxBSizeCoord = stylePos->MaxBSize(aWM);
if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
maxBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), maxBSizeCoord);
} else {
maxBSize = nscoord_MAX;
}
const nsStyleCoord& minBSizeCoord = stylePos->MinBSize(aWM);
if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
minBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), minBSizeCoord);
} else {
minBSize = 0;
}
// Resolve percentage intrinsic iSize/bSize as necessary:
NS_ASSERTION(aCBSize.ISize(aWM) != NS_UNCONSTRAINEDSIZE,
"Our containing block must not have unconstrained inline-size!");
const bool isVertical = aWM.IsVertical();
const nsStyleCoord& isizeCoord =
isVertical ? aIntrinsicSize.height : aIntrinsicSize.width;
const nsStyleCoord& bsizeCoord =
isVertical ? aIntrinsicSize.width : aIntrinsicSize.height;
bool hasIntrinsicISize, hasIntrinsicBSize;
nscoord intrinsicISize, intrinsicBSize;
if (isizeCoord.GetUnit() == eStyleUnit_Coord) {
hasIntrinsicISize = true;
intrinsicISize = isizeCoord.GetCoordValue();
if (intrinsicISize < 0)
intrinsicISize = 0;
} else {
NS_ASSERTION(isizeCoord.GetUnit() == eStyleUnit_None,
"unexpected unit");
hasIntrinsicISize = false;
intrinsicISize = 0;
}
if (bsizeCoord.GetUnit() == eStyleUnit_Coord) {
hasIntrinsicBSize = true;
intrinsicBSize = bsizeCoord.GetCoordValue();
if (intrinsicBSize < 0)
intrinsicBSize = 0;
} else {
NS_ASSERTION(bsizeCoord.GetUnit() == eStyleUnit_None,
"unexpected unit");
hasIntrinsicBSize = false;
intrinsicBSize = 0;
}
NS_ASSERTION(aIntrinsicRatio.width >= 0 && aIntrinsicRatio.height >= 0,
"Intrinsic ratio has a negative component!");
LogicalSize logicalRatio(aWM, aIntrinsicRatio);
// Now calculate the used values for iSize and bSize:
if (isAutoISize) {
if (isAutoBSize) {
// 'auto' iSize, 'auto' bSize
// Get tentative values - CSS 2.1 sections 10.3.2 and 10.6.2:
nscoord tentISize, tentBSize;
if (hasIntrinsicISize) {
tentISize = intrinsicISize;
} else if (hasIntrinsicBSize && logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(intrinsicBSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
} else if (logicalRatio.ISize(aWM) > 0) {
tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar?
if (tentISize < 0) tentISize = 0;
} else {
tentISize = nsPresContext::CSSPixelsToAppUnits(300);
}
if (hasIntrinsicBSize) {
tentBSize = intrinsicBSize;
} else if (logicalRatio.ISize(aWM) > 0) {
tentBSize = NSCoordMulDiv(tentISize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
} else {
tentBSize = nsPresContext::CSSPixelsToAppUnits(150);
}
if (aIntrinsicRatio != nsSize(0, 0)) {
if (stretchI || stretchB) {
// Stretch within the CB size with preserved intrinsic ratio.
if (stretchI && tentISize != iSize) {
tentISize = iSize; // fill the CB iSize
if (logicalRatio.ISize(aWM) > 0) {
tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
if (tentBSize > bSize && stretchB) {
// We're stretching in both dimensions and the bSize calculated
// from the iSize / ratio would overflow the CB bSize, so stretch
// the bSize instead and derive the iSize which will then fit.
tentBSize = bSize; // fill the CB bSize
if (logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
}
}
} else if (stretchB && tentBSize != bSize) {
tentBSize = bSize; // fill the CB bSize
if (logicalRatio.BSize(aWM) > 0) {
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
}
}
nsSize autoSize = nsLayoutUtils::
ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize,
maxISize, maxBSize,
tentISize, tentBSize);
// The nsSize that ComputeAutoSizeWithIntrinsicDimensions returns will
// actually contain logical values if the parameters passed to it were
// logical coordinates, so we do NOT perform a physical-to-logical
// conversion here, but just assign the fields directly to our result.
iSize = autoSize.width;
bSize = autoSize.height;
} else {
// No intrinsic ratio, so just clamp the dimensions
// independently without calling
// ComputeAutoSizeWithIntrinsicDimensions, which deals with
// propagating these changes to the other dimension (and would
// be incorrect when there is no intrinsic ratio).
iSize = NS_CSS_MINMAX(tentISize, minISize, maxISize);
bSize = NS_CSS_MINMAX(tentBSize, minBSize, maxBSize);
}
} else {
// 'auto' iSize, non-'auto' bSize
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
if (logicalRatio.BSize(aWM) > 0) {
iSize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
} else if (hasIntrinsicISize) {
iSize = intrinsicISize;
} else {
iSize = nsPresContext::CSSPixelsToAppUnits(300);
}
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
}
} else {
if (isAutoBSize) {
// non-'auto' iSize, 'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
if (logicalRatio.ISize(aWM) > 0) {
bSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
} else if (hasIntrinsicBSize) {
bSize = intrinsicBSize;
} else {
bSize = nsPresContext::CSSPixelsToAppUnits(150);
}
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
} else {
// non-'auto' iSize, non-'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
}
}
return LogicalSize(aWM, iSize, bSize);
}
nsRect
nsIFrame::ComputeTightBounds(DrawTarget* aDrawTarget) const
{

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

@ -275,6 +275,21 @@ public:
const mozilla::LogicalSize& aPadding,
ComputeSizeFlags aFlags) override;
/**
* Calculate the used values for 'width' and 'height' for a replaced element.
* http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
*/
mozilla::LogicalSize
ComputeSizeWithIntrinsicDimensions(
nsRenderingContext* aRenderingContext,
mozilla::WritingMode aWM,
const mozilla::IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio,
const mozilla::LogicalSize& aCBSize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding);
// Compute tight bounds assuming this frame honours its border, background
// and outline, its children's tight bounds, and nothing else.
nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;

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

@ -236,14 +236,9 @@ nsHTMLCanvasFrame::ComputeSize(nsRenderingContext *aRenderingContext,
nsSize intrinsicRatio = GetIntrinsicRatio(); // won't actually be used
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
aWM,
aRenderingContext, this,
intrinsicSize, intrinsicRatio,
aCBSize,
aMargin,
aBorder,
aPadding);
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, intrinsicRatio,
aCBSize, aMargin, aBorder, aPadding);
}
void

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

@ -870,13 +870,9 @@ nsImageFrame::ComputeSize(nsRenderingContext *aRenderingContext,
}
}
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM,
aRenderingContext, this,
intrinsicSize, mIntrinsicRatio,
aCBSize,
aMargin,
aBorder,
aPadding);
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, mIntrinsicRatio,
aCBSize, aMargin, aBorder, aPadding);
}
// XXXdholbert This function's clients should probably just be calling

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

@ -717,14 +717,11 @@ nsSubDocumentFrame::ComputeSize(nsRenderingContext* aRenderingContext,
{
nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
if (subDocRoot) {
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM,
aRenderingContext, this,
subDocRoot->GetIntrinsicSize(),
subDocRoot->GetIntrinsicRatio(),
aCBSize,
aMargin,
aBorder,
aPadding);
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
subDocRoot->GetIntrinsicSize(),
subDocRoot->GetIntrinsicRatio(),
aCBSize, aMargin, aBorder,
aPadding);
}
return nsAtomicContainerFrame::ComputeSize(aRenderingContext, aWM,
aCBSize, aAvailableISize,

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

@ -535,15 +535,9 @@ nsVideoFrame::ComputeSize(nsRenderingContext *aRenderingContext,
// Only video elements have an intrinsic ratio.
nsSize intrinsicRatio = HasVideoElement() ? size : nsSize(0, 0);
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM,
aRenderingContext,
this,
intrinsicSize,
intrinsicRatio,
aCBSize,
aMargin,
aBorder,
aPadding);
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, intrinsicRatio,
aCBSize, aMargin, aBorder, aPadding);
}
nscoord nsVideoFrame::GetMinISize(nsRenderingContext *aRenderingContext)

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

@ -347,13 +347,9 @@ nsSVGOuterSVGFrame::ComputeSize(nsRenderingContext *aRenderingContext,
"we lack an intrinsic height or width.");
}
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM,
aRenderingContext, this,
intrinsicSize, GetIntrinsicRatio(),
cbSize,
aMargin,
aBorder,
aPadding);
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, GetIntrinsicRatio(),
cbSize, aMargin, aBorder, aPadding);
}
void