Bug 513395: Implement revised CSS gradient notation (1/2): parser and data structure changes

This commit is contained in:
Zack Weinberg ext:(%2C%20Ms2ger%20%3Cms2ger%40gmail.com%3E) 2009-11-02 11:36:43 -08:00
Родитель 66d74905ab
Коммит 2ac3a6879f
19 изменённых файлов: 924 добавлений и 543 удалений

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

@ -1625,6 +1625,7 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
const nsRect& aFillArea,
PRBool aRepeat)
{
#if 0
gfxContext *ctx = aRenderingContext.ThebesContext();
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
@ -1676,6 +1677,7 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
ctx->Rectangle(areaToFill - fillOrigin, PR_TRUE);
ctx->Fill();
ctx->Restore();
#endif
}
void

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

@ -748,6 +748,16 @@
#define NS_STYLE_IME_MODE_DISABLED 3
#define NS_STYLE_IME_MODE_INACTIVE 4
// See nsStyleGradient
#define NS_STYLE_GRADIENT_SHAPE_LINEAR 0
#define NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL 1
#define NS_STYLE_GRADIENT_SHAPE_CIRCULAR 2
#define NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE 0
#define NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER 1
#define NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE 2
#define NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER 3
#ifdef MOZ_SVG
// See nsStyleSVG

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

@ -10,11 +10,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435293
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
/* Skewed boxes can get very big. The .pane wrapper prevents them
from obscuring the test results. */
.pane {
height: 300px;
width: 300px;
float: left;
overflow: auto;
border: 1px solid black;
}
.test {
background: green;
height: 100px;
width: 100px;
margin: 100px;
}
/* Radian units are not used in this test because our CSS
implementation stores all dimensional values in single-
precision floating point, which makes it impossible to
hit mathematically interesting angles with radians.
Degrees and grads do not suffer this problem. */
#test1 {
-moz-transform: skewx(30deg);
}
@ -24,14 +40,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435293
#test3 {
-moz-transform: skew(45deg, 45deg);
}
/* We will set test 4 and 5 from JS in order to use exact values.
For clarity, their style is as follows:
#test4 {
-moz-transform: skew(2(PI)rad, 45deg);
-moz-transform: skew(360deg, 45deg);
}
#test5 {
-moz-transform: skew(PI/4rad, 150grad);
}*/
-moz-transform: skew(45deg, 150grad);
}
#test6 {
-moz-transform: skew(80%, 78px);
}
@ -44,54 +58,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435293
#test9 {
-moz-transform: skew(30deg, 30deg, 30deg);
}
/* approach the singularity from the negative side */
#test10 {
display:none;
-moz-transform: skew(50grad, 89.99999999999999deg);
-moz-transform: skew(50grad, 90.001deg);
}
/* For test 11, we style it in JS to obtain exact values. For clarity, the
rule that will be created is below.
#test11 {
-moz-transform: skew(300grad, (PI/2)rad);
}*/
-moz-transform: skew(300grad, 90.001deg);
}
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435293">Mozilla Bug 435293</a>
<p id="display"></p>
<div id="content">
<div id="test1" class="test">
test
</div>
<p id="test2" class="test">
test
</p>
<div id="test3" class="test">
test
</div>
<div id="test4" class="test">
test
</div>
<div id="test5" class="test">
test
</div>
<div id="test6" class="test">
test
</div>
<div id="test7" class="test">
test
</div>
<div id="test8" class="test">
test
</div>
<div id="test9" class="test">
test
</div>
<div id="test10" class="test">
test
</div>
<div id="test11" class="test">
test
</div>
<div class="pane"><div id="test1" class="test">test</div></div>
<div class="pane"><p id="test2" class="test">test</p></div>
<div class="pane"><div id="test3" class="test">test</div></div>
<div class="pane"><div id="test4" class="test">test</div></div>
<div class="pane"><div id="test5" class="test">test</div></div>
<div class="pane"><div id="test6" class="test">test</div></div>
<div class="pane"><div id="test7" class="test">test</div></div>
<div class="pane"><div id="test8" class="test">test</div></div>
<div class="pane"><div id="test9" class="test">test</div></div>
<div class="pane"><div id="test10" class="test">test</div></div>
<div class="pane"><div id="test11" class="test">test</div></div>
</div>
<pre id="test">
@ -99,17 +90,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435293
runtests();
function runtests() {
// Set the style rules for test 4, 5, and 11 using Math.pi instead of
// approximations
var e = document.getElementById("test4");
e.setAttribute("style", "-moz-transform: skew(" + Math.PI * 2 + "rad, 45deg);");
e = document.getElementById("test5");
e.setAttribute("style", "-moz-transform: skew(" + Math.PI/4 + "rad, 150grad);");
e = document.getElementById("test11");
e.setAttribute("style", "-moz-transform: skew(300grad, " + Math.PI/2 + "rad");
// For test 1 we need to handle the contingency that different systems may
// round differently. We will parse out the values and compare them
// individually. The matrix should be: matrix(1, 0, 0.57735, 1, 0px, 0px)
@ -141,13 +121,23 @@ function runtests() {
is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 1, 1, 0px, 0px)",
"Test3: Skew proper matrix is applied");
// Argument reduction here may give us a value that is close to but not
// exactly zero.
style = window.getComputedStyle(document.getElementById("test4"), "");
is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 0, 1, 0px, 0px)",
"Test4: Skew mixing deg and rad");
tformStyle = style.getPropertyValue("-moz-transform");
tformValues = tformStyle.substring(tformStyle.indexOf('(') + 1,
tformStyle.indexOf(')')).split(',');
is((+tformValues[0]), 1, "Test4: skew angle wrap: param 0 is 1");
is((+tformValues[1]), 1, "Test4: skew angle wrap: param 1 is 1");
ok(verifyRounded(tformValues[2], 0),
"Test4: skew angle wrap: rounded param 2 is 0");
is((+tformValues[3]), 1, "Test4: skew angle wrap: param 3 is 1");
is(tformValues[4].trim(), "0px", "Test4: skew angle wrap: param 4 is 0px");
is(tformValues[5].trim(), "0px", "Test4: skew angle wrap: param 5 is 0px");
style = window.getComputedStyle(document.getElementById("test5"), "");
is(style.getPropertyValue("-moz-transform"), "matrix(1, -1, 1, 1, 0px, 0px)",
"Test5: Skew mixing rad and grad");
"Test5: Skew mixing deg and grad");
style = window.getComputedStyle(document.getElementById("test6"), "");
is(style.getPropertyValue("-moz-transform"), "none",

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

@ -441,42 +441,74 @@ nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty,
else if (eCSSUnit_Gradient == unit) {
nsCSSValueGradient* gradient = aValue.GetGradientValue();
if (gradient->mIsRadial)
aResult.AppendLiteral("-moz-radial-gradient(");
else
aResult.AppendLiteral("-moz-linear-gradient(");
if (gradient->mIsRepeating) {
if (gradient->mIsRadial)
aResult.AppendLiteral("-moz-repeating-radial-gradient(");
else
aResult.AppendLiteral("-moz-repeating-linear-gradient(");
} else {
if (gradient->mIsRadial)
aResult.AppendLiteral("-moz-radial-gradient(");
else
aResult.AppendLiteral("-moz-linear-gradient(");
}
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mStartX, aResult);
aResult.AppendLiteral(" ");
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mStartY, aResult);
aResult.AppendLiteral(", ");
if (gradient->mIsRadial) {
AppendCSSValueToString(aProperty, gradient->mStartRadius, aResult);
if (gradient->mBgPosX.GetUnit() != eCSSUnit_None ||
gradient->mBgPosY.GetUnit() != eCSSUnit_None ||
gradient->mAngle.GetUnit() != eCSSUnit_None) {
if (gradient->mBgPosX.GetUnit() != eCSSUnit_None) {
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mBgPosX, aResult);
aResult.AppendLiteral(" ");
}
if (gradient->mBgPosY.GetUnit() != eCSSUnit_None) {
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mBgPosY, aResult);
aResult.AppendLiteral(" ");
}
if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
AppendCSSValueToString(aProperty, gradient->mAngle, aResult);
}
aResult.AppendLiteral(", ");
}
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mEndX, aResult);
aResult.AppendLiteral(" ");
if (gradient->mIsRadial &&
(gradient->mRadialShape.GetUnit() != eCSSUnit_None ||
gradient->mRadialSize.GetUnit() != eCSSUnit_None)) {
if (gradient->mRadialShape.GetUnit() != eCSSUnit_None) {
NS_ASSERTION(gradient->mRadialShape.GetUnit() == eCSSUnit_Enumerated,
"bad unit for radial gradient shape");
PRInt32 intValue = gradient->mRadialShape.GetIntValue();
NS_ASSERTION(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
"radial gradient with linear shape?!");
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
nsCSSProps::kRadialGradientShapeKTable),
aResult);
aResult.AppendLiteral(" ");
}
AppendCSSValueToString(eCSSProperty_background_position,
gradient->mEndY, aResult);
if (gradient->mIsRadial) {
if (gradient->mRadialSize.GetUnit() != eCSSUnit_None) {
NS_ASSERTION(gradient->mRadialSize.GetUnit() == eCSSUnit_Enumerated,
"bad unit for radial gradient size");
PRInt32 intValue = gradient->mRadialSize.GetIntValue();
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
nsCSSProps::kRadialGradientSizeKTable),
aResult);
}
aResult.AppendLiteral(", ");
AppendCSSValueToString(aProperty, gradient->mEndRadius, aResult);
}
for (PRUint32 i = 0; i < gradient->mStops.Length(); i++) {
aResult.AppendLiteral(", color-stop(");
AppendCSSValueToString(aProperty, gradient->mStops[i].mLocation, aResult);
aResult.AppendLiteral(", ");
for (PRUint32 i = 0 ;;) {
AppendCSSValueToString(aProperty, gradient->mStops[i].mColor, aResult);
aResult.AppendLiteral(")");
if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) {
aResult.AppendLiteral(" ");
AppendCSSValueToString(aProperty, gradient->mStops[i].mLocation,
aResult);
}
if (++i == gradient->mStops.Length()) {
break;
}
aResult.AppendLiteral(", ");
}
aResult.AppendLiteral(")");

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

