Commit 49879cc6 authored by fs@opera.com's avatar fs@opera.com

Support scientific notation in CSS numbers/percentages/dimensions

Previously, scientific notation (scinot) was only supported for SVG
presentation attributes through a special tokenizer quirk. Since scinot
has now been added to the CSS syntax spec [1][2][3] and is already
supported by Gecko [4] and IE(11).
To harmonize, the call to parseSVGNumber(...) is replaced with a call to
charactersToDouble(...). This results in a small behavioral change, since
the former would reject numbers that were too large. These will now parse
as "Infinity" [5].
Since this removes the last caller of isSVGNumberParsingEnabledForMode()
that function is removed as well.

[1] http://dev.w3.org/csswg/css-syntax/#number-token-diagram
[2] http://lists.w3.org/Archives/Public/www-style/2012Aug/0900.html
[3] http://lists.w3.org/Archives/Public/www-style/2013Apr/0428.html
[4] https://bugzilla.mozilla.org/show_bug.cgi?id=964529
[5] Tested browsers were not entirely consistent in their treatment of
    infinities (Gecko: Infinity, IE: FLT_MAX).

BUG=388161
BUG=344645

Review URL: https://codereview.chromium.org/545173003

git-svn-id: svn://svn.chromium.org/blink/trunk@181560 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent da33e9a8
......@@ -3,7 +3,7 @@
<script src="../resources/testharnessreport.js"></script>
<script src="resources/property-parsing-test.js"></script>
<script>
assert_valid_value("counterIncrement", "hello world 999");
assert_valid_value("counterIncrement", "hello world 999", "hello 1, world 999");
assert_invalid_value("counterIncrement", 'hello "world"');
assert_invalid_value("counterIncrement", "40");
assert_invalid_value("counterReset", 'c 10 20');
......
......@@ -12,7 +12,10 @@ function convert_to_dashes(property) {
});
}
function assert_valid_value(property, value) {
function assert_valid_value(property, value, serializedValue) {
if (arguments.length != 3)
serializedValue = value;
test(function(){
assert_true(CSS.supports(convert_to_dashes(property), value));
}, "CSS.supports('" + property + "', '" + value + "') should return true");
......@@ -27,6 +30,7 @@ function assert_valid_value(property, value) {
var div = document.createElement('div');
div.style[property] = value;
var readValue = div.style[property];
assert_equals(readValue, serializedValue);
div.style[property] = readValue;
assert_equals(div.style[property], readValue);
}, "Serialization should round-trip after setting e.style['" + property + "'] = '" + value + "'");
......
<!doctype html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="resources/property-parsing-test.js"></script>
<script>
assert_valid_value("opacity", "2e2", "200");
assert_valid_value("opacity", "2E2", "200");
assert_valid_value("opacity", "2e+2", "200");
assert_valid_value("opacity", "2E+2", "200");
assert_valid_value("opacity", "2e-2", "0.02");
assert_valid_value("opacity", "2E-2", "0.02");
assert_valid_value("opacity", "2e200", "2e+200");
assert_valid_value("opacity", "2E200", "2e+200");
assert_valid_value("opacity", "2e+200", "2e+200");
assert_valid_value("opacity", "2E+200", "2e+200");
assert_valid_value("opacity", "2e-200", "2e-200");
assert_valid_value("opacity", "2E-200", "2e-200");
assert_valid_value("opacity", "1e0", "1");
assert_valid_value("opacity", "1e+0", "1");
assert_valid_value("opacity", "1e-0", "1");
assert_valid_value("opacity", "1e10", "10000000000");
assert_valid_value("opacity", "1e+10", "10000000000");
assert_valid_value("opacity", "1e-10", "1e-10");
assert_valid_value("width", "2e2px", "200px");
assert_valid_value("width", "2E2px", "200px");
assert_valid_value("width", "2e+2px", "200px");
assert_valid_value("width", "2E+2px", "200px");
assert_valid_value("width", "2e-2px", "0.02px");
assert_valid_value("width", "2E-2px", "0.02px");
assert_valid_value("width", "2e200px", "2e+200px");
assert_valid_value("width", "2E200px", "2e+200px");
assert_valid_value("width", "2e+200px", "2e+200px");
assert_valid_value("width", "2E+200px", "2e+200px");
assert_valid_value("width", "2e-200px", "2e-200px");
assert_valid_value("width", "2E-200px", "2e-200px");
assert_valid_value("width", "1e0px", "1px");
assert_valid_value("width", "1e+0px", "1px");
assert_valid_value("width", "1e-0px", "1px");
assert_valid_value("width", "1e10px", "10000000000px");
assert_valid_value("width", "1e+10px", "10000000000px");
assert_valid_value("width", "1e-10px", "1e-10px");
assert_valid_value("width", "1e0em", "1em");
assert_valid_value("width", "1e+0em", "1em");
assert_valid_value("width", "1e-0em", "1em");
assert_valid_value("width", "1e10em", "10000000000em");
assert_valid_value("width", "1e+10em", "10000000000em");
assert_valid_value("width", "1e-10em", "1e-10em");
assert_valid_value("width", "1e0%", "1%");
assert_valid_value("width", "1e+0%", "1%");
assert_valid_value("width", "1e-0%", "1%");
assert_valid_value("width", "1e10%", "10000000000%");
assert_valid_value("width", "1e+10%", "10000000000%");
assert_valid_value("width", "1e-10%", "1e-10%");
// Large exponents (not representable). This is not necessarily the correct value.
assert_valid_value("opacity", "1e600", "0");
assert_valid_value("opacity", "1e-600", "0");
assert_valid_value("width", "1e600px", "0px");
assert_valid_value("width", "1e-600px", "0px");
assert_invalid_value("width", "1e1.0px");
assert_invalid_value("width", "1e10.0px");
assert_invalid_value("width", "1e1.0em");
assert_invalid_value("width", "1e10.0em");
</script>
......@@ -96,9 +96,9 @@ PASS getComputedStyle(text).baselineShift is "50px"
Test behavior on overflow
PASS getComputedStyle(text).baselineShift is "baseline"
PASS getComputedStyle(text).baselineShift is "0px"
PASS getComputedStyle(text).baselineShift is "baseline"
PASS getComputedStyle(text).baselineShift is "baseline"
PASS getComputedStyle(text).baselineShift is "baseline"
PASS getComputedStyle(text).baselineShift is "0px"
Invalid values
PASS getComputedStyle(text).baselineShift is "baseline"
......
......@@ -82,8 +82,8 @@ test("5e1 ", "50px");
debug("");
debug("Test behavior on overflow");
test("2E+500", "baseline");
test("-2E+500", "baseline");
test("2E+500", "0px");
test("-2E+500", "0px");
debug("");
debug("Invalid values");
......@@ -94,4 +94,4 @@ test("50.e0", "baseline");
var successfullyParsed = true;
completeTest();
\ No newline at end of file
completeTest();
......@@ -78,11 +78,6 @@ inline bool isCSSViewportParsingEnabledForMode(CSSParserMode mode)
return mode == CSSViewportRuleMode;
}
inline bool isSVGNumberParsingEnabledForMode(CSSParserMode mode)
{
return mode == SVGAttributeMode;
}
inline bool isUseCounterEnabledForMode(CSSParserMode mode)
{
// We don't count the UA style sheet in our statistics.
......
......@@ -1239,28 +1239,23 @@ restartAfterComment:
break;
}
// Use SVG parser for numbers on SVG presentation attributes.
if (isSVGNumberParsingEnabledForMode(m_parser.m_context.mode())) {
// We need to take care of units like 'em' or 'ex'.
SrcCharacterType* character = currentCharacter<SrcCharacterType>();
if (isASCIIAlphaCaselessEqual(*character, 'e')) {
ASSERT(character - tokenStart<SrcCharacterType>() > 0);
// We need to take care of units like 'em' or 'ex'.
SrcCharacterType* character = currentCharacter<SrcCharacterType>();
if (isASCIIAlphaCaselessEqual(*character, 'e')) {
ASSERT(character - tokenStart<SrcCharacterType>() > 0);
++character;
if (*character == '-' || *character == '+' || isASCIIDigit(*character)) {
++character;
if (*character == '-' || *character == '+' || isASCIIDigit(*character)) {
while (isASCIIDigit(*character))
++character;
while (isASCIIDigit(*character))
++character;
// Use FLOATTOKEN if the string contains exponents.
dotSeen = true;
currentCharacter<SrcCharacterType>() = character;
}
// Use FLOATTOKEN if the string contains exponents.
dotSeen = true;
currentCharacter<SrcCharacterType>() = character;
}
if (!parseSVGNumber(tokenStart<SrcCharacterType>(), character - tokenStart<SrcCharacterType>(), yylval->number))
break;
} else {
yylval->number = charactersToDouble(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
}
yylval->number = charactersToDouble(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
// Type of the function.
if (isIdentifierStart<SrcCharacterType>()) {
SrcCharacterType* type = currentCharacter<SrcCharacterType>();
......
......@@ -145,18 +145,6 @@ static bool genericParseNumber(const CharType*& ptr, const CharType* end, FloatT
return true;
}
template <typename CharType>
bool parseSVGNumber(CharType* begin, size_t length, double& number)
{
const CharType* ptr = begin;
const CharType* end = ptr + length;
return genericParseNumber(ptr, end, number, AllowLeadingAndTrailingWhitespace);
}
// Explicitly instantiate the two flavors of parseSVGNumber() to satisfy external callers
template bool parseSVGNumber(LChar* begin, size_t length, double&);
template bool parseSVGNumber(UChar* begin, size_t length, double&);
bool parseNumber(const LChar*& ptr, const LChar* end, float& number, WhitespaceMode mode)
{
return genericParseNumber(ptr, end, number, mode);
......
......@@ -41,8 +41,6 @@ enum WhitespaceMode {
AllowLeadingAndTrailingWhitespace = AllowLeadingWhitespace | AllowTrailingWhitespace
};
template <typename CharType>
bool parseSVGNumber(CharType* ptr, size_t length, double& number);
bool parseNumber(const LChar*& ptr, const LChar* end, float& number, WhitespaceMode = AllowLeadingAndTrailingWhitespace);
bool parseNumber(const UChar*& ptr, const UChar* end, float& number, WhitespaceMode = AllowLeadingAndTrailingWhitespace);
bool parseNumberOptionalNumber(const String& s, float& h, float& v);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment