Add support for calc() to the 'height', 'min-height', and 'max-height' properties. (Bug 585715) r=bzbarsky a2.0=blocking+

This commit is contained in:
L. David Baron 2010-08-25 12:17:55 +02:00
Родитель 46490e81bb
Коммит fce97072e6
21 изменённых файлов: 338 добавлений и 116 удалений

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

@ -1773,6 +1773,8 @@ static nscoord AddPercents(nsLayoutUtils::IntrinsicWidthType aType,
return result;
}
// Use only for widths/heights (or their min/max), since it clamps
// negative calc() results to 0.
static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult)
{
if (aStyle.IsCalcUnit()) {
@ -1781,6 +1783,8 @@ static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult)
}
// If it has no percents, we can pass 0 for the percentage basis.
aResult = nsRuleNode::ComputeComputedCalc(aStyle, 0);
if (aResult < 0)
aResult = 0;
return PR_TRUE;
}
@ -1788,6 +1792,7 @@ static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult)
return PR_FALSE;
aResult = aStyle.GetCoordValue();
NS_ASSERTION(aResult >= 0, "negative widths not allowed");
return PR_TRUE;
}
@ -1813,7 +1818,7 @@ GetPercentHeight(const nsStyleCoord& aStyle,
if (!GetAbsoluteCoord(pos->mHeight, h) &&
!GetPercentHeight(pos->mHeight, f, h)) {
NS_ASSERTION(pos->mHeight.GetUnit() == eStyleUnit_Auto ||
pos->mHeight.GetUnit() == eStyleUnit_Percent,
pos->mHeight.HasPercent(),
"unknown height unit");
nsIAtom* fType = f->GetType();
if (fType != nsGkAtoms::viewportFrame && fType != nsGkAtoms::canvasFrame &&
@ -1844,7 +1849,7 @@ GetPercentHeight(const nsStyleCoord& aStyle,
h = maxh;
} else {
NS_ASSERTION(pos->mMaxHeight.GetUnit() == eStyleUnit_None ||
pos->mMaxHeight.GetUnit() == eStyleUnit_Percent,
pos->mMaxHeight.HasPercent(),
"unknown max-height unit");
}
@ -1854,7 +1859,7 @@ GetPercentHeight(const nsStyleCoord& aStyle,
if (minh > h)
h = minh;
} else {
NS_ASSERTION(pos->mMinHeight.GetUnit() == eStyleUnit_Percent,
NS_ASSERTION(pos->mMinHeight.HasPercent(),
"unknown min-height unit");
}
@ -2248,8 +2253,7 @@ IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
nsStyleUnit unit = aCoord.GetUnit();
return unit == eStyleUnit_Auto || // only for 'height'
unit == eStyleUnit_None || // only for 'max-height'
(unit == eStyleUnit_Percent &&
aCBHeight == NS_AUTOHEIGHT);
(aCBHeight == NS_AUTOHEIGHT && aCoord.HasPercent());
}
#define MULDIV(a,b,c) (nscoord(PRInt64(a) * PRInt64(b) / PRInt64(c)))
@ -2309,7 +2313,7 @@ nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
if (!isAutoHeight) {
height = nsLayoutUtils::
ComputeHeightDependentValue(aCBSize.height, stylePos->mHeight) -
ComputeHeightValue(aCBSize.height, stylePos->mHeight) -
boxSizingAdjust.height;
if (height < 0)
height = 0;
@ -2317,7 +2321,7 @@ nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
if (!IsAutoHeight(stylePos->mMaxHeight, aCBSize.height)) {
maxHeight = nsLayoutUtils::
ComputeHeightDependentValue(aCBSize.height, stylePos->mMaxHeight) -
ComputeHeightValue(aCBSize.height, stylePos->mMaxHeight) -
boxSizingAdjust.height;
if (maxHeight < 0)
maxHeight = 0;
@ -2327,7 +2331,7 @@ nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
if (!IsAutoHeight(stylePos->mMinHeight, aCBSize.height)) {
minHeight = nsLayoutUtils::
ComputeHeightDependentValue(aCBSize.height, stylePos->mMinHeight) -
ComputeHeightValue(aCBSize.height, stylePos->mMinHeight) -
boxSizingAdjust.height;
if (minHeight < 0)
minHeight = 0;

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

@ -776,6 +776,19 @@ public:
nscoord aContainingBlockHeight,
const nsStyleCoord& aCoord);
/*
* Likewise, but for 'height', 'min-height', or 'max-height'.
*/
static nscoord ComputeHeightValue(nscoord aContainingBlockHeight,
const nsStyleCoord& aCoord)
{
nscoord result =
ComputeHeightDependentValue(aContainingBlockHeight, aCoord);
if (result < 0)
result = 0; // clamp calc()
return result;
}
/*
* Calculate the used values for 'width' and 'height' for a replaced element.
*

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

@ -2751,6 +2751,23 @@ IsPaddingZero(nsStyleUnit aUnit, const nsStyleCoord &aCoord)
(aUnit == eStyleUnit_Percent && aCoord.GetPercentValue() == 0.0));
}
static inline PRBool
IsNonAutoNonZeroHeight(const nsStyleCoord& aCoord)
{
if (aCoord.GetUnit() == eStyleUnit_Auto)
return PR_FALSE;
if (aCoord.IsCoordPercentCalcUnit()) {
// If we evaluate the length/percent/calc at a percentage basis of
// both nscoord_MAX and 0, and it's zero both ways, then it's a zero
// length, percent, or combination thereof. Test > 0 so we clamp
// negative calc() results to 0.
return nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) > 0 ||
nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) > 0;
}
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected unit for height or min-height");
return PR_TRUE;
}
/* virtual */ PRBool
nsBlockFrame::IsSelfEmpty()
{
@ -2762,33 +2779,9 @@ nsBlockFrame::IsSelfEmpty()
const nsStylePosition* position = GetStylePosition();
switch (position->mMinHeight.GetUnit()) {
case eStyleUnit_Coord:
if (position->mMinHeight.GetCoordValue() != 0)
return PR_FALSE;
break;
case eStyleUnit_Percent:
if (position->mMinHeight.GetPercentValue() != 0.0f)
return PR_FALSE;
break;
default:
return PR_FALSE;
}
switch (position->mHeight.GetUnit()) {
case eStyleUnit_Auto:
break;
case eStyleUnit_Coord:
if (position->mHeight.GetCoordValue() != 0)
return PR_FALSE;
break;
case eStyleUnit_Percent:
if (position->mHeight.GetPercentValue() != 0.0f)
return PR_FALSE;
break;
default:
return PR_FALSE;
}
if (IsNonAutoNonZeroHeight(position->mMinHeight) ||
IsNonAutoNonZeroHeight(position->mHeight))
return PR_FALSE;
const nsStyleBorder* border = GetStyleBorder();
const nsStylePadding* padding = GetStylePadding();

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

@ -3102,8 +3102,7 @@ IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
nsStyleUnit unit = aCoord.GetUnit();
return unit == eStyleUnit_Auto || // only for 'height'
unit == eStyleUnit_None || // only for 'max-height'
(unit == eStyleUnit_Percent &&
aCBHeight == NS_AUTOHEIGHT);
(aCBHeight == NS_AUTOHEIGHT && aCoord.HasPercent());
}
/* virtual */ nsSize
@ -3156,16 +3155,14 @@ nsFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
if (!IsAutoHeight(stylePos->mHeight, aCBSize.height)) {
result.height =
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
stylePos->mHeight) -
nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mHeight) -
boxSizingAdjust.height;
}
if (result.height != NS_UNCONSTRAINEDSIZE) {
if (!IsAutoHeight(stylePos->mMaxHeight, aCBSize.height)) {
nscoord maxHeight =
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
stylePos->mMaxHeight) -
nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mMaxHeight) -
boxSizingAdjust.height;
if (maxHeight < result.height)
result.height = maxHeight;
@ -3173,8 +3170,7 @@ nsFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
if (!IsAutoHeight(stylePos->mMinHeight, aCBSize.height)) {
nscoord minHeight =
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
stylePos->mMinHeight) -
nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mMinHeight) -
boxSizingAdjust.height;
if (minHeight > result.height)
result.height = minHeight;
@ -3313,10 +3309,9 @@ nsFrame::DidReflow(nsPresContext* aPresContext,
// height. This happens in the case where a table cell has no computed
// height but can fabricate one when the cell height is known.
if (aReflowState && aReflowState->mPercentHeightObserver &&
(eStyleUnit_Percent == aReflowState->mStylePosition->mHeight.GetUnit())) {
nsIFrame* prevInFlow = GetPrevInFlow();
if (!prevInFlow) { // 1st in flow
!GetPrevInFlow()) {
const nsStyleCoord &height = aReflowState->mStylePosition->mHeight;
if (height.HasPercent()) {
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
}
}

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

@ -165,7 +165,7 @@ struct nsHTMLReflowMetrics {
// The rect is in the local coordinate space of the frame, and should be at
// least as big as the desired size. If there is no content that overflows,
// then the overflow area is identical to the desired size and should be
// {0, 0, mWidth, mHeight}.
// {0, 0, width, height}.
nsRect mOverflowArea;
PRUint32 mFlags;

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

@ -395,9 +395,15 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext)
}
PRBool dependsOnCBHeight =
mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent ||
mStylePosition->mMinHeight.GetUnit() == eStyleUnit_Percent ||
mStylePosition->mMaxHeight.GetUnit() == eStyleUnit_Percent ||
(mStylePosition->HeightDependsOnContainer() &&
// FIXME: condition this on not-abspos?
mStylePosition->mHeight.GetUnit() != eStyleUnit_Auto) ||
(mStylePosition->MinHeightDependsOnContainer() &&
// FIXME: condition this on not-abspos?
mStylePosition->mMinHeight.GetUnit() != eStyleUnit_Auto) ||
(mStylePosition->MaxHeightDependsOnContainer() &&
// FIXME: condition this on not-abspos?
mStylePosition->mMaxHeight.GetUnit() != eStyleUnit_Auto) ||
mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Percent ||
mStylePosition->mOffset.GetBottomUnit() != eStyleUnit_Auto ||
frame->IsBoxFrame() ||
@ -1579,6 +1585,7 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(nsPresContext* aPres
} else {
// an element in quirks mode gets a containing block based on looking for a
// parent with a non-auto height if the element has a percent height
// Note: We don't emulate this quirk for percents in calc().
if (NS_AUTOHEIGHT == aContainingBlockHeight) {
if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent) {
@ -1708,12 +1715,14 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
InitOffsets(aContainingBlockWidth, aBorder, aPadding);
nsStyleUnit heightUnit = mStylePosition->mHeight.GetUnit();
const nsStyleCoord &height = mStylePosition->mHeight;
nsStyleUnit heightUnit = height.GetUnit();
// Check for a percentage based height and a containing block height
// that depends on the content height
// XXX twiddling heightUnit doesn't help anymore
if (eStyleUnit_Percent == heightUnit) {
// FIXME Shouldn't we fix that?
if (height.HasPercent()) {
if (NS_AUTOHEIGHT == aContainingBlockHeight) {
// this if clause enables %-height on replaced inline frames,
// such as images. See bug 54119. The else clause "heightUnit = eStyleUnit_Auto;"
@ -1772,7 +1781,8 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
// Internal table elements. The rules vary depending on the type.
// Calculate the computed width
PRBool rowOrRowGroup = PR_FALSE;
nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit();
const nsStyleCoord &width = mStylePosition->mWidth;
nsStyleUnit widthUnit = width.GetUnit();
if ((NS_STYLE_DISPLAY_TABLE_ROW == mStyleDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == mStyleDisplay->mDisplay)) {
// 'width' property doesn't apply to table rows and row groups
@ -1780,7 +1790,8 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
rowOrRowGroup = PR_TRUE;
}
if (eStyleUnit_Auto == widthUnit) {
// calc() acts like auto on internal table elements
if (eStyleUnit_Auto == widthUnit || width.IsCalcUnit()) {
mComputedWidth = availableWidth;
if ((mComputedWidth != NS_UNCONSTRAINEDSIZE) && !rowOrRowGroup){
@ -1807,14 +1818,14 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
// 'height' property doesn't apply to table columns and column groups
heightUnit = eStyleUnit_Auto;
}
if (eStyleUnit_Auto == heightUnit) {
// calc() acts like 'auto' on internal table elements
if (eStyleUnit_Auto == heightUnit || height.IsCalcUnit()) {
mComputedHeight = NS_AUTOHEIGHT;
} else {
NS_ASSERTION(heightUnit == mStylePosition->mHeight.GetUnit(),
"unexpected height unit change");
mComputedHeight = nsLayoutUtils::
ComputeHeightDependentValue(aContainingBlockHeight,
mStylePosition->mHeight);
ComputeHeightValue(aContainingBlockHeight, mStylePosition->mHeight);
}
// Doesn't apply to table elements
@ -2277,28 +2288,36 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth,
// Check for percentage based values and a containing block height that
// depends on the content height. Treat them like 'auto'
if ((NS_AUTOHEIGHT == aContainingBlockHeight) &&
(eStyleUnit_Percent == mStylePosition->mMinHeight.GetUnit())) {
// Likewise, check for calc() on internal table elements; calc() on
// such elements is unsupported.
const nsStyleCoord &minHeight = mStylePosition->mMinHeight;
if ((NS_AUTOHEIGHT == aContainingBlockHeight &&
minHeight.HasPercent()) ||
(mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE &&
minHeight.IsCalcUnit())) {
mComputedMinHeight = 0;
} else {
mComputedMinHeight = nsLayoutUtils::
ComputeHeightDependentValue(aContainingBlockHeight,
mStylePosition->mMinHeight);
ComputeHeightValue(aContainingBlockHeight, minHeight);
}
nsStyleUnit maxHeightUnit = mStylePosition->mMaxHeight.GetUnit();
const nsStyleCoord &maxHeight = mStylePosition->mMaxHeight;
nsStyleUnit maxHeightUnit = maxHeight.GetUnit();
if (eStyleUnit_None == maxHeightUnit) {
// Specified value of 'none'
mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; // no limit
} else {
// Check for percentage based values and a containing block height that
// depends on the content height. Treat them like 'auto'
if ((NS_AUTOHEIGHT == aContainingBlockHeight) &&
(eStyleUnit_Percent == maxHeightUnit)) {
// Likewise, check for calc() on internal table elements; calc() on
// such elements is unsupported.
if ((NS_AUTOHEIGHT == aContainingBlockHeight &&
maxHeight.HasPercent()) ||
(mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE &&
maxHeight.IsCalcUnit())) {
mComputedMaxHeight = NS_UNCONSTRAINEDSIZE;
} else {
mComputedMaxHeight = nsLayoutUtils::
ComputeHeightDependentValue(aContainingBlockHeight,
mStylePosition->mMaxHeight);
ComputeHeightValue(aContainingBlockHeight, maxHeight);
}
}

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

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<title>Test for height:calc() or min-height:calc() on blocks</title>
<style>
body { margin: 0 }
body > div { float: left; width: 1px; background: blue; }
</style>
<!-- tests with a fixed-height container -->
<div style="height: 50px"></div>
<div style="height: 50px"></div>
<div style="height: 75px"></div>
<div style="height: 45px"></div>
<div style="height: 40px"></div>
<div style="height: 30px"></div>
<!-- tests with an auto-height container -->
<div style="height: 50px"></div>
<div style="height: 10px"></div>
<div style="height: 10px"></div>
<div style="height: 10px"></div>
<div style="height: 10px"></div>
<div style="height: 10px"></div>

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

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<title>Test for height:calc() on blocks</title>
<style>
body { margin: 0 }
body > div { float: left; height: 100px; width: 1px; }
body > div > div { background: blue }
/* for auto-height tests */
body > div > div > div > div { height: 10px }
</style>
<!-- tests with a fixed-height container -->
<div><div style="height: -moz-calc(50px)"></div></div>
<div><div style="height: -moz-calc(50%)"></div></div>
<div><div style="height: -moz-calc(25px + 50%)"></div></div>
<div><div style="height: -moz-calc(150% / 2 - 30px)"></div></div>
<div><div style="height: -moz-calc(40px + 10% - 20% / 2)"></div></div>
<div><div style="height: -moz-calc(40px - 10%)"></div></div>
<!-- tests with an auto-height container -->
<div><div><div style="height: -moz-calc(50px)"><div></div></div></div></div>
<div><div><div style="height: -moz-calc(50%)"><div></div></div></div></div>
<div><div><div style="height: -moz-calc(25px + 50%)"><div></div></div></div></div>
<div><div><div style="height: -moz-calc(150% / 2 - 30px)"><div></div></div></div></div>
<div><div><div style="height: -moz-calc(40px + 10% - 20% / 2)"><div></div></div></div></div>
<div><div><div style="height: -moz-calc(40px - 10%)"><div></div></div></div></div>

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

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<title>Test that height:calc() has no effect on inner table elements</title>
<table border>
<tbody>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
</tbody>
</table>

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

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<title>Test that height:calc() has no effect on inner table elements</title>
<style>
tbody, tr, td {
height: -moz-calc(500px);
min-height: -moz-calc(1000px);
max-height: -moz-calc(2px);
}
</style>
<table border>
<tbody>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
</tbody>
</table>

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

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<title>Test for max-height:calc() on blocks</title>
<style>
body { margin: 0 }
body > div { float: left; width: 1px; background: blue; }
</style>
<!-- tests with a fixed-height container -->
<div style="height: 50px"></div>
<div style="height: 50px"></div>
<div style="height: 75px"></div>
<div style="height: 45px"></div>
<div style="height: 40px"></div>
<div style="height: 30px"></div>
<!-- tests with an auto-height container -->
<div style="height: 50px"></div>
<div style="height: 300px"></div>
<div style="height: 300px"></div>
<div style="height: 300px"></div>
<div style="height: 300px"></div>
<div style="height: 300px"></div>

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

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<title>Test for max-height:calc() on blocks</title>
<style>
body { margin: 0 }
body > div { float: left; height: 100px; width: 1px; }
body > div > div { background: blue }
/* to give the max-height something to restrict */
span { display: block; height: 300px }
</style>
<!-- tests with a fixed-height container -->
<div><div style="max-height: -moz-calc(50px)"><span></span></div></div>
<div><div style="max-height: -moz-calc(50%)"><span></span></div></div>
<div><div style="max-height: -moz-calc(25px + 50%)"><span></span></div></div>
<div><div style="max-height: -moz-calc(150% / 2 - 30px)"><span></span></div></div>
<div><div style="max-height: -moz-calc(40px + 10% - 20% / 2)"><span></span></div></div>
<div><div style="max-height: -moz-calc(40px - 10%)"><span></span></div></div>
<!-- tests with an auto-height container -->
<div><div><div style="max-height: -moz-calc(50px)"><span></span></div></div></div>
<div><div><div style="max-height: -moz-calc(50%)"><span></span></div></div></div>
<div><div><div style="max-height: -moz-calc(25px + 50%)"><span></span></div></div></div>
<div><div><div style="max-height: -moz-calc(150% / 2 - 30px)"><span></span></div></div></div>
<div><div><div style="max-height: -moz-calc(40px + 10% - 20% / 2)"><span></span></div></div></div>
<div><div><div style="max-height: -moz-calc(40px - 10%)"><span></span></div></div></div>

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

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<title>Test for min-height:calc() on blocks</title>
<style>
body { margin: 0 }
body > div { float: left; height: 100px; width: 1px; }
body > div > div { background: blue }
/* for auto-height tests */
body > div > div > div > div { height: 10px }
</style>
<!-- tests with a fixed-height container -->
<div><div style="min-height: -moz-calc(50px)"></div></div>
<div><div style="min-height: -moz-calc(50%)"></div></div>
<div><div style="min-height: -moz-calc(25px + 50%)"></div></div>
<div><div style="min-height: -moz-calc(150% / 2 - 30px)"></div></div>
<div><div style="min-height: -moz-calc(40px + 10% - 20% / 2)"></div></div>
<div><div style="min-height: -moz-calc(40px - 10%)"></div></div>
<!-- tests with an auto-height container -->
<div><div><div style="min-height: -moz-calc(50px)"><div></div></div></div></div>
<div><div><div style="min-height: -moz-calc(50%)"><div></div></div></div></div>
<div><div><div style="min-height: -moz-calc(25px + 50%)"><div></div></div></div></div>
<div><div><div style="min-height: -moz-calc(150% / 2 - 30px)"><div></div></div></div></div>
<div><div><div style="min-height: -moz-calc(40px + 10% - 20% / 2)"><div></div></div></div></div>
<div><div><div style="min-height: -moz-calc(40px - 10%)"><div></div></div></div></div>

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

@ -1,3 +1,7 @@
== height-block-1.html height-block-1-ref.html
== height-table-1.html height-table-1-ref.html
== max-height-block-1.html max-height-block-1-ref.html
== min-height-block-1.html height-block-1-ref.html
== width-block-1.html width-block-1-ref.html
== width-block-intrinsic-1.html width-block-intrinsic-1-ref.html
== width-table-auto-1.html width-table-auto-1-ref.html

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

@ -5731,7 +5731,8 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBoxSizingKTable);
case eCSSProperty_height:
return ParseNonNegativeVariant(aValue, VARIANT_AHLP, nsnull);
return ParseNonNegativeVariant(aValue, VARIANT_AHLP | VARIANT_CALC,
nsnull);
case eCSSProperty_width:
return ParseNonNegativeVariant(aValue, VARIANT_AHKLP | VARIANT_CALC,
nsCSSProps::kWidthKTable);
@ -5830,12 +5831,14 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
case eCSSProperty_marks:
return ParseMarks(aValue);
case eCSSProperty_max_height:
return ParseNonNegativeVariant(aValue, VARIANT_HLPO, nsnull);
return ParseNonNegativeVariant(aValue, VARIANT_HLPO | VARIANT_CALC,
nsnull);
case eCSSProperty_max_width:
return ParseNonNegativeVariant(aValue, VARIANT_HKLPO,
nsCSSProps::kWidthKTable);
case eCSSProperty_min_height:
return ParseNonNegativeVariant(aValue, VARIANT_HLP, nsnull);
return ParseNonNegativeVariant(aValue, VARIANT_HLP | VARIANT_CALC,
nsnull);
case eCSSProperty_min_width:
return ParseNonNegativeVariant(aValue, VARIANT_HKLP,
nsCSSProps::kWidthKTable);

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

@ -5548,14 +5548,14 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
mPresContext, canStoreInRuleTree);
SetCoord(posData.mHeight, pos->mHeight, parentPos->mHeight,
SETCOORD_LPAH | SETCOORD_INITIAL_AUTO, aContext,
mPresContext, canStoreInRuleTree);
SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
aContext, mPresContext, canStoreInRuleTree);
SetCoord(posData.mMinHeight, pos->mMinHeight, parentPos->mMinHeight,
SETCOORD_LPH | SETCOORD_INITIAL_ZERO, aContext,
mPresContext, canStoreInRuleTree);
SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
aContext, mPresContext, canStoreInRuleTree);
SetCoord(posData.mMaxHeight, pos->mMaxHeight, parentPos->mMaxHeight,
SETCOORD_LPOH | SETCOORD_INITIAL_NONE, aContext,
mPresContext, canStoreInRuleTree);
SETCOORD_LPOH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC,
aContext, mPresContext, canStoreInRuleTree);
// box-sizing: enum, inherit, initial
SetDiscrete(posData.mBoxSizing, pos->mBoxSizing, canStoreInRuleTree,

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

@ -1089,9 +1089,9 @@ struct nsStylePosition {
nsStyleCoord mWidth; // [reset] coord, percent, enum, auto
nsStyleCoord mMinWidth; // [reset] coord, percent, enum
nsStyleCoord mMaxWidth; // [reset] coord, percent, enum, none
nsStyleCoord mHeight; // [reset] coord, percent, auto
nsStyleCoord mMinHeight; // [reset] coord, percent
nsStyleCoord mMaxHeight; // [reset] coord, percent, none
nsStyleCoord mHeight; // [reset] coord, percent, calc, auto
nsStyleCoord mMinHeight; // [reset] coord, percent, calc
nsStyleCoord mMaxHeight; // [reset] coord, percent, calc, none
PRUint8 mBoxSizing; // [reset] see nsStyleConsts.h
nsStyleCoord mZIndex; // [reset] integer, auto
@ -1113,7 +1113,7 @@ private:
static PRBool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
{
return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
aCoord.GetUnit() == eStyleUnit_Percent;
aCoord.HasPercent();
}
};

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

@ -1584,7 +1584,14 @@ var gCSSProperties = {
initial_values: [ " auto" ],
/* computed value tests for height test more with display:block */
prerequisites: { "display": "block" },
other_values: [ "15px", "3em", "15%" ],
other_values: [ "15px", "3em", "15%",
"-moz-calc(2px)",
"-moz-calc(50%)",
"-moz-calc(3*25px)",
"-moz-calc(25px*3)",
"-moz-calc(3*25px + 50%)",
"-moz-min(30%, 30em,200px, min(500px ,40em))",
],
invalid_values: [ "none", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available" ]
},
"ime-mode": {
@ -1759,7 +1766,14 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
prerequisites: { "display": "block" },
initial_values: [ "none" ],
other_values: [ "30px", "50%", "0" ],
other_values: [ "30px", "50%", "0",
"-moz-calc(2px)",
"-moz-calc(50%)",
"-moz-calc(3*25px)",
"-moz-calc(25px*3)",
"-moz-calc(3*25px + 50%)",
"-moz-min(30%, 30em,200px, min(500px ,40em))",
],
invalid_values: [ "auto", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available" ]
},
"max-width": {
@ -1777,7 +1791,14 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
prerequisites: { "display": "block" },
initial_values: [ "0" ],
other_values: [ "30px", "50%" ],
other_values: [ "30px", "50%",
"-moz-calc(2px)",
"-moz-calc(50%)",
"-moz-calc(3*25px)",
"-moz-calc(25px*3)",
"-moz-calc(3*25px + 50%)",
"-moz-min(30%, 30em,200px, min(500px ,40em))",
],
invalid_values: [ "auto", "none", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available" ]
},
"min-width": {

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

@ -1589,7 +1589,9 @@ nsTableFrame::AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowSta
if (IS_TABLE_CELL(frameType) ||
(nsGkAtoms::tableRowFrame == frameType) ||
(nsGkAtoms::tableRowGroupFrame == frameType)) {
if (rs->mStylePosition->mHeight.GetUnit() != eStyleUnit_Auto) {
const nsStyleCoord &height = rs->mStylePosition->mHeight;
// calc() treated like 'auto' on internal table elements
if (height.GetUnit() != eStyleUnit_Auto && !height.IsCalcUnit()) {
return PR_TRUE;
}
}
@ -1608,6 +1610,11 @@ nsTableFrame::AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowSta
void
nsTableFrame::CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState)
{
NS_ASSERTION(IS_TABLE_CELL(aReflowState.frame->GetType()) ||
aReflowState.frame->GetType() == nsGkAtoms::tableRowFrame ||
aReflowState.frame->GetType() == nsGkAtoms::tableRowGroupFrame ||
aReflowState.frame->GetType() == nsGkAtoms::tableFrame,
"unexpected frame type");
if (!aReflowState.frame->GetPrevInFlow() && // 1st in flow
(NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight() || // no computed height
0 == aReflowState.ComputedHeight()) &&
@ -3349,26 +3356,11 @@ nsTableFrame::GetTableFrame(nsIFrame* aSourceFrame)
PRBool
nsTableFrame::IsAutoHeight()
{
PRBool isAuto = PR_TRUE; // the default
const nsStylePosition* position = GetStylePosition();
switch (position->mHeight.GetUnit()) {
case eStyleUnit_Auto: // specified auto width
break;
case eStyleUnit_Coord:
isAuto = PR_FALSE;
break;
case eStyleUnit_Percent:
if (position->mHeight.GetPercentValue() > 0.0f) {
isAuto = PR_FALSE;
}
break;
default:
break;
}
return isAuto;
const nsStyleCoord &height = GetStylePosition()->mHeight;
// Don't consider calc() here like this quirk for percent.
return height.GetUnit() == eStyleUnit_Auto ||
(height.GetUnit() == eStyleUnit_Percent &&
height.GetPercentValue() <= 0.0f);
}
nscoord

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

@ -547,6 +547,7 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
else if (eStyleUnit_Percent == position->mHeight.GetUnit()) {
SetPctHeight(position->mHeight.GetPercentValue());
}
// calc() is treated like 'auto' on table rows.
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame;
kidFrame = kidFrame->GetNextSibling()) {
@ -675,7 +676,7 @@ nsTableRowFrame::CalculateCellActualHeight(nsTableCellFrame* aCellFrame,
break;
}
case eStyleUnit_Auto:
default:
default: // includes calc(), which we treat like 'auto'
break;
}
@ -1405,8 +1406,10 @@ void nsTableRowFrame::InitHasCellWithStyleHeight(nsTableFrame* aTableFrame)
continue;
}
// Ignore row-spanning cells
const nsStyleCoord &cellHeight = cellFrame->GetStylePosition()->mHeight;
if (aTableFrame->GetEffectiveRowSpan(*cellFrame) == 1 &&
cellFrame->GetStylePosition()->mHeight.GetUnit() != eStyleUnit_Auto) {
cellHeight.GetUnit() != eStyleUnit_Auto &&
!cellHeight.IsCalcUnit() /* calc() treated like 'auto' */) {
AddStateBits(NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT);
return;
}

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

@ -687,15 +687,26 @@ nsIBox::AddCSSPrefSize(nsIBox* aBox, nsSize& aSize, PRBool &aWidthSet, PRBool &a
if (!width.CalcHasPercent()) {
// pass 0 for percentage basis since we know there are no %s
aSize.width = nsRuleNode::ComputeComputedCalc(width, 0);
if (aSize.width < 0)
aSize.width = 0;
aWidthSet = PR_TRUE;
}
}
if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
aSize.height = position->mHeight.GetCoordValue();
const nsStyleCoord &height = position->mHeight;
if (height.GetUnit() == eStyleUnit_Coord) {
aSize.height = height.GetCoordValue();
aHeightSet = PR_TRUE;
} else if (height.IsCalcUnit()) {
if (!height.CalcHasPercent()) {
// pass 0 for percentage basis since we know there are no %s
aSize.height = nsRuleNode::ComputeComputedCalc(height, 0);
if (aSize.height < 0)
aSize.height = 0;
aHeightSet = PR_TRUE;
}
}
nsIContent* content = aBox->GetContent();
// ignore 'height' and 'width' attributes if the actual element is not XUL
// For example, we might be magic XUL frames whose primary content is an HTML
@ -780,18 +791,23 @@ nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize,
// GetPrefSize/GetMinSize methods that don't consider
// (min-/max-/)(width/height) properties.
if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) {
nscoord min = position->mMinHeight.GetCoordValue();
if (min && (!aHeightSet || (min > aSize.height && canOverride))) {
const nsStyleCoord &minHeight = position->mMinHeight;
if ((minHeight.GetUnit() == eStyleUnit_Coord &&
minHeight.GetCoordValue() != 0) ||
(minHeight.IsCalcUnit() && !minHeight.CalcHasPercent())) {
nscoord min = nsRuleNode::ComputeCoordPercentCalc(minHeight, 0);
if (!aHeightSet || (min > aSize.height && canOverride)) {
aSize.height = min;
aHeightSet = PR_TRUE;
}
} else if (position->mMinHeight.GetUnit() == eStyleUnit_Percent) {
} else if (minHeight.GetUnit() == eStyleUnit_Percent) {
NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f,
"Non-zero percentage values not currently supported");
aSize.height = 0;
aHeightSet = PR_TRUE;
aHeightSet = PR_TRUE; // FIXME: should we really do this for
// nonzero values?
}
// calc() with percentage is treated like '0' (unset)
nsIContent* content = aBox->GetContent();
if (content) {
@ -847,10 +863,12 @@ nsIBox::AddCSSMaxSize(nsIBox* aBox, nsSize& aSize, PRBool &aWidthSet, PRBool &aH
aWidthSet = PR_TRUE;
}
if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) {
aSize.height = position->mMaxHeight.GetCoordValue();
const nsStyleCoord &maxHeight = position->mMaxHeight;
if (maxHeight.ConvertsToLength()) {
aSize.height = nsRuleNode::ComputeCoordPercentCalc(maxHeight, 0);
aHeightSet = PR_TRUE;
}
// percentages and calc() with percentages are treated like 'none'
nsIContent* content = aBox->GetContent();
if (content) {