@ -230,6 +230,8 @@ CSS_KEY(ch, ch)
CSS_KEY(circle, circle)
CSS_KEY(cjk-ideographic, cjk_ideographic)
CSS_KEY(close-quote, close_quote)
CSS_KEY(closest-corner, closest_corner)
CSS_KEY(closest-side, closest_side)
CSS_KEY(cm, cm)
CSS_KEY(code, code)
CSS_KEY(col-resize, col_resize)
@ -265,6 +267,7 @@ CSS_KEY(ease-in-out, ease_in_out)
CSS_KEY(ease-out, ease_out)
CSS_KEY(element, element)
CSS_KEY(elements, elements)
CSS_KEY(ellipse, ellipse)
CSS_KEY(em, em)
CSS_KEY(embed, embed)
CSS_KEY(enabled, enabled)
@ -276,6 +279,8 @@ CSS_KEY(extra-expanded, extra_expanded)
CSS_KEY(ew-resize, ew_resize)
CSS_KEY(far-left, far_left)
CSS_KEY(far-right, far_right)
CSS_KEY(farthest-side, farthest_side)
CSS_KEY(farthest-corner, farthest_corner)
CSS_KEY(fast, fast)
CSS_KEY(faster, faster)
CSS_KEY(fill, fill)

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

@ -540,8 +540,9 @@ protected:
PRBool TranslateDimension(nsCSSValue& aValue, PRInt32 aVariantMask,
float aNumber, const nsString& aUnit);
PRBool ParseImageRect(nsCSSValue& aImage);
PRBool ParseGradientStop(nsCSSValueGradient* aGradient);
PRBool ParseGradient(nsCSSValue& aValue, PRBool aIsRadial);
PRBool ParseColorStop(nsCSSValueGradient* aGradient);
PRBool ParseGradient(nsCSSValue& aValue, PRBool aIsRadial,
PRBool aIsRepeating);
void SetParsingCompoundProperty(PRBool aBool) {
NS_ASSERTION(aBool == PR_TRUE || aBool == PR_FALSE, "bad PRBool value");
@ -4521,10 +4522,16 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
eCSSToken_Function == tk->mType) {
// a generated gradient
if (tk->mIdent.LowerCaseEqualsLiteral("-moz-linear-gradient"))
return ParseGradient(aValue, PR_FALSE);
return ParseGradient(aValue, PR_FALSE, PR_FALSE);
if (tk->mIdent.LowerCaseEqualsLiteral("-moz-radial-gradient"))
return ParseGradient(aValue, PR_TRUE);
return ParseGradient(aValue, PR_TRUE, PR_FALSE);
if (tk->mIdent.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient"))
return ParseGradient(aValue, PR_FALSE, PR_TRUE);
if (tk->mIdent.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient"))
return ParseGradient(aValue, PR_TRUE, PR_TRUE);
}
if ((aVariantMask & VARIANT_IMAGE_RECT) != 0 &&
eCSSToken_Function == tk->mType &&
@ -4822,167 +4829,165 @@ CSSParserImpl::ParseImageRect(nsCSSValue& aImage)
return PR_FALSE;
}
// <color-stop> : <color> [ <percentage> | <length> ]?
PRBool
CSSParserImpl::ParseGradientStop(nsCSSValueGradient* aGradient)
CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient)
{
if (!GetToken(PR_TRUE))
return PR_FALSE;
if (eCSSToken_Function != mToken.mType) {
UngetToken();
nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement();
if (!stop) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
return PR_FALSE;
}
if (mToken.mIdent.LowerCaseEqualsLiteral("from")) {
// Start of the gradient
if (!ExpectSymbol('(', PR_FALSE)) {
NS_ABORT_IF_FALSE(PR_FALSE, "function token without (");
}
nsCSSValue fromFloat(0.0f, eCSSUnit_Percent);
nsCSSValue fromColor;
if (!ParseVariant(fromColor, VARIANT_COLOR, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
if (!ExpectSymbol(')', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
aGradient->mStops.AppendElement(nsCSSValueGradientStop(fromFloat, fromColor));
return PR_TRUE;
if (!ParseVariant(stop->mColor, VARIANT_COLOR, nsnull)) {
return PR_FALSE;
}
if (mToken.mIdent.LowerCaseEqualsLiteral("to")) {
// End of the gradient
if (!ExpectSymbol('(', PR_FALSE)) {
NS_ABORT_IF_FALSE(PR_FALSE, "function token without (");
}
nsCSSValue toFloat(1.0f, eCSSUnit_Percent);
nsCSSValue toColor;
if (!ParseVariant(toColor, VARIANT_COLOR, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
if (!ExpectSymbol(')', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
aGradient->mStops.AppendElement(nsCSSValueGradientStop(toFloat, toColor));
return PR_TRUE;
// Stop positions do not have to fall between the starting-point and
// ending-point, so we don't use ParseNonNegativeVariant.
if (!ParseVariant(stop->mLocation, VARIANT_LP, nsnull)) {
stop->mLocation.SetNoneValue();
}
if (mToken.mIdent.LowerCaseEqualsLiteral("color-stop")) {
// Some kind of gradient stop, somewhere...
if (!ExpectSymbol('(', PR_FALSE)) {
NS_ABORT_IF_FALSE(PR_FALSE, "function token without (");
}
nsCSSValue stopFloat;
if (!ParseVariant(stopFloat, VARIANT_PERCENT | VARIANT_NUMBER, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
// Check for a sane position value, and clamp it if it isn't
if (stopFloat.GetUnit() == eCSSUnit_Percent) {
if (stopFloat.GetPercentValue() > 1.0)
stopFloat.SetPercentValue(1.0);
else if (stopFloat.GetPercentValue() < 0.0)
stopFloat.SetPercentValue(0.0);
} else {
if (stopFloat.GetFloatValue() > 1.0)
stopFloat.SetFloatValue(1.0, eCSSUnit_Number);
else if (stopFloat.GetFloatValue() < 0.0)
stopFloat.SetFloatValue(0.0, eCSSUnit_Number);
}
if (!ExpectSymbol(',', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
nsCSSValue stopColor;
if (!ParseVariant(stopColor, VARIANT_COLOR, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
if (!ExpectSymbol(')', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
aGradient->mStops.AppendElement(nsCSSValueGradientStop(stopFloat, stopColor));
return PR_TRUE;
}
// No idea what this is
return PR_FALSE;
return PR_TRUE;
}
// <gradient>
// : linear-gradient( <gradient-line>? <color-stops> ')'
// : radial-gradient( <gradient-line>? <gradient-shape-size>?
// <color-stops> ')'
//
// <gradient-line> : [<bg-position> || <angle>] ,
//
// <gradient-shape-size> : [<gradient-shape> || <gradient-size>] ,
// <gradient-shape> : circle | ellipse
// <gradient-size> : closest-side | closest-corner
// | farthest-side | farthest-corner
// | contain | cover
//
// <color-stops> : <color-stop> , <color-stop> [, <color-stop>]*
PRBool
CSSParserImpl::ParseGradient(nsCSSValue& aValue,
PRBool aIsRadial)
CSSParserImpl::ParseGradient(nsCSSValue& aValue, PRBool aIsRadial,
PRBool aIsRepeating)
{
if (!ExpectSymbol('(', PR_FALSE)) {
NS_ABORT_IF_FALSE(PR_FALSE, "function token without (");
}
nsCSSValuePair startPos;
if (!ParseBoxPositionValues(startPos, PR_FALSE))
return PR_FALSE;
nsRefPtr<nsCSSValueGradient> cssGradient
= new nsCSSValueGradient(aIsRadial, aIsRepeating);
if (!ExpectSymbol(',', PR_TRUE)) {
// <gradient-line>
// N.B. ParseBoxPositionValues is not guaranteed to put back
// everything it scanned if it fails, so we must only call it
// if there is no alternative to consuming a <box-position>.
// ParseVariant, as used here, will either succeed and consume
// a single token, or fail and consume none, so we can be more
// cavalier about calling it.
if (!GetToken(PR_TRUE)) {
return PR_FALSE;
}
nsCSSTokenType ty = mToken.mType;
nsString id = mToken.mIdent;
UngetToken();
PRBool haveGradientLine = PR_FALSE;
switch (ty) {
case eCSSToken_Percentage:
case eCSSToken_Number:
case eCSSToken_Dimension:
haveGradientLine = PR_TRUE;
break;
case eCSSToken_Function:
case eCSSToken_ID:
case eCSSToken_Ref:
// this is a color
break;
case eCSSToken_Ident: {
// This is only a gradient line if it's a box position keyword.
nsCSSKeyword kw = nsCSSKeywords::LookupKeyword(id);
PRInt32 junk;
if (kw != eCSSKeyword_UNKNOWN &&
nsCSSProps::FindKeyword(kw, nsCSSProps::kBackgroundPositionKTable,
junk)) {
haveGradientLine = PR_TRUE;
}
break;
}
default:
// error
SkipUntil(')');
return PR_FALSE;
}
nsCSSValue startRadius;
if (aIsRadial) {
if (!ParseNonNegativeVariant(startRadius, VARIANT_LENGTH, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
if (haveGradientLine) {
PRBool haveAngle =
ParseVariant(cssGradient->mAngle, VARIANT_ANGLE, nsnull);
if (!ExpectSymbol(',', PR_TRUE)) {
// if we got an angle, we might now have a comma, ending the gradient-line
if (!haveAngle || !ExpectSymbol(',', PR_TRUE)) {
// This intermediate is necessary because nsCSSValueGradient cannot
// contain a nsCSSValuePair (because the latter type is defined in
// nsCSSStruct.h rather than nsCSSValue.h).
nsCSSValuePair bgPos;
if (ParseBoxPositionValues(bgPos, PR_FALSE)) {
cssGradient->mBgPosX = bgPos.mXValue;
cssGradient->mBgPosY = bgPos.mYValue;
} else {
SkipUntil(')');
return PR_FALSE;
}
if (!ExpectSymbol(',', PR_TRUE) &&
// if we didn't already get an angle, we might have one now,
// otherwise it's an error
(haveAngle ||
!ParseVariant(cssGradient->mAngle, VARIANT_ANGLE, nsnull) ||
// now we better have a comma
!ExpectSymbol(',', PR_TRUE))) {
SkipUntil(')');
return PR_FALSE;
}
}
}
// radial gradients might have a <gradient-shape-size> here
if (aIsRadial) {
PRBool haveShape =
ParseVariant(cssGradient->mRadialShape, VARIANT_KEYWORD,
nsCSSProps::kRadialGradientShapeKTable);
PRBool haveSize =
ParseVariant(cssGradient->mRadialSize, VARIANT_KEYWORD,
nsCSSProps::kRadialGradientSizeKTable);
// could be in either order
if (!haveShape) {
haveShape =
ParseVariant(cssGradient->mRadialShape, VARIANT_KEYWORD,
nsCSSProps::kRadialGradientShapeKTable);
}
if ((haveShape || haveSize) && !ExpectSymbol(',', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
}
nsCSSValuePair endPos;
if (!ParseBoxPositionValues(endPos, PR_FALSE)) {
// At least two color stops are required
if (!ParseColorStop(cssGradient) ||
!ExpectSymbol(',', PR_TRUE) ||
!ParseColorStop(cssGradient)) {
SkipUntil(')');
return PR_FALSE;
}
nsCSSValue endRadius;
if (aIsRadial) {
if (!ExpectSymbol(',', PR_TRUE)) {
SkipUntil(')');
return PR_FALSE;
}
if (!ParseNonNegativeVariant(endRadius, VARIANT_LENGTH, nsnull)) {
SkipUntil(')');
return PR_FALSE;
}
}
nsRefPtr<nsCSSValueGradient> cssGradient =
new nsCSSValueGradient(aIsRadial, startPos.mXValue, startPos.mYValue,
startRadius, endPos.mXValue, endPos.mYValue,
endRadius);
// Do optional stop functions
// Additional color stops
while (ExpectSymbol(',', PR_TRUE)) {
if (!ParseGradientStop(cssGradient)) {
if (!ParseColorStop(cssGradient)) {
SkipUntil(')');
return PR_FALSE;
}
@ -6460,6 +6465,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem,
(mToken.mIdent.LowerCaseEqualsLiteral("url") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-linear-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-radial-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-image-rect"))) {
if (haveImage)
return PR_FALSE;

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

@ -1063,6 +1063,23 @@ const PRInt32 nsCSSProps::kPositionKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
const PRInt32 nsCSSProps::kRadialGradientShapeKTable[] = {
eCSSKeyword_circle, NS_STYLE_GRADIENT_SHAPE_CIRCULAR,
eCSSKeyword_ellipse, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL,
eCSSKeyword_UNKNOWN,-1
};
const PRInt32 nsCSSProps::kRadialGradientSizeKTable[] = {
eCSSKeyword_closest_side, NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
eCSSKeyword_closest_corner, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER,
eCSSKeyword_farthest_side, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE,
eCSSKeyword_farthest_corner, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
// synonyms
eCSSKeyword_contain, NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
eCSSKeyword_cover, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
eCSSKeyword_UNKNOWN,-1
};
const PRInt32 nsCSSProps::kSpeakKTable[] = {
eCSSKeyword_none, NS_STYLE_SPEAK_NONE,
eCSSKeyword_normal, NS_STYLE_SPEAK_NORMAL,

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

@ -280,6 +280,8 @@ public:
static const PRInt32 kPitchKTable[];
static const PRInt32 kPointerEventsKTable[];
static const PRInt32 kPositionKTable[];
static const PRInt32 kRadialGradientShapeKTable[];
static const PRInt32 kRadialGradientSizeKTable[];
static const PRInt32 kSpeakKTable[];
static const PRInt32 kSpeakHeaderKTable[];
static const PRInt32 kSpeakNumeralKTable[];

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

@ -45,6 +45,7 @@
#include "nsIDocument.h"
#include "nsContentUtils.h"
#include "nsIPrincipal.h"
#include "nsMathUtils.h"
// Paint forcing
#include "prenv.h"
@ -209,6 +210,21 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
return PR_FALSE;
}
double nsCSSValue::GetAngleValueInRadians() const
{
double angle = GetFloatValue();
switch (GetUnit()) {
case eCSSUnit_Radian: return angle;
case eCSSUnit_Degree: return angle * M_PI / 180.0;
case eCSSUnit_Grad: return angle * M_PI / 200.0;
default:
NS_NOTREACHED("unrecognized angular unit");
return 0.0;
}
}
imgIRequest* nsCSSValue::GetImageValue() const
{
NS_ASSERTION(mUnit == eCSSUnit_Image, "not an Image value");
@ -550,10 +566,9 @@ nsCSSValue::Image::~Image()
{
}
nsCSSValueGradientStop::nsCSSValueGradientStop(const nsCSSValue& aLocation,
const nsCSSValue& aColor)
: mLocation(aLocation),
mColor(aColor)
nsCSSValueGradientStop::nsCSSValueGradientStop()
: mLocation(eCSSUnit_None),
mColor(eCSSUnit_Null)
{
MOZ_COUNT_CTOR(nsCSSValueGradientStop);
}
@ -570,16 +585,15 @@ nsCSSValueGradientStop::~nsCSSValueGradientStop()
MOZ_COUNT_DTOR(nsCSSValueGradientStop);
}
nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial, const nsCSSValue& aStartX,
const nsCSSValue& aStartY, const nsCSSValue& aStartRadius, const nsCSSValue& aEndX,
const nsCSSValue& aEndY, const nsCSSValue& aEndRadius)
nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial,
PRBool aIsRepeating)
: mIsRadial(aIsRadial),
mStartX(aStartX),
mStartY(aStartY),
mEndX(aEndX),
mEndY(aEndY),
mStartRadius(aStartRadius),
mEndRadius(aEndRadius),
mIsRepeating(aIsRepeating),
mBgPosX(eCSSUnit_None),
mBgPosY(eCSSUnit_None),
mAngle(eCSSUnit_None),
mRadialShape(eCSSUnit_None),
mRadialSize(eCSSUnit_None),
mRefCnt(0)
{
}

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

@ -235,6 +235,16 @@ public:
return mValue.mFloat;
}
float GetAngleValue() const
{
NS_ASSERTION(eCSSUnit_Degree <= mUnit &&
eCSSUnit_Radian >=-mUnit, "not an angle value");
return mValue.mFloat;
}
// Converts any angle to radians.
double GetAngleValueInRadians() const;
nsAString& GetStringValue(nsAString& aBuffer) const
{
NS_ASSERTION(UnitHasStringValue(), "not a string value");
@ -454,7 +464,7 @@ protected:
struct nsCSSValueGradientStop {
public:
nsCSSValueGradientStop(const nsCSSValue& aLocation, const nsCSSValue& aColor) NS_HIDDEN;
nsCSSValueGradientStop() NS_HIDDEN;
// needed to keep bloat logs happy when we use the nsTArray in nsCSSValueGradient
nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther) NS_HIDDEN;
~nsCSSValueGradientStop() NS_HIDDEN;
@ -475,33 +485,32 @@ public:
};
struct nsCSSValueGradient {
nsCSSValueGradient(PRBool aIsRadial, const nsCSSValue& aStartX, const nsCSSValue& aStartY,
const nsCSSValue& aStartRadius, const nsCSSValue& aEndX, const nsCSSValue& aEndY,
const nsCSSValue& aEndRadius) NS_HIDDEN;
nsCSSValueGradient(PRBool aIsRadial,
PRBool aIsRepeating) NS_HIDDEN;
// true if gradient is radial, false if it is linear
PRPackedBool mIsRadial;
nsCSSValue mStartX;
nsCSSValue mStartY;
nsCSSValue mEndX;
nsCSSValue mEndY;
PRPackedBool mIsRepeating;
// line position and angle
nsCSSValue mBgPosX;
nsCSSValue mBgPosY;
nsCSSValue mAngle;
// Only meaningful if mIsRadial is true
nsCSSValue mStartRadius;
nsCSSValue mEndRadius;
nsCSSValue mRadialShape;
nsCSSValue mRadialSize;
nsTArray<nsCSSValueGradientStop> mStops;
PRBool operator==(const nsCSSValueGradient& aOther) const
{
if (mIsRadial != aOther.mIsRadial ||
mStartX != aOther.mStartX ||
mStartY != aOther.mStartY ||
mStartRadius != aOther.mStartRadius ||
mEndX != aOther.mEndX ||
mEndY != aOther.mEndY ||
mEndRadius != aOther.mEndRadius)
mIsRepeating != aOther.mIsRepeating ||
mBgPosX != aOther.mBgPosX ||
mBgPosY != aOther.mBgPosY ||
mAngle != aOther.mAngle ||
mRadialShape != aOther.mRadialShape ||
mRadialSize != aOther.mRadialSize)
return PR_FALSE;
if (mStops.Length() != aOther.mStops.Length())

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

@ -1358,76 +1358,92 @@ AppendCSSGradientLength(const nsStyleCoord& aValue,
aString.Append(tokenString);
}
static void
AppendCSSGradientRadius(const nscoord aValue,
nsROCSSPrimitiveValue* aPrimitive,
nsAString& aString)
{
nsAutoString tokenString;
aPrimitive->SetAppUnits(aValue);
aPrimitive->GetCssText(tokenString);
aString.Append(tokenString);
}
nsresult
nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
nsAString& aString)
{
if (aGradient->mIsRadial)
aString.AssignLiteral("-moz-radial-gradient(");
else
aString.AssignLiteral("-moz-linear-gradient(");
if (aGradient->mRepeating) {
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR)
aString.AssignLiteral("-moz-repeating-linear-gradient(");
else
aString.AssignLiteral("-moz-repeating-radial-gradient(");
} else {
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR)
aString.AssignLiteral("-moz-linear-gradient(");
else
aString.AssignLiteral("-moz-radial-gradient(");
}
PRBool needSep = PR_FALSE;
nsAutoString tokenString;
nsROCSSPrimitiveValue *tmpVal = GetROCSSPrimitiveValue();
if (!tmpVal)
return NS_ERROR_OUT_OF_MEMORY;
// starting X position
AppendCSSGradientLength(aGradient->mStartX, tmpVal, aString);
aString.AppendLiteral(" ");
// starting Y position
AppendCSSGradientLength(aGradient->mStartY, tmpVal, aString);
aString.AppendLiteral(", ");
// starting radius
if (aGradient->mIsRadial) {
AppendCSSGradientRadius(aGradient->mStartRadius, tmpVal, aString);
aString.AppendLiteral(", ");
if (aGradient->mBgPosX.mUnit != eStyleUnit_None) {
AppendCSSGradientLength(aGradient->mBgPosX, tmpVal, aString);
needSep = PR_TRUE;
}
if (aGradient->mBgPosY.mUnit != eStyleUnit_None) {
if (needSep) {
aString.AppendLiteral(" ");
}
AppendCSSGradientLength(aGradient->mBgPosY, tmpVal, aString);
needSep = PR_TRUE;
}
if (aGradient->mAngle.mUnit != eStyleUnit_None) {
if (needSep) {
aString.AppendLiteral(" ");
}
tmpVal->SetNumber(aGradient->mAngle.GetAngleValue());
tmpVal->GetCssText(tokenString);
aString.Append(tokenString);
switch (aGradient->mAngle.mUnit) {
case eStyleUnit_Degree: aString.AppendLiteral("deg"); break;
case eStyleUnit_Grad: aString.AppendLiteral("grad"); break;
case eStyleUnit_Radian: aString.AppendLiteral("rad"); break;
default: NS_NOTREACHED("unrecognized angle unit");
}
needSep = PR_TRUE;
}
// ending X position
AppendCSSGradientLength(aGradient->mEndX, tmpVal, aString);
aString.AppendLiteral(" ");
// ending Y position
AppendCSSGradientLength(aGradient->mEndY, tmpVal, aString);
// ending radius
if (aGradient->mIsRadial) {
aString.AppendLiteral(", ");
AppendCSSGradientRadius(aGradient->mStartRadius, tmpVal, aString);
if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR) {
if (needSep) {
aString.AppendLiteral(", ");
}
AppendASCIItoUTF16(nsCSSProps::
ValueToKeyword(aGradient->mShape,
nsCSSProps::kRadialGradientShapeKTable),
aString);
if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
aString.AppendLiteral(" ");
AppendASCIItoUTF16(nsCSSProps::
ValueToKeyword(aGradient->mSize,
nsCSSProps::kRadialGradientSizeKTable),
aString);
}
needSep = PR_TRUE;
}
// color stops
for (PRUint32 i = 0; i < aGradient->mStops.Length(); ++i) {
nsAutoString tokenString;
aString.AppendLiteral(", color-stop(");
tmpVal->SetPercent(aGradient->mStops[i].mPosition);
tmpVal->GetCssText(tokenString);
aString.Append(tokenString);
aString.AppendLiteral(", ");
if (needSep) {
aString.AppendLiteral(", ");
}
nsresult rv = SetToRGBAColor(tmpVal, aGradient->mStops[i].mColor);
if (NS_FAILED(rv)) {
delete tmpVal;
return NS_ERROR_OUT_OF_MEMORY;
}
tmpVal->GetCssText(tokenString);
aString.Append(tokenString);
aString.AppendLiteral(")");
if (aGradient->mStops[i].mLocation.mUnit != eStyleUnit_None) {
aString.AppendLiteral(" ");
AppendCSSGradientLength(aGradient->mStops[i].mLocation, tmpVal, aString);
}
needSep = PR_TRUE;
}
delete tmpVal;

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

@ -314,6 +314,7 @@ nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
#define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
#define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
#define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
#define SETCOORD_LPO (SETCOORD_LP | SETCOORD_NONE)
#define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
#define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
#define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
@ -517,9 +518,11 @@ static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresConte
}
// OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
PRBool result = SetCoord(aValue, aResult, nsStyleCoord(), SETCOORD_LP,
aContext, aPresContext, aCanStoreInRuleTree);
NS_ABORT_IF_FALSE(result, "Incorrect data structure created by parsing code");
if (!SetCoord(aValue, aResult, nsStyleCoord(), SETCOORD_LPO,
aContext, aPresContext, aCanStoreInRuleTree)) {
NS_NOTREACHED("unexpected unit for gradient anchor point");
aResult.SetNoneValue();
}
}
static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
@ -530,34 +533,55 @@ static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
"The given data is not a gradient");
nsCSSValueGradient* gradient = aValue.GetGradientValue();
aResult.mIsRadial = gradient->mIsRadial;
// start values
SetGradientCoord(gradient->mStartX, aPresContext, aContext,
aResult.mStartX, aCanStoreInRuleTree);
SetGradientCoord(gradient->mStartY, aPresContext, aContext,
aResult.mStartY, aCanStoreInRuleTree);
if (gradient->mIsRadial) {
NS_ABORT_IF_FALSE(gradient->mStartRadius.IsLengthUnit(),
"Incorrect data structure created by parsing code");
aResult.mStartRadius = CalcLength(gradient->mStartRadius, aContext,
aPresContext, aCanStoreInRuleTree);
if (gradient->mRadialShape.GetUnit() == eCSSUnit_Enumerated) {
aResult.mShape = gradient->mRadialShape.GetIntValue();
} else {
NS_ASSERTION(gradient->mRadialShape.GetUnit() == eCSSUnit_None,
"bad unit for radial shape");
aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
}
if (gradient->mRadialSize.GetUnit() == eCSSUnit_Enumerated) {
aResult.mSize = gradient->mRadialSize.GetIntValue();
} else {
NS_ASSERTION(gradient->mRadialSize.GetUnit() == eCSSUnit_None,
"bad unit for radial shape");
aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
}
} else {
NS_ASSERTION(gradient->mRadialShape.GetUnit() == eCSSUnit_None,
"bad unit for linear shape");
NS_ASSERTION(gradient->mRadialSize.GetUnit() == eCSSUnit_None,
"bad unit for linear size");
aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR;
aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
}
// end values
SetGradientCoord(gradient->mEndX, aPresContext, aContext,
aResult.mEndX, aCanStoreInRuleTree);
// bg-position
SetGradientCoord(gradient->mBgPosX, aPresContext, aContext,
aResult.mBgPosX, aCanStoreInRuleTree);
SetGradientCoord(gradient->mEndY, aPresContext, aContext,
aResult.mEndY, aCanStoreInRuleTree);
SetGradientCoord(gradient->mBgPosY, aPresContext, aContext,
aResult.mBgPosY, aCanStoreInRuleTree);
if (gradient->mIsRadial) {
NS_ABORT_IF_FALSE(gradient->mEndRadius.IsLengthUnit(),
"Incorrect data structure created by parsing code");
aResult.mEndRadius = CalcLength(gradient->mEndRadius, aContext,
aPresContext, aCanStoreInRuleTree);
aResult.mRepeating = gradient->mIsRepeating;
// angle
if (gradient->mAngle.IsAngularUnit()) {
nsStyleUnit unit;
switch (gradient->mAngle.GetUnit()) {
case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
case eCSSUnit_Grad: unit = eStyleUnit_Grad; break;
case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
default: NS_NOTREACHED("unrecognized angular unit");
unit = eStyleUnit_Degree;
}
aResult.mAngle.SetAngleValue(gradient->mAngle.GetAngleValue(), unit);
} else {
NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
"bad unit for gradient angle");
aResult.mAngle.SetNoneValue();
}
// stops
@ -565,10 +589,11 @@ static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
nsStyleGradientStop stop;
nsCSSValueGradientStop &valueStop = gradient->mStops[i];
if (valueStop.mLocation.GetUnit() == eCSSUnit_Percent)
stop.mPosition = valueStop.mLocation.GetPercentValue();
else
stop.mPosition = valueStop.mLocation.GetFloatValue();
if (!SetCoord(valueStop.mLocation, stop.mLocation,
nsStyleCoord(), SETCOORD_LPO,
aContext, aPresContext, aCanStoreInRuleTree)) {
NS_NOTREACHED("unexpected unit for gradient stop location");
}
// inherit is not a valid color for stops, so we pass in a dummy
// parent color

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

@ -41,6 +41,7 @@
#include "nsString.h"
#include "nsCRT.h"
#include "prlog.h"
#include "nsMathUtils.h"
nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit)
: mUnit(aUnit)
@ -72,16 +73,12 @@ nsStyleCoord::nsStyleCoord(PRInt32 aValue, nsStyleUnit aUnit)
nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit)
: mUnit(aUnit)
{
NS_ASSERTION((aUnit == eStyleUnit_Percent) ||
(aUnit == eStyleUnit_Factor), "not a float value");
if ((aUnit == eStyleUnit_Percent) ||
(aUnit == eStyleUnit_Factor)) {
if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) {
NS_NOTREACHED("not a float value");
Reset();
} else {
mValue.mFloat = aValue;
}
else {
mUnit = eStyleUnit_Null;
mValue.mInt = 0;
}
}
nsStyleCoord& nsStyleCoord::operator=(const nsStyleCoord& aCopy)
@ -147,6 +144,19 @@ void nsStyleCoord::SetFactorValue(float aValue)
mValue.mFloat = aValue;
}
void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
{
if (aUnit == eStyleUnit_Degree ||
aUnit == eStyleUnit_Grad ||
aUnit == eStyleUnit_Radian) {
mUnit = aUnit;
mValue.mFloat = aValue;
} else {
NS_NOTREACHED("not an angle value");
Reset();
}
}
void nsStyleCoord::SetNormalValue(void)
{
mUnit = eStyleUnit_Normal;
@ -165,6 +175,24 @@ void nsStyleCoord::SetNoneValue(void)
mValue.mInt = 0;
}
// accessors that are not inlined
double
nsStyleCoord::GetAngleValueInRadians() const
{
double angle = mValue.mFloat;
switch (GetUnit()) {
case eStyleUnit_Radian: return angle;
case eStyleUnit_Degree: return angle * M_PI / 180.0;
case eStyleUnit_Grad: return angle * M_PI / 200.0;
default:
NS_NOTREACHED("unrecognized angular unit");
return 0.0;
}
}
// used by nsStyleSides and nsStyleCorners
#define COMPARE_INDEXED_COORD(i) \
PR_BEGIN_MACRO \

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

@ -53,6 +53,9 @@ enum nsStyleUnit {
eStyleUnit_None = 3, // (no value)
eStyleUnit_Percent = 10, // (float) 1.0 == 100%
eStyleUnit_Factor = 11, // (float) a multiplier
eStyleUnit_Degree = 12, // (float) angle in degrees
eStyleUnit_Grad = 13, // (float) angle in radians
eStyleUnit_Radian = 14, // (float) angle in radians
eStyleUnit_Coord = 20, // (nscoord) value is twips
eStyleUnit_Integer = 30, // (int) value is simple integer
eStyleUnit_Enumerated = 32 // (int) value has enumerated meaning
@ -94,6 +97,8 @@ public:
PRInt32 GetIntValue(void) const;
float GetPercentValue(void) const;
float GetFactorValue(void) const;
float GetAngleValue(void) const;
double GetAngleValueInRadians(void) const;
void GetUnionValue(nsStyleUnion& aValue) const;
void Reset(void); // sets to null
@ -101,6 +106,7 @@ public:
void SetIntValue(PRInt32 aValue, nsStyleUnit aUnit);
void SetPercentValue(float aValue);
void SetFactorValue(float aValue);
void SetAngleValue(float aValue, nsStyleUnit aUnit);
void SetNormalValue(void);
void SetAutoValue(void);
void SetNoneValue(void);
@ -253,6 +259,16 @@ inline float nsStyleCoord::GetFactorValue(void) const
return 0.0f;
}
inline float nsStyleCoord::GetAngleValue(void) const
{
NS_ASSERTION(mUnit >= eStyleUnit_Degree &&
mUnit <= eStyleUnit_Radian, "not an angle value");
if (mUnit >= eStyleUnit_Degree && mUnit <= eStyleUnit_Radian) {
return mValue.mFloat;
}
return 0.0f;
}
inline void nsStyleCoord::GetUnionValue(nsStyleUnion& aValue) const
{
memcpy(&aValue, &mValue, sizeof(nsStyleUnion));

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

@ -1290,26 +1290,26 @@ nsChangeHint nsStyleColor::MaxDifference()
PRBool
nsStyleGradient::operator==(const nsStyleGradient& aOther) const
{
NS_ABORT_IF_FALSE(mIsRadial || (mStartRadius == 0 && mEndRadius == 0),
"incorrect unused radius values");
NS_ABORT_IF_FALSE(aOther.mIsRadial ||
(aOther.mStartRadius == 0 && aOther.mEndRadius == 0),
"incorrect unused radius values");
NS_ABORT_IF_FALSE(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
"incorrect combination of shape and size");
NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
"incorrect combination of shape and size");
if (mIsRadial != aOther.mIsRadial ||
mStartX != aOther.mStartX ||
mStartY != aOther.mStartY ||
mStartRadius != aOther.mStartRadius ||
mEndX != aOther.mEndX ||
mEndY != aOther.mEndY ||
mEndRadius != aOther.mEndRadius)
if (mShape != aOther.mShape ||
mSize != aOther.mSize ||
mRepeating != aOther.mRepeating ||
mBgPosX != aOther.mBgPosX ||
mBgPosY != aOther.mBgPosY ||
mAngle != aOther.mAngle)
return PR_FALSE;
if (mStops.Length() != aOther.mStops.Length())
return PR_FALSE;
for (PRUint32 i = 0; i < mStops.Length(); i++) {
if (mStops[i].mPosition != aOther.mStops[i].mPosition ||
if (mStops[i].mLocation != aOther.mStops[i].mLocation ||
mStops[i].mColor != aOther.mStops[i].mColor)
return PR_FALSE;
}
@ -1318,15 +1318,11 @@ nsStyleGradient::operator==(const nsStyleGradient& aOther) const
}
nsStyleGradient::nsStyleGradient(void)
: mIsRadial(PR_FALSE)
, mStartRadius(0)
, mEndRadius(0)
: mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
, mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
, mRepeating(PR_FALSE)
, mRefCnt(0)
{
mStartX.SetCoordValue(0);
mStartY.SetCoordValue(0);
mEndX.SetCoordValue(0);
mEndY.SetCoordValue(0);
}
// --------------------

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

@ -132,24 +132,21 @@ struct nsStyleFont {
};
struct nsStyleGradientStop {
nsStyleCoord mLocation; // percent, coord, none
nscolor mColor;
float mPosition; // 0.0 - 1.0
};
class nsStyleGradient {
public:
nsStyleGradient();
PRUint8 mShape; // NS_STYLE_GRADIENT_SHAPE_*
PRUint8 mSize; // NS_STYLE_GRADIENT_SIZE_*;
// not used (must be FARTHEST_CORNER) for linear shape
PRPackedBool mRepeating;
PRPackedBool mIsRadial;
nsStyleCoord mStartX; // percent or coord
nsStyleCoord mStartY; // percent or coord
nsStyleCoord mEndX; // percent or coord
nsStyleCoord mEndY; // percent or coord
nscoord mStartRadius;
nscoord mEndRadius;
nsStyleCoord mBgPosX; // percent, coord, none
nsStyleCoord mBgPosY; // percent, coord, none
nsStyleCoord mAngle; // none, angle
// stops are in the order specified in the stylesheet
nsTArray<nsStyleGradientStop> mStops;

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

@ -45,27 +45,29 @@
#include "nsPresContext.h"
#include "nsRuleNode.h"
#include "nsCSSKeywords.h"
#include <math.h>
#include "nsMathUtils.h"
/* Arguably, this loses precision, but it doesn't hurt! */
const float kPi = 3.1415926535897932384626433832795f;
const float kTwoPi = 6.283185307179586476925286766559f;
const float kEpsilon = 0.0001f;
/* Computes tan(theta). For values of theta such that
* tan(theta) is undefined or arbitrarily large, SafeTangent
* returns a managably large or small value of the correct sign.
/* Note on floating point precision: The transform matrix is an array
* of single precision 'float's, and so are most of the input values
* we get from the style system, but intermediate calculations
* involving angles need to be done in 'double'.
*/
static float SafeTangent(float aTheta)
{
/* We'll do this by computing sin and cos theta. If cos(theta) is
* is too close to zero, we'll set it to some arbitrary epsilon value
* that avoid float overflow or undefined result.
*/
float sinTheta = sin(aTheta);
float cosTheta = cos(aTheta);
/* Bound cos(theta) to be in the range [-1, -epsilon) U (epsilon, 1] */
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
* undefined or very large, SafeTangent returns a manageably large value
* of the correct sign.
*/
static double SafeTangent(double aTheta)
{
const double kEpsilon = 0.0001;
/* tan(theta) = sin(theta)/cos(theta); problems arise when
* cos(theta) is too close to zero. Limit cos(theta) to the
* range [-1, -epsilon] U [epsilon, 1].
*/
double sinTheta = sin(aTheta);
double cosTheta = cos(aTheta);
if (cosTheta >= 0 && cosTheta < kEpsilon)
cosTheta = kEpsilon;
else if (cosTheta < 0 && cosTheta >= -kEpsilon)
@ -74,44 +76,6 @@ static float SafeTangent(float aTheta)
return sinTheta / cosTheta;
}
/* Helper function to constrain an angle to a value in the range [-pi, pi),
* which reduces accumulated floating point errors from trigonometric functions
* by keeping the error terms small.
*/
static inline float ConstrainFloatValue(float aValue)
{
/* Get in range [0, 2pi) */
aValue = fmod(aValue, kTwoPi);
return aValue >= kPi ? aValue - kTwoPi : aValue;
}
/* Converts an nsCSSValue containing an angle into an equivalent measure
* of radians. The value is guaranteed to be in the range (-pi, pi) to
* minimize error.
*/
static float CSSToRadians(const nsCSSValue &aValue)
{
NS_PRECONDITION(aValue.IsAngularUnit(),
"Expected an angle, but didn't find one!");
switch (aValue.GetUnit()) {
case eCSSUnit_Degree:
/* 360deg = 2pi rad, so deg = pi / 180 rad */
return
ConstrainFloatValue(aValue.GetFloatValue() * kPi / 180.0f);
case eCSSUnit_Grad:
/* 400grad = 2pi rad, so grad = pi / 200 rad */
return
ConstrainFloatValue(aValue.GetFloatValue() * kPi / 200.0f);
case eCSSUnit_Radian:
/* Yay identity transforms! */
return ConstrainFloatValue(aValue.GetFloatValue());
default:
NS_NOTREACHED("Unexpected angular unit!");
return 0.0f;
}
}
/* Constructor sets the data to the identity matrix. */
nsStyleTransformMatrix::nsStyleTransformMatrix()
{
@ -410,13 +374,13 @@ static void ProcessScale(float aMain[4], const nsCSSValue::Array* aData)
/* Helper function that, given a set of angles, constructs the appropriate
* skew matrix.
*/
static void ProcessSkewHelper(float aXAngle, float aYAngle, float aMain[4])
static void ProcessSkewHelper(double aXAngle, double aYAngle, float aMain[4])
{
/* We want our matrix to look like this:
* | 1 tan(ThetaX) 0|
* | tan(ThetaY) 1 0|
* | 0 0 1|
* However, to avoid infinte values, we'll use the SafeTangent function
* However, to avoid infinite values, we'll use the SafeTangent function
* instead of the C standard tan function.
*/
aMain[2] = SafeTangent(aXAngle);
@ -427,14 +391,14 @@ static void ProcessSkewHelper(float aXAngle, float aYAngle, float aMain[4])
static void ProcessSkewX(float aMain[4], const nsCSSValue::Array* aData)
{
NS_ASSERTION(aData->Count() == 2, "Bad array!");
ProcessSkewHelper(CSSToRadians(aData->Item(1)), 0.0f, aMain);
ProcessSkewHelper(aData->Item(1).GetAngleValueInRadians(), 0.0, aMain);
}
/* Function that converts a skewy transform into a matrix. */
static void ProcessSkewY(float aMain[4], const nsCSSValue::Array* aData)
{
NS_ASSERTION(aData->Count() == 2, "Bad array!");
ProcessSkewHelper(0.0f, CSSToRadians(aData->Item(1)), aMain);
ProcessSkewHelper(0.0, aData->Item(1).GetAngleValueInRadians(), aMain);
}
/* Function that converts a skew transform into a matrix. */
@ -442,8 +406,9 @@ static void ProcessSkew(float aMain[4], const nsCSSValue::Array* aData)
{
NS_ASSERTION(aData->Count() == 2 || aData->Count() == 3, "Bad array!");
float xSkew = CSSToRadians(aData->Item(1));
float ySkew = (aData->Count() == 2 ? 0.0f : CSSToRadians(aData->Item(2)));
double xSkew = aData->Item(1).GetAngleValueInRadians();
double ySkew = (aData->Count() == 2
? 0.0 : aData->Item(2).GetAngleValueInRadians());
ProcessSkewHelper(xSkew, ySkew, aMain);
}
@ -459,7 +424,7 @@ static void ProcessRotate(float aMain[4], const nsCSSValue::Array* aData)
* | 0 0 1|
* (see http://www.w3.org/TR/SVG/coords.html#RotationDefined)
*/
float theta = CSSToRadians(aData->Item(1));
double theta = aData->Item(1).GetAngleValueInRadians();
float cosTheta = cos(theta);
float sinTheta = sin(theta);

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

@ -20,7 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -47,20 +47,20 @@ const CSS_TYPE_TRUE_SHORTHAND = 1;
const CSS_TYPE_SHORTHAND_AND_LONGHAND = 2;
// Each property has the following fields:
// domProp: The name of the relevant member of nsIDOM[NS]CSS2Properties
// inherited: Whether the property is inherited by default (stated as
// yes or no in the property header in all CSS specs)
// type: see above
// get_computed: if present, the property's computed value shows up on
// another property, and this is a function used to get it
// initial_values: Values whose computed value should be the same as the
// computed value for the property's initial value.
// other_values: Values whose computed value should be different from the
// computed value for the property's initial value.
// XXX Should have a third field for values whose computed value may or
// may not be the same as for the property's initial value.
// invalid_values: Things that are not values for the property and
// should be rejected.
// domProp: The name of the relevant member of nsIDOM[NS]CSS2Properties
// inherited: Whether the property is inherited by default (stated as
// yes or no in the property header in all CSS specs)
// type: see above
// get_computed: if present, the property's computed value shows up on
// another property, and this is a function used to get it
// initial_values: Values whose computed value should be the same as the
// computed value for the property's initial value.
// other_values: Values whose computed value should be different from the
// computed value for the property's initial value.
// XXX Should have a third field for values whose computed value may or
// may not be the same as for the property's initial value.
// invalid_values: Things that are not values for the property and
// should be rejected.
var gCSSProperties = {
"-moz-appearance": {
@ -168,16 +168,16 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "url('border.png') 27 27 27 27",
"url('border.png') 27",
"url('border.png') 27 27 27 27 repeat",
"url('border.png') 27 27 27 27 / 1em",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em repeat",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em stretch round" ],
"url('border.png') 27",
"url('border.png') 27 27 27 27 repeat",
"url('border.png') 27 27 27 27 / 1em",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em repeat",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em stretch round" ],
invalid_values: [ "url('border.png')",
"url('border.png') 27 27 27 27 27",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em 1em",
"url('border.png') / repeat",
"url('border.png') 27 27 27 27 /" ]
"url('border.png') 27 27 27 27 27",
"url('border.png') 27 27 27 27 / 1em 1em 1em 1em 1em",
"url('border.png') / repeat",
"url('border.png') 27 27 27 27 /" ]
},
"-moz-border-left-colors": {
domProp: "MozBorderLeftColors",
@ -194,8 +194,8 @@ 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
],
invalid_values: [ "2px -2px", "inherit 2px", "inherit / 2px", "2px inherit", "2px / inherit", "2px 2px 2px 2px 2px", "1px / 2px 2px 2px 2px 2px" ]
},
"-moz-border-radius-bottomleft": {
@ -204,8 +204,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-border-radius-bottomright": {
@ -214,8 +214,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-border-radius-topleft": {
@ -224,8 +224,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-border-radius-topright": {
@ -234,8 +234,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-border-right-colors": {
@ -471,8 +471,8 @@ 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
],
invalid_values: [ "2px -2px", "inherit 2px", "inherit / 2px", "2px inherit", "2px / inherit", "2px 2px 2px 2px 2px", "1px / 2px 2px 2px 2px 2px" ]
},
"-moz-outline-radius-bottomleft": {
@ -481,8 +481,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-outline-radius-bottomright": {
@ -491,8 +491,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-outline-radius-topleft": {
@ -501,8 +501,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-outline-radius-topright": {
@ -511,8 +511,8 @@ 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
],
invalid_values: [ "-1px", "4px -2px", "inherit 2px", "2px inherit" ]
},
"-moz-padding-end": {
@ -632,44 +632,68 @@ var gCSSProperties = {
subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "-moz-background-clip", "-moz-background-origin", "-moz-background-size" ],
initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "transparent none repeat scroll top left", "left top repeat none scroll transparent" ],
other_values: [
/* without multiple backgrounds */
"green", "none green repeat scroll left top", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') transparent left top scroll", "repeat-x", "repeat-y", "no-repeat", "none repeat-y transparent scroll 0% 0%", "fixed", "0% top transparent fixed repeat none", "top", "left", "50% 50%", "center", "bottom right scroll none transparent repeat", "50% transparent", "transparent 50%", "50%", "-moz-radial-gradient(10% bottom, 30px, 20px 20px, 10px, from(#ffffff), to(black)) scroll no-repeat", "-moz-linear-gradient(10px 10px, 20px 20px, from(red), to(blue)) repeat",
/* multiple backgrounds */
"url(404.png), url(404.png)",
"url(404.png), url(404.png) transparent",
"url(404.png), url(404.png) red",
"repeat-x, fixed, none",
"0% top url(404.png), url(404.png) 0% top",
"fixed repeat-y top left url(404.png), repeat-x green",
"url(404.png), -moz-linear-gradient(20px 20px, 30px 30px, from(blue), to(green)) black",
/* test cases with clip+origin in the shorthand */
// This is commented out for now until we change
// -moz-background-clip to background-clip, -moz-background-origin
// to background-origin, change their value names to *-box, and add
// support for content-box on background-clip.
/*
"url(404.png) green padding-box",
"url(404.png) border-box transparent",
"content-box url(404.png) blue",
*/
/* without multiple backgrounds */
"green",
"none green repeat scroll left top",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
"repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') transparent left top scroll",
"repeat-x",
"repeat-y",
"no-repeat",
"none repeat-y transparent scroll 0% 0%",
"fixed",
"0% top transparent fixed repeat none",
"top",
"left",
"50% 50%",
"center",
"bottom right scroll none transparent repeat",
"50% transparent",
"transparent 50%",
"50%",
"-moz-radial-gradient(10% bottom, #ffffff, black) scroll no-repeat",
"-moz-linear-gradient(10px 10px -45deg, red, blue) repeat",
"-moz-repeating-radial-gradient(10% bottom, #ffffff, black) scroll no-repeat",
"-moz-repeating-linear-gradient(10px 10px -45deg, red, blue) repeat",
/* multiple backgrounds */
"url(404.png), url(404.png)",
"url(404.png), url(404.png) transparent",
"url(404.png), url(404.png) red",
"repeat-x, fixed, none",
"0% top url(404.png), url(404.png) 0% top",
"fixed repeat-y top left url(404.png), repeat-x green",
"url(404.png), -moz-linear-gradient(20px 20px -45deg, blue, green) black",
/* test cases with clip+origin in the shorthand */
// This is commented out for now until we change
// -moz-background-clip to background-clip, -moz-background-origin
// to background-origin, change their value names to *-box, and add
// support for content-box on background-clip.
/*
"url(404.png) green padding-box",
"url(404.png) border-box transparent",
"content-box url(404.png) blue",
*/
],
invalid_values: [
/* mixes with keywords have to be in correct order */
"50% left", "top 50%",
/* bug 258080: don't accept background-position separated */
"left url(404.png) top", "top url(404.png) left",
/* not allowed to have color in non-bottom layer */
"url(404.png) transparent, url(404.png)",
"url(404.png) red, url(404.png)",
"url(404.png) transparent, url(404.png) transparent",
"url(404.png) transparent red, url(404.png) transparent red",
"url(404.png) red, url(404.png) red",
"url(404.png) rgba(0, 0, 0, 0), url(404.png)",
"url(404.png) rgb(255, 0, 0), url(404.png)",
"url(404.png) rgba(0, 0, 0, 0), url(404.png) rgba(0, 0, 0, 0)",
"url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0), url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0)",
"url(404.png) rgb(255, 0, 0), url(404.png) rgb(255, 0, 0)",
]
invalid_values: [
/* mixes with keywords have to be in correct order */
"50% left", "top 50%",
/* bug 258080: don't accept background-position separated */
"left url(404.png) top", "top url(404.png) left",
/* not allowed to have color in non-bottom layer */
"url(404.png) transparent, url(404.png)",
"url(404.png) red, url(404.png)",
"url(404.png) transparent, url(404.png) transparent",
"url(404.png) transparent red, url(404.png) transparent red",
"url(404.png) red, url(404.png) red",
"url(404.png) rgba(0, 0, 0, 0), url(404.png)",
"url(404.png) rgb(255, 0, 0), url(404.png)",
"url(404.png) rgba(0, 0, 0, 0), url(404.png) rgba(0, 0, 0, 0)",
"url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0), url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0)",
"url(404.png) rgb(255, 0, 0), url(404.png) rgb(255, 0, 0)",
/* bug 513395: old syntax for gradients */
"-moz-radial-gradient(10% bottom, 30px, 20px 20px, 10px, from(#ffffff), to(black)) scroll no-repeat",
"-moz-linear-gradient(10px 10px, 20px 20px, from(red), to(blue)) repeat",
]
},
"background-attachment": {
domProp: "backgroundAttachment",
@ -692,35 +716,220 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")',
"none, none",
"none, none, none, none, none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"none, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
other_values: [
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")',
"none, none",
"none, none, none, none, none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"none, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
/* gradient torture test */
"-moz-linear-gradient(red, blue)",
"-moz-linear-gradient(red, yellow, blue)",
"-moz-linear-gradient(red 1px, yellow 20%, blue 24em, green)",
"-moz-linear-gradient(red, yellow, green, blue 50%)",
"-moz-linear-gradient(red -50%, yellow -25%, green, blue)",
"-moz-linear-gradient(red -99px, yellow, green, blue 120%)",
"-moz-linear-gradient(#ffff00, #ef3, rgba(10, 20, 30, 0.4))",
"-moz-linear-gradient(rgba(10, 20, 30, 0.4), #ffff00, #ef3)",
"-moz-radial-gradient(45px 60px, 10px, 52px 50px, 30px, from(red), color-stop(90%, #019f62), to(rgba(1, 159, 98, 0)))",
"-moz-linear-gradient(20% center, left bottom, color-stop(0, #ffff00), to(green))",
"-moz-radial-gradient(50% 50%, 60px, 10% 20%, 20px, to(red), from(pink), color-stop(0.94, goldenrod))",
"-moz-linear-gradient(20px 10px, 100px top, from(rgb(10, 100, 0)), color-stop(1, rgba(10, 20, 30, 0.4)))",
"-moz-radial-gradient(center top, 10px, right bottom, 20px, color-stop(0.7, green), color-stop(20%, #ccddee), from(rgb(1, 2, 3)), color-stop(0.95, #aa0012))",
"-moz-linear-gradient(10px 20%, -50px -10%, from(green))",
"-moz-linear-gradient(10px 10px, 20px 20px)",
"-moz-linear-gradient(10px 10px, 20px 20px, color-stop(314%, blue))",
"-moz-linear-gradient(10px 10px, 20px 20px, color-stop(-0.2, green))",
"-moz-linear-gradient( 10px 10px , 40px 20px , from(blue) )"
"-moz-linear-gradient(top left, red, blue)",
"-moz-linear-gradient(0 0, red, blue)",
"-moz-linear-gradient(20% bottom, red, blue)",
"-moz-linear-gradient(center 20%, red, blue)",
"-moz-linear-gradient(left 35px, red, blue)",
"-moz-linear-gradient(10% 10em, red, blue)",
"-moz-linear-gradient(44px top, red, blue)",
"-moz-linear-gradient(top left 45deg, red, blue)",
"-moz-linear-gradient(20% bottom -300deg, red, blue)",
"-moz-linear-gradient(center 20% 1.95929rad, red, blue)",
"-moz-linear-gradient(left 35px 30grad, red, blue)",
"-moz-linear-gradient(10% 10em 99999deg, red, blue)",
"-moz-linear-gradient(44px top -33deg, red, blue)",
"-moz-linear-gradient(-33deg, red, blue)",
"-moz-linear-gradient(30grad left 35px, red, blue)",
"-moz-linear-gradient(10deg 20px, red, blue)",
"-moz-linear-gradient(.414rad bottom, red, blue)",
"-moz-radial-gradient(red, blue)",
"-moz-radial-gradient(red, yellow, blue)",
"-moz-radial-gradient(red 1px, yellow 20%, blue 24em, green)",
"-moz-radial-gradient(red, yellow, green, blue 50%)",
"-moz-radial-gradient(red -50%, yellow -25%, green, blue)",
"-moz-radial-gradient(red -99px, yellow, green, blue 120%)",
"-moz-radial-gradient(#ffff00, #ef3, rgba(10, 20, 30, 0.4))",
"-moz-radial-gradient(top left, red, blue)",
"-moz-radial-gradient(20% bottom, red, blue)",
"-moz-radial-gradient(center 20%, red, blue)",
"-moz-radial-gradient(left 35px, red, blue)",
"-moz-radial-gradient(10% 10em, red, blue)",
"-moz-radial-gradient(44px top, red, blue)",
"-moz-radial-gradient(top left 45deg, red, blue)",
"-moz-radial-gradient(0 0, red, blue)",
"-moz-radial-gradient(20% bottom -300deg, red, blue)",
"-moz-radial-gradient(center 20% 1.95929rad, red, blue)",
"-moz-radial-gradient(left 35px 30grad, red, blue)",
"-moz-radial-gradient(10% 10em 99999deg, red, blue)",
"-moz-radial-gradient(44px top -33deg, red, blue)",
"-moz-radial-gradient(rgba(10, 20, 30, 0.4), #ffff00, #ef3)",
"-moz-radial-gradient(-33deg, red, blue)",
"-moz-radial-gradient(30grad left 35px, red, blue)",
"-moz-radial-gradient(10deg 20px, red, blue)",
"-moz-radial-gradient(.414rad bottom, red, blue)",
"-moz-radial-gradient(cover, red, blue)",
"-moz-radial-gradient(circle, red, blue)",
"-moz-radial-gradient(ellipse closest-corner, red, blue)",
"-moz-radial-gradient(farthest-side circle, red, blue)",
"-moz-radial-gradient(top left, cover, red, blue)",
"-moz-radial-gradient(15% 20%, circle, red, blue)",
"-moz-radial-gradient(45px, ellipse closest-corner, red, blue)",
"-moz-radial-gradient(45px, farthest-side circle, red, blue)",
"-moz-radial-gradient(99deg, cover, red, blue)",
"-moz-radial-gradient(-1.2345rad, circle, red, blue)",
"-moz-radial-gradient(399grad, ellipse closest-corner, red, blue)",
"-moz-radial-gradient(399grad, farthest-side circle, red, blue)",
"-moz-radial-gradient(top left 99deg, cover, red, blue)",
"-moz-radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
"-moz-radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
"-moz-radial-gradient(45px 399grad, farthest-side circle, red, blue)",
"-moz-repeating-linear-gradient(red, blue)",
"-moz-repeating-linear-gradient(red, yellow, blue)",
"-moz-repeating-linear-gradient(red 1px, yellow 20%, blue 24em, green)",
"-moz-repeating-linear-gradient(red, yellow, green, blue 50%)",
"-moz-repeating-linear-gradient(red -50%, yellow -25%, green, blue)",
"-moz-repeating-linear-gradient(red -99px, yellow, green, blue 120%)",
"-moz-repeating-linear-gradient(#ffff00, #ef3, rgba(10, 20, 30, 0.4))",
"-moz-repeating-linear-gradient(rgba(10, 20, 30, 0.4), #ffff00, #ef3)",
"-moz-repeating-linear-gradient(top left, red, blue)",
"-moz-repeating-linear-gradient(0 0, red, blue)",
"-moz-repeating-linear-gradient(20% bottom, red, blue)",
"-moz-repeating-linear-gradient(center 20%, red, blue)",
"-moz-repeating-linear-gradient(left 35px, red, blue)",
"-moz-repeating-linear-gradient(10% 10em, red, blue)",
"-moz-repeating-linear-gradient(44px top, red, blue)",
"-moz-repeating-linear-gradient(top left 45deg, red, blue)",
"-moz-repeating-linear-gradient(20% bottom -300deg, red, blue)",
"-moz-repeating-linear-gradient(center 20% 1.95929rad, red, blue)",
"-moz-repeating-linear-gradient(left 35px 30grad, red, blue)",
"-moz-repeating-linear-gradient(10% 10em 99999deg, red, blue)",
"-moz-repeating-linear-gradient(44px top -33deg, red, blue)",
"-moz-repeating-linear-gradient(-33deg, red, blue)",
"-moz-repeating-linear-gradient(30grad left 35px, red, blue)",
"-moz-repeating-linear-gradient(10deg 20px, red, blue)",
"-moz-repeating-linear-gradient(.414rad bottom, red, blue)",
"-moz-repeating-radial-gradient(red, blue)",
"-moz-repeating-radial-gradient(red, yellow, blue)",
"-moz-repeating-radial-gradient(red 1px, yellow 20%, blue 24em, green)",
"-moz-repeating-radial-gradient(red, yellow, green, blue 50%)",
"-moz-repeating-radial-gradient(red -50%, yellow -25%, green, blue)",
"-moz-repeating-radial-gradient(red -99px, yellow, green, blue 120%)",
"-moz-repeating-radial-gradient(#ffff00, #ef3, rgba(10, 20, 30, 0.4))",
"-moz-repeating-radial-gradient(rgba(10, 20, 30, 0.4), #ffff00, #ef3)",
"-moz-repeating-radial-gradient(top left, red, blue)",
"-moz-repeating-radial-gradient(0 0, red, blue)",
"-moz-repeating-radial-gradient(20% bottom, red, blue)",
"-moz-repeating-radial-gradient(center 20%, red, blue)",
"-moz-repeating-radial-gradient(left 35px, red, blue)",
"-moz-repeating-radial-gradient(10% 10em, red, blue)",
"-moz-repeating-radial-gradient(44px top, red, blue)",
"-moz-repeating-radial-gradient(top left 45deg, red, blue)",
"-moz-repeating-radial-gradient(20% bottom -300deg, red, blue)",
"-moz-repeating-radial-gradient(center 20% 1.95929rad, red, blue)",
"-moz-repeating-radial-gradient(left 35px 30grad, red, blue)",
"-moz-repeating-radial-gradient(10% 10em 99999deg, red, blue)",
"-moz-repeating-radial-gradient(44px top -33deg, red, blue)",
"-moz-repeating-radial-gradient(-33deg, red, blue)",
"-moz-repeating-radial-gradient(30grad left 35px, red, blue)",
"-moz-repeating-radial-gradient(10deg 20px, red, blue)",
"-moz-repeating-radial-gradient(.414rad bottom, red, blue)",
"-moz-repeating-radial-gradient(cover, red, blue)",
"-moz-repeating-radial-gradient(circle, red, blue)",
"-moz-repeating-radial-gradient(ellipse closest-corner, red, blue)",
"-moz-repeating-radial-gradient(farthest-side circle, red, blue)",
"-moz-repeating-radial-gradient(top left, cover, red, blue)",
"-moz-repeating-radial-gradient(15% 20%, circle, red, blue)",
"-moz-repeating-radial-gradient(45px, ellipse closest-corner, red, blue)",
"-moz-repeating-radial-gradient(45px, farthest-side circle, red, blue)",
"-moz-repeating-radial-gradient(99deg, cover, red, blue)",
"-moz-repeating-radial-gradient(-1.2345rad, circle, red, blue)",
"-moz-repeating-radial-gradient(399grad, ellipse closest-corner, red, blue)",
"-moz-repeating-radial-gradient(399grad, farthest-side circle, red, blue)",
"-moz-repeating-radial-gradient(top left 99deg, cover, red, blue)",
"-moz-repeating-radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
"-moz-repeating-radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)"
],
invalid_values: [ "-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))",
"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
"-moz-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
"-moz-linear-gradient(10px, 20px, 30px, 40px, color-stop(0.5, #00ccff))",
"-moz-linear-gradient(20px 20px, from(blue), to(red))",
"-moz-linear-gradient(40px 40px, 10px 10px, from(blue) to(red) color-stop(10%, fuchsia))",
"-moz-linear-gradient(20px 20px 30px, 10px 10px, from(red), to(#ff0000))",
"-moz-radial-gradient(left top, center, 20px 20px, 10px, from(blue), to(red))",
"-moz-linear-gradient(left left, top top, from(blue))",
"-moz-linear-gradient(inherit, 10px 10px, from(blue))",
"-moz-linear-gradient()" ]
invalid_values: [
/* Old syntax */
"-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))",
"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
"-moz-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
"-moz-linear-gradient(10px, 20px, 30px, 40px, color-stop(0.5, #00ccff))",
"-moz-linear-gradient(20px 20px, from(blue), to(red))",
"-moz-linear-gradient(40px 40px, 10px 10px, from(blue) to(red) color-stop(10%, fuchsia))",
"-moz-linear-gradient(20px 20px 30px, 10px 10px, from(red), to(#ff0000))",
"-moz-radial-gradient(left top, center, 20px 20px, 10px, from(blue), to(red))",
"-moz-linear-gradient(left left, top top, from(blue))",
"-moz-linear-gradient(inherit, 10px 10px, from(blue))",
/* New syntax */
"-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, blue 0, red 100%)",
"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
"-moz-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
"-moz-linear-gradient(10px, 20px, 30px, 40px, #00ccff 50%)",
"-moz-linear-gradient(40px 40px, 10px 10px, blue 0 fuchsia 10% red 100%)",
"-moz-linear-gradient(20px 20px 30px, 10px 10px, red 0, #ff0000 100%)",
"-moz-radial-gradient(left top, center, 20px 20px, 10px, from(blue), to(red))",
"-moz-linear-gradient(left left, top top, blue 0)",
"-moz-linear-gradient(inherit, 10px 10px, blue 0)",
"-moz-linear-gradient(left left blue red)",
"-moz-linear-gradient(left left blue, red)",
"-moz-linear-gradient()",
"-moz-linear-gradient(cover, red, blue)",
"-moz-linear-gradient(auto, red, blue)",
"-moz-linear-gradient(22 top, red, blue)",
"-moz-linear-gradient(10% red blue)",
"-moz-linear-gradient(10%, red blue)",
"-moz-linear-gradient(10%,, red, blue)",
"-moz-linear-gradient(45px, center, red, blue)",
"-moz-linear-gradient(45px, center red, blue)",
"-moz-radial-gradient(contain, ellipse, red, blue)",
"-moz-radial-gradient(10deg contain, red, blue)",
"-moz-radial-gradient(10deg, contain,, red, blue)",
"-moz-radial-gradient(contain contain, red, blue)",
"-moz-radial-gradient(ellipse circle, red, blue)",
"-moz-repeating-linear-gradient(10px 10px, 20px, 30px 30px, 40px, blue 0, red 100%)",
"-moz-repeating-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
"-moz-repeating-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
"-moz-repeating-linear-gradient(10px, 20px, 30px, 40px, #00ccff 50%)",
"-moz-repeating-linear-gradient(40px 40px, 10px 10px, blue 0 fuchsia 10% red 100%)",
"-moz-repeating-linear-gradient(20px 20px 30px, 10px 10px, red 0, #ff0000 100%)",
"-moz-repeating-radial-gradient(left top, center, 20px 20px, 10px, from(blue), to(red))",
"-moz-repeating-linear-gradient(left left, top top, blue 0)",
"-moz-repeating-linear-gradient(inherit, 10px 10px, blue 0)",
"-moz-repeating-linear-gradient(left left blue red)",
"-moz-repeating-linear-gradient()" ]
},
"background-position": {
domProp: "backgroundPosition",
@ -1199,7 +1408,7 @@ var gCSSProperties = {
* getComputedStyle (which uses the CSS2 computed value, or
* CSS2.1 used value) doesn't match what the CSS2.1 computed
* value is. And they even require consistent font metrics for
* computation of 'normal'. -moz-block-height requires height
* computation of 'normal'. -moz-block-height requires height
* on a block.
*/
prerequisites: { "font-size": "19px", "font-size-adjust": "none", "font-family": "serif", "font-weight": "normal", "font-style": "normal", "height": "18px", "display": "block"},
@ -1582,7 +1791,7 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
initial_values: [ "auto" ],
other_values: [ "visiblePainted", "visibleFill", "visibleStroke", "visible",
"painted", "fill", "stroke", "all", "none" ],
"painted", "fill", "stroke", "all", "none" ],
invalid_values: []
},
"position": {
@ -1598,7 +1807,7 @@ var gCSSProperties = {
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ '"\u201C" "\u201D" "\u2018" "\u2019"',
'"\\201C" "\\201D" "\\2018" "\\2019"' ],
'"\\201C" "\\201D" "\\2018" "\\2019"' ],
other_values: [ "none", "'\"' '\"'" ],
invalid_values: []
},
@ -2072,7 +2281,7 @@ var gCSSProperties = {
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "5px,3px,2px", " 5px ,3px , 2px ", "1px", "5%", "3em" ],
other_values: [ "5px,3px,2px", " 5px ,3px , 2px ", "1px", "5%", "3em" ],
invalid_values: []
},
"stroke-dashoffset": {

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

@ -38,10 +38,35 @@
#ifndef nsMathUtils_h__
#define nsMathUtils_h__
#define _USE_MATH_DEFINES /* needed for M_ constants on Win32 */
#include "nscore.h"
#include <math.h>
#include <float.h>
/*
* The M_ constants are not defined by the WinCE/WinMo SDKs even with
* _USE_MATH_DEFINES. Provide a fallback. We assume that the entire
* set is not available if M_E isn't. Values taken from GNU libc,
* providing just enough precision for IEEE double.
*/
#ifndef M_E
# define M_E 2.7182818284590452354 /* e */
# define M_LOG2E 1.4426950408889634074 /* log_2 e */
# define M_LOG10E 0.43429448190325182765 /* log_10 e */
# define M_LN2 0.69314718055994530942 /* log_e 2 */
# define M_LN10 2.30258509299404568402 /* log_e 10 */
# define M_PI 3.14159265358979323846 /* pi */
# define M_PI_2 1.57079632679489661923 /* pi/2 */
# define M_PI_4 0.78539816339744830962 /* pi/4 */
# define M_1_PI 0.31830988618379067154 /* 1/pi */
# define M_2_PI 0.63661977236758134308 /* 2/pi */
# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#endif
/*
* round
*/
@ -123,4 +148,20 @@ inline NS_HIDDEN_(float) NS_floorf(float x)
return floorf(x);
}
/*
* hypot. We don't need a super accurate version of this, if a platform
* turns up with none of the possibilities below it would be okay to fall
* back to sqrt(x*x + y*y).
*/
inline NS_HIDDEN_(double) NS_hypot(double x, double y)
{
#if __GNUC__ >= 4
return __builtin_hypot(x, y);
#elif defined _WIN32
return _hypot(x, y);
#else
return hypot(x, y);
#endif
}
#endif