зеркало из https://github.com/mozilla/pjs.git
Bug 513395: Implement revised CSS gradient notation (1/2): parser and data structure changes
This commit is contained in:
Родитель
66d74905ab
Коммит
2ac3a6879f
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче