Bug 1105268 - part 1 - Fix the logical/physical confusion with min- and max- dimensions in nsFrame::ComputeSize(). r=smontagu

This commit is contained in:
Jonathan Kew 2014-11-27 15:01:11 +00:00
parent c5ea153ed0
commit f8c40475ef
3 changed files with 103 additions and 53 deletions

View File

@ -4354,27 +4354,27 @@ nsLayoutUtils::ComputeCBDependentValue(nscoord aPercentBasis,
}
/* static */ nscoord
nsLayoutUtils::ComputeWidthValue(
nsLayoutUtils::ComputeISizeValue(
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
nscoord aContainingBlockWidth,
nscoord aContainingBlockISize,
nscoord aContentEdgeToBoxSizing,
nscoord aBoxSizingToMarginEdge,
const nsStyleCoord& aCoord)
{
NS_PRECONDITION(aFrame, "non-null frame expected");
NS_PRECONDITION(aRenderingContext, "non-null rendering context expected");
NS_WARN_IF_FALSE(aContainingBlockWidth != NS_UNCONSTRAINEDSIZE,
"have unconstrained width; this should only result from "
"very large sizes, not attempts at intrinsic width "
NS_WARN_IF_FALSE(aContainingBlockISize != NS_UNCONSTRAINEDSIZE,
"have unconstrained inline-size; this should only result from "
"very large sizes, not attempts at intrinsic inline-size "
"calculation");
NS_PRECONDITION(aContainingBlockWidth >= 0,
"width less than zero");
NS_PRECONDITION(aContainingBlockISize >= 0,
"inline-size less than zero");
nscoord result;
if (aCoord.IsCoordPercentCalcUnit()) {
result = nsRuleNode::ComputeCoordPercentCalc(aCoord,
aContainingBlockWidth);
aContainingBlockISize);
// The result of a calc() expression might be less than 0; we
// should clamp at runtime (below). (Percentages and coords that
// are less than 0 have already been dropped by the parser.)
@ -4389,24 +4389,24 @@ nsLayoutUtils::ComputeWidthValue(
switch (val) {
case NS_STYLE_WIDTH_MAX_CONTENT:
result = aFrame->GetPrefISize(aRenderingContext);
NS_ASSERTION(result >= 0, "width less than zero");
NS_ASSERTION(result >= 0, "inline-size less than zero");
break;
case NS_STYLE_WIDTH_MIN_CONTENT:
result = aFrame->GetMinISize(aRenderingContext);
NS_ASSERTION(result >= 0, "width less than zero");
NS_ASSERTION(result >= 0, "inline-size less than zero");
break;
case NS_STYLE_WIDTH_FIT_CONTENT:
{
nscoord pref = aFrame->GetPrefISize(aRenderingContext),
min = aFrame->GetMinISize(aRenderingContext),
fill = aContainingBlockWidth -
fill = aContainingBlockISize -
(aBoxSizingToMarginEdge + aContentEdgeToBoxSizing);
result = std::max(min, std::min(pref, fill));
NS_ASSERTION(result >= 0, "width less than zero");
NS_ASSERTION(result >= 0, "inline-size less than zero");
}
break;
case NS_STYLE_WIDTH_AVAILABLE:
result = aContainingBlockWidth -
result = aContainingBlockISize -
(aBoxSizingToMarginEdge + aContentEdgeToBoxSizing);
}
}
@ -4415,28 +4415,28 @@ nsLayoutUtils::ComputeWidthValue(
}
/* static */ nscoord
nsLayoutUtils::ComputeHeightDependentValue(
nscoord aContainingBlockHeight,
nsLayoutUtils::ComputeBSizeDependentValue(
nscoord aContainingBlockBSize,
const nsStyleCoord& aCoord)
{
// XXXldb Some callers explicitly check aContainingBlockHeight
// XXXldb Some callers explicitly check aContainingBlockBSize
// against NS_AUTOHEIGHT *and* unit against eStyleUnit_Percent or
// calc()s containing percents before calling this function.
// However, it would be much more likely to catch problems without
// the unit conditions.
// XXXldb Many callers pass a non-'auto' containing block height when
// according to CSS2.1 they should be passing 'auto'.
NS_PRECONDITION(NS_AUTOHEIGHT != aContainingBlockHeight ||
NS_PRECONDITION(NS_AUTOHEIGHT != aContainingBlockBSize ||
!aCoord.HasPercent(),
"unexpected containing block height");
"unexpected containing block block-size");
if (aCoord.IsCoordPercentCalcUnit()) {
return nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockHeight);
return nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockBSize);
}
NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_None ||
aCoord.GetUnit() == eStyleUnit_Auto,
"unexpected height value");
"unexpected block-size value");
return 0;
}

