diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 9bc80d917fce..bffef0ddd22e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3262,14 +3262,13 @@ nsLayoutUtils::SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC) static PRBool NonZeroStyleCoord(const nsStyleCoord& aCoord) { - switch (aCoord.GetUnit()) { - case eStyleUnit_Percent: - return aCoord.GetPercentValue() > 0; - case eStyleUnit_Coord: - return aCoord.GetCoordValue() > 0; - default: - return PR_TRUE; + if (aCoord.IsCoordPercentCalcUnit()) { + // Since negative results are clamped to 0, check > 0. + return nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) > 0 || + nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) > 0; } + + return PR_TRUE; } /* static */ PRBool diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 0fa7bac44a03..cf2f450e96f7 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -749,19 +749,15 @@ nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius, nscoord axis = NS_HALF_CORNER_IS_X(i) ? aFrameSize.width : aFrameSize.height; - switch (c.GetUnit()) { - case eStyleUnit_Percent: - aRadii[i] = (nscoord)(c.GetPercentValue() * axis); - break; - - case eStyleUnit_Coord: - aRadii[i] = c.GetCoordValue(); - break; - - default: - NS_NOTREACHED("ComputeBorderRadii: bad unit"); + if (c.IsCoordPercentCalcUnit()) { + aRadii[i] = nsRuleNode::ComputeCoordPercentCalc(c, axis); + if (aRadii[i] < 0) { + // clamp calc() aRadii[i] = 0; - break; + } + } else { + NS_NOTREACHED("ComputeBorderRadii: bad unit"); + aRadii[i] = 0; } } diff --git a/layout/reftests/css-calc/border-radius-1-ref.html b/layout/reftests/css-calc/border-radius-1-ref.html new file mode 100644 index 000000000000..c906eb97f711 --- /dev/null +++ b/layout/reftests/css-calc/border-radius-1-ref.html @@ -0,0 +1,13 @@ + +test for border-radius: calc() + +

diff --git a/layout/reftests/css-calc/border-radius-1.html b/layout/reftests/css-calc/border-radius-1.html new file mode 100644 index 000000000000..3dc740f0efe9 --- /dev/null +++ b/layout/reftests/css-calc/border-radius-1.html @@ -0,0 +1,13 @@ + +test for border-radius: calc() + +

diff --git a/layout/reftests/css-calc/reftest.list b/layout/reftests/css-calc/reftest.list index 9bd2ca21ee44..0daf129afd2e 100644 --- a/layout/reftests/css-calc/reftest.list +++ b/layout/reftests/css-calc/reftest.list @@ -1,3 +1,4 @@ +== border-radius-1.html border-radius-1-ref.html == height-block-1.html height-block-1-ref.html == height-table-1.html height-table-1-ref.html == margin-block-1.html margin-block-1-ref.html diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 7873fdb0fec7..de492fb9bc8e 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -5068,13 +5068,13 @@ CSSParserImpl::ParseBoxCornerRadius(nsCSSProperty aPropID) { nsCSSValue dimenX, dimenY; // required first value - if (! ParseNonNegativeVariant(dimenX, VARIANT_HLP, nsnull)) + if (! ParseNonNegativeVariant(dimenX, VARIANT_HLP | VARIANT_CALC, nsnull)) return PR_FALSE; // optional second value (forbidden if first value is inherit/initial) if (dimenX.GetUnit() != eCSSUnit_Inherit && dimenX.GetUnit() != eCSSUnit_Initial) { - ParseNonNegativeVariant(dimenY, VARIANT_LP, nsnull); + ParseNonNegativeVariant(dimenY, VARIANT_LP | VARIANT_CALC, nsnull); } if (dimenX == dimenY || dimenY.GetUnit() == eCSSUnit_Null) { @@ -5098,7 +5098,9 @@ CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[]) NS_FOR_CSS_SIDES (side) { if (! ParseNonNegativeVariant(dimenX.*nsCSSRect::sides[side], - side > 0 ? VARIANT_LP : VARIANT_HLP, nsnull)) + (side > 0 ? 0 : VARIANT_INHERIT) | + VARIANT_LP | VARIANT_CALC, + nsnull)) break; countX++; } @@ -5108,7 +5110,7 @@ CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[]) if (ExpectSymbol('/', PR_TRUE)) { NS_FOR_CSS_SIDES (side) { if (! ParseNonNegativeVariant(dimenY.*nsCSSRect::sides[side], - VARIANT_LP, nsnull)) + VARIANT_LP | VARIANT_CALC, nsnull)) break; countY++; } diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 2f4f7abfcd07..659e81110af5 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -5195,7 +5195,8 @@ nsRuleNode::ComputeBorderData(void* aStartStruct, nsStyleCoord coordX, coordY; if (SetPairCoords(radius, coordX, coordY, parentX, parentY, - SETCOORD_LPH | SETCOORD_INITIAL_ZERO, + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | + SETCOORD_STORE_CALC, aContext, mPresContext, canStoreInRuleTree)) { border->mBorderRadius.Set(cx, coordX); border->mBorderRadius.Set(cy, coordY); @@ -5406,7 +5407,8 @@ nsRuleNode::ComputeOutlineData(void* aStartStruct, nsStyleCoord coordX, coordY; if (SetPairCoords(radius, coordX, coordY, parentX, parentY, - SETCOORD_LPH | SETCOORD_INITIAL_ZERO, + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | + SETCOORD_STORE_CALC, aContext, mPresContext, canStoreInRuleTree)) { outline->mOutlineRadius.Set(cx, coordX); outline->mOutlineRadius.Set(cy, coordY); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 906c4d6f6fd0..2a285a1809ef 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -749,7 +749,7 @@ struct nsStyleBorder { static PRBool ForceCompare() { return PR_FALSE; } PRBool ImageBorderDiffers() const; - nsStyleCorners mBorderRadius; // [reset] coord, percent + nsStyleCorners mBorderRadius; // [reset] coord, percent, calc nsStyleSides mBorderImageSplit; // [reset] integer, percent PRUint8 mFloatEdge; // [reset] see nsStyleConsts.h PRUint8 mBorderImageHFill; // [reset] @@ -972,7 +972,7 @@ struct nsStyleOutline { #endif static PRBool ForceCompare() { return PR_FALSE; } - nsStyleCorners mOutlineRadius; // [reset] coord, percent + nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc // Note that this is a specified value. You can get the actual values // with GetOutlineWidth. You cannot get the computed value directly. diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 413b3620b37e..5bf6524b1faf 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -165,7 +165,18 @@ var gCSSProperties = { subproperties: [ "-moz-border-radius-bottomleft", "-moz-border-radius-bottomright", "-moz-border-radius-topleft", "-moz-border-radius-topright" ], initial_values: [ "0", "0px", "0px 0 0 0px" ], /* 0% ? */ other_values: [ "3%", "1px", "2em", "3em 2px", "2pt 3% 4em", "2px 2px 2px 2px", // circular - "3% / 2%", "1px / 4px", "2em / 1em", "3em 2px / 2px 3em", "2pt 3% 4em / 4pt 1% 5em", "2px 2px 2px 2px / 4px 4px 4px 4px", "1pt / 2pt 3pt", "4pt 5pt / 3pt" // elliptical + "3% / 2%", "1px / 4px", "2em / 1em", "3em 2px / 2px 3em", "2pt 3% 4em / 4pt 1% 5em", "2px 2px 2px 2px / 4px 4px 4px 4px", "1pt / 2pt 3pt", "4pt 5pt / 3pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", + "2px 2px -moz-calc(2px + 1%) 2px", + "1px 2px 2px 2px / 2px 2px -moz-calc(2px + 1%) 2px", ], invalid_values: [ "2px -2px", "inherit 2px", "inherit / 2px", "2px inherit", "2px / inherit", "2px 2px 2px 2px 2px", "1px / 2px 2px 2px 2px 2px" ] }, @@ -175,7 +186,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px" ], /* 0% ? */ other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -185,7 +205,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px" ], /* 0% ? */ other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -195,7 +224,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px" ], /* 0% ? */ other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -205,7 +243,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px" ], /* 0% ? */ other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -607,7 +654,18 @@ var gCSSProperties = { subproperties: [ "-moz-outline-radius-bottomleft", "-moz-outline-radius-bottomright", "-moz-outline-radius-topleft", "-moz-outline-radius-topright" ], initial_values: [ "0", "0px", "0%" ], other_values: [ "3%", "1px", "2em", "3em 2px", "2pt 3% 4em", "2px 2px 2px 2px", // circular - "3% / 2%", "1px / 4px", "2em / 1em", "3em 2px / 2px 3em", "2pt 3% 4em / 4pt 1% 5em", "2px 2px 2px 2px / 4px 4px 4px 4px", "1pt / 2pt 3pt", "4pt 5pt / 3pt" // elliptical + "3% / 2%", "1px / 4px", "2em / 1em", "3em 2px / 2px 3em", "2pt 3% 4em / 4pt 1% 5em", "2px 2px 2px 2px / 4px 4px 4px 4px", "1pt / 2pt 3pt", "4pt 5pt / 3pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", + "2px 2px -moz-calc(2px + 1%) 2px", + "1px 2px 2px 2px / 2px 2px -moz-calc(2px + 1%) 2px", ], invalid_values: [ "2px -2px", "inherit 2px", "inherit / 2px", "2px inherit", "2px / inherit", "2px 2px 2px 2px 2px", "1px / 2px 2px 2px 2px 2px" ] }, @@ -617,7 +675,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px", "0%" ], other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -627,7 +694,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px", "0%" ], other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -637,7 +713,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px", "0%" ], other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] }, @@ -647,7 +732,16 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "0", "0px", "0%" ], other_values: [ "3%", "1px", "2em", // circular - "3% 2%", "1px 4px", "2em 2pt" // elliptical + "3% 2%", "1px 4px", "2em 2pt", // elliptical + "-moz-calc(2px)", + "-moz-calc(50%)", + "-moz-calc(3*25px)", + "-moz-calc(3*25px) 5px", + "5px -moz-calc(3*25px)", + "-moz-calc(20%) -moz-calc(3*25px)", + "-moz-calc(25px*3)", + "-moz-calc(3*25px + 50%)", + "-moz-min(30%, 30em,200px, min(500px ,40em))", ], invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ] },