View File

@ -1295,45 +1295,86 @@ public:
* and margin that goes outside the rect chosen by box-sizing.
* @param aCoord The width value to compute.
*/
// XXX to be removed
static nscoord ComputeWidthValue(
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
nscoord aContainingBlockWidth,
nscoord aContentEdgeToBoxSizing,
nscoord aBoxSizingToMarginEdge,
const nsStyleCoord& aCoord);
const nsStyleCoord& aCoord)
{
return ComputeISizeValue(aRenderingContext,
aFrame,
aContainingBlockWidth,
aContentEdgeToBoxSizing,
aBoxSizingToMarginEdge,
aCoord);
}
static nscoord ComputeISizeValue(
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
nscoord aContainingBlockISize,
nscoord aContentEdgeToBoxSizing,
nscoord aBoxSizingToMarginEdge,
const nsStyleCoord& aCoord);
/*
* Convert nsStyleCoord to nscoord when percentages depend on the
* containing block height.
*/
// XXX to be removed
static nscoord ComputeHeightDependentValue(
nscoord aContainingBlockHeight,
const nsStyleCoord& aCoord)
{
return ComputeBSizeDependentValue(aContainingBlockHeight, aCoord);
}
static nscoord ComputeBSizeDependentValue(
nscoord aContainingBlockBSize,
const nsStyleCoord& aCoord);
/*
* Likewise, but for 'height', 'min-height', or 'max-height'.
*/
// XXX to be removed
static nscoord ComputeHeightValue(nscoord aContainingBlockHeight,
nscoord aContentEdgeToBoxSizingBoxEdge,
const nsStyleCoord& aCoord)
{
MOZ_ASSERT(aContainingBlockHeight != nscoord_MAX || !aCoord.HasPercent(),
"caller must deal with %% of unconstrained height");
return ComputeBSizeValue(aContainingBlockHeight,
aContentEdgeToBoxSizingBoxEdge,
aCoord);
}
static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
nscoord aContentEdgeToBoxSizingBoxEdge,
const nsStyleCoord& aCoord)
{
MOZ_ASSERT(aContainingBlockBSize != nscoord_MAX || !aCoord.HasPercent(),
"caller must deal with %% of unconstrained block-size");
MOZ_ASSERT(aCoord.IsCoordPercentCalcUnit());
nscoord result =
nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockHeight);
nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockBSize);
// Clamp calc(), and the subtraction for box-sizing.
return std::max(0, result - aContentEdgeToBoxSizingBoxEdge);
}
// XXX to be removed
static bool IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
{
return IsAutoBSize(aCoord, aCBHeight);
}
static bool IsAutoBSize(const nsStyleCoord &aCoord, nscoord aCBBSize)
{
nsStyleUnit unit = aCoord.GetUnit();
return unit == eStyleUnit_Auto || // only for 'height'
unit == eStyleUnit_None || // only for 'max-height'
(aCBHeight == nscoord_MAX && aCoord.HasPercent());
(aCBBSize == nscoord_MAX && aCoord.HasPercent());
}
static bool IsPaddingZero(const nsStyleCoord &aCoord)

View File

@ -4139,15 +4139,12 @@ nsFrame::ComputeSize(nsRenderingContext *aRenderingContext,
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
boxSizingAdjust.ISize(aWM);
const nsStyleCoord* inlineStyleCoord;
const nsStyleCoord* blockStyleCoord;
if (aWM.IsVertical()) {
inlineStyleCoord = &(stylePos->mHeight);
blockStyleCoord = &(stylePos->mWidth);
} else {
inlineStyleCoord = &(stylePos->mWidth);
blockStyleCoord = &(stylePos->mHeight);
}
bool isVertical = aWM.IsVertical();
const nsStyleCoord* inlineStyleCoord =
isVertical ? &(stylePos->mHeight) : &(stylePos->mWidth);
const nsStyleCoord* blockStyleCoord =
isVertical ? &(stylePos->mWidth) : &(stylePos->mHeight);
bool isFlexItem = IsFlexItem();
bool isInlineFlexItem = false;
@ -4188,30 +4185,36 @@ nsFrame::ComputeSize(nsRenderingContext *aRenderingContext,
if (inlineStyleCoord->GetUnit() != eStyleUnit_Auto) {
result.ISize(aWM) =
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
nsLayoutUtils::ComputeISizeValue(aRenderingContext, this,
aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
*inlineStyleCoord);
}
const nsStyleCoord& maxISizeCoord =
isVertical ? stylePos->mMaxHeight : stylePos->mMaxWidth;
// Flex items ignore their min & max sizing properties in their
// flex container's main-axis. (Those properties get applied later in
// the flexbox algorithm.)
if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_None &&
if (maxISizeCoord.GetUnit() != eStyleUnit_None &&
!(isFlexItem && isInlineFlexItem)) {
nscoord maxISize =
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
nsLayoutUtils::ComputeISizeValue(aRenderingContext, this,
aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
stylePos->mMaxWidth);
maxISizeCoord);
result.ISize(aWM) = std::min(maxISize, result.ISize(aWM));
}
const nsStyleCoord& minISizeCoord =
isVertical ? stylePos->mMinHeight : stylePos->mMinWidth;
nscoord minISize;
if (stylePos->mMinWidth.GetUnit() != eStyleUnit_Auto &&
if (minISizeCoord.GetUnit() != eStyleUnit_Auto &&
!(isFlexItem && isInlineFlexItem)) {
minISize =
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
nsLayoutUtils::ComputeISizeValue(aRenderingContext, this,
aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
stylePos->mMinWidth);
minISizeCoord);
} else {
// Treat "min-width: auto" as 0.
// NOTE: Technically, "auto" is supposed to behave like "min-content" on
@ -4226,30 +4229,36 @@ nsFrame::ComputeSize(nsRenderingContext *aRenderingContext,
// (but not if we're auto-height or if we recieved the "eUseAutoHeight"
// flag -- then, we'll just stick with the height that we already calculated
// in the initial ComputeAutoSize() call.)
if (!nsLayoutUtils::IsAutoHeight(*blockStyleCoord, aCBSize.BSize(aWM)) &&
if (!nsLayoutUtils::IsAutoBSize(*blockStyleCoord, aCBSize.BSize(aWM)) &&
!(aFlags & nsIFrame::eUseAutoHeight)) {
result.BSize(aWM) =
nsLayoutUtils::ComputeHeightValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
*blockStyleCoord);
nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
*blockStyleCoord);
}
const nsStyleCoord& maxBSizeCoord =
isVertical ? stylePos->mMaxWidth : stylePos->mMaxHeight;
if (result.BSize(aWM) != NS_UNCONSTRAINEDSIZE) {
if (!nsLayoutUtils::IsAutoHeight(stylePos->mMaxHeight, aCBSize.BSize(aWM)) &&
if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
nscoord maxBSize =
nsLayoutUtils::ComputeHeightValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
stylePos->mMaxHeight);
nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
maxBSizeCoord);
result.BSize(aWM) = std::min(maxBSize, result.BSize(aWM));
}
if (!nsLayoutUtils::IsAutoHeight(stylePos->mMinHeight, aCBSize.BSize(aWM)) &&
const nsStyleCoord& minBSizeCoord =
isVertical ? stylePos->mMinWidth : stylePos->mMinHeight;
if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) &&
!(isFlexItem && !isInlineFlexItem)) {
nscoord minBSize =
nsLayoutUtils::ComputeHeightValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
stylePos->mMinHeight);
nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
minBSizeCoord);
result.BSize(aWM) = std::max(minBSize, result.BSize(aWM));
}
}