Converting time, angle and frequency units in CSS calc() function
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Jan 2015 17:18:23 +0000 (17:18 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Jan 2015 17:18:23 +0000 (17:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138356

Reviewed by Darin Adler.

Source/WebCore:

Update CSSPrimitiveValue::primitiveType() to actually query the
primitiveType of the CSSCalcValue instead of assuming a given
type based on its category (e.g. If category is CalcTime, then
assume type is CSS_MS, even though it would be CSS_S as well).

This would like to calculation errors such as:
calc(4s + 1s) -> 5ms

Because we would assume the unit is CSS_MS without actually
checking.

This patch is inspired by the following Blink revision
by <rhodovan.u-szeged@partner.samsung.com> and initial WebKit
patch from <tmeszaros.u-szeged@partner.samsung.com>:
https://src.chromium.org/viewvc/blink?view=rev&revision=179101

Test: fast/css/calc-with-angle-time-frequency.html

* css/CSSCalculationValue.h:
(WebCore::CSSCalcValue::primitiveType):
* css/CSSPrimitiveValue.cpp:
(WebCore::CSSPrimitiveValue::primitiveType):

LayoutTests:

Update fast/css/calc-with-angle-time-frequency.html to include more
test cases and actually validate the result of the calculation,
instead of merely setting the CSS property and being happy if we don't
crash.

* fast/css/calc-with-angle-time-frequency-expected.txt:
* fast/css/calc-with-angle-time-frequency.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@178627 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/css/calc-with-angle-time-frequency-expected.txt
LayoutTests/fast/css/calc-with-angle-time-frequency.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSCalculationValue.h
Source/WebCore/css/CSSPrimitiveValue.cpp

index c69807c..0661c0c 100644 (file)
@@ -1,3 +1,18 @@
+2015-01-17  Chris Dumez  <cdumez@apple.com>
+
+        Converting time, angle and frequency units in CSS calc() function
+        https://bugs.webkit.org/show_bug.cgi?id=138356
+
+        Reviewed by Darin Adler.
+
+        Update fast/css/calc-with-angle-time-frequency.html to include more
+        test cases and actually validate the result of the calculation,
+        instead of merely setting the CSS property and being happy if we don't
+        crash.
+
+        * fast/css/calc-with-angle-time-frequency-expected.txt:
+        * fast/css/calc-with-angle-time-frequency.html:
+
 2015-01-16  Daniel Bates  <dabates@apple.com>
 
         Update some expected results for iOS
index 654ddf7..a93b4d5 100644 (file)
@@ -1 +1,60 @@
-This test passes if it does not crash.
+Tests that using angle, time and frequency units in calc() is working as intended.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300deg/2))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(150deg))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(150deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300rad/2))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(150rad))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(8594.366926962348deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300grad/2))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(150grad))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(135deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(3turn/2))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(1.5turn))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(540deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(1turn + 10deg))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(370deg))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(370deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300deg + 30deg))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(330deg))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(330deg)"
+testDiv.style['-webkit-filter'] = 'hue-rotate(calc(2turn + 1turn))'
+PASS testDiv.style['-webkit-filter'] is "hue-rotate(calc(3turn))"
+PASS window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter') is "hue-rotate(1080deg)"
+testDiv.style['transition-delay'] = 'calc(300ms/2)'
+PASS testDiv.style['transition-delay'] is "calc(150ms)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "0.15s"
+testDiv.style['transition-delay'] = 'calc(300s/2)'
+PASS testDiv.style['transition-delay'] is "calc(150s)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "150s"
+testDiv.style['transition-delay'] = 'calc(10s + 100ms)'
+PASS testDiv.style['transition-delay'] is "calc(10100ms)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "10.1s"
+testDiv.style['transition-delay'] = 'calc(100ms + 10s)'
+PASS testDiv.style['transition-delay'] is "calc(10100ms)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "10.1s"
+testDiv.style['transition-delay'] = 'calc(4s + 1s)'
+PASS testDiv.style['transition-delay'] is "calc(5s)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "5s"
+testDiv.style['transition-delay'] = 'calc(4ms + 1ms)'
+PASS testDiv.style['transition-delay'] is "calc(5ms)"
+PASS window.getComputedStyle(testDiv).getPropertyValue('transition-delay') is "0.005s"
+testDiv.style['width'] = 'calc(300Hz/2)'
+PASS testDiv.style['width'] is ""
+testDiv.style['width'] = 'calc(300kHz/2)'
+PASS testDiv.style['width'] is ""
+testDiv.style['width'] = 'calc(10Hz + 20Hz)'
+PASS testDiv.style['width'] is ""
+testDiv.style['width'] = 'calc(10kHz + 20kHz)'
+PASS testDiv.style['width'] is ""
+testDiv.style['width'] = 'calc(10kHz + 200Hz)'
+PASS testDiv.style['width'] is ""
+testDiv.style['width'] = 'calc(200Hz + 10kHz)'
+PASS testDiv.style['width'] is ""
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
index b67e8a7..e92f241 100644 (file)
@@ -1,25 +1,87 @@
+<!DOCTYPE html>
 <html>
-    <head>
+    <body>
+        <script src="../../resources/js-test-pre.js"></script>
+        <div id="testDiv"></div>
         <script>
-            if (window.testRunner)
-                testRunner.dumpAsText();
+            description("Tests that using angle, time and frequency units in calc() is working as intended.");
+
+            var testDiv = document.getElementById("testDiv");
+
+            // Angle units.
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300deg/2))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(150deg))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(150deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300rad/2))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(150rad))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(8594.366926962348deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300grad/2))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(150grad))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(135deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(3turn/2))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(1.5turn))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(540deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(1turn + 10deg))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(370deg))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(370deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(300deg + 30deg))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(330deg))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(330deg)");
+
+            evalAndLog("testDiv.style['-webkit-filter'] = 'hue-rotate(calc(2turn + 1turn))'");
+            shouldBeEqualToString("testDiv.style['-webkit-filter']", "hue-rotate(calc(3turn))");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('-webkit-filter')", "hue-rotate(1080deg)");
+
+            // Time units.
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(300ms/2)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(150ms)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "0.15s");
+
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(300s/2)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(150s)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "150s");
+
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(10s + 100ms)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(10100ms)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "10.1s");
+
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(100ms + 10s)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(10100ms)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "10.1s");
+
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(4s + 1s)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(5s)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "5s");
+
+            evalAndLog("testDiv.style['transition-delay'] = 'calc(4ms + 1ms)'");
+            shouldBeEqualToString("testDiv.style['transition-delay']", "calc(5ms)");
+            shouldBeEqualToString("window.getComputedStyle(testDiv).getPropertyValue('transition-delay')", "0.005s");
+
+            // Frequency units.
+            // NOTE: Since there is no CSS property that uses frequency at the moment we only test the parsing.
+            evalAndLog("testDiv.style['width'] = 'calc(300Hz/2)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
+
+            evalAndLog("testDiv.style['width'] = 'calc(300kHz/2)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
+
+            evalAndLog("testDiv.style['width'] = 'calc(10Hz + 20Hz)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
+
+            evalAndLog("testDiv.style['width'] = 'calc(10kHz + 20kHz)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
+
+            evalAndLog("testDiv.style['width'] = 'calc(10kHz + 200Hz)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
+
+            evalAndLog("testDiv.style['width'] = 'calc(200Hz + 10kHz)'");
+            shouldBeEqualToString("testDiv.style['width']", "");
         </script>
-        <style>
-            * {
-                width: calc(300deg/2);
-                width: calc(300rad/2);
-                width: calc(300grad/2);
-                width: calc(300turn/2);
-
-                width: calc(300ms/2);
-                width: calc(300s/2);
-
-                width: calc(300hz/2);
-                width: calc(300khz/2);
-            }
-        </style>
-    </head>
-    <body>
-        This test passes if it does not crash.
+        <script src="../../resources/js-test-post.js"></script>
     </body>
 </html>
index cf69c29..aac63df 100644 (file)
@@ -1,5 +1,35 @@
 2015-01-17  Chris Dumez  <cdumez@apple.com>
 
+        Converting time, angle and frequency units in CSS calc() function
+        https://bugs.webkit.org/show_bug.cgi?id=138356
+
+        Reviewed by Darin Adler.
+
+        Update CSSPrimitiveValue::primitiveType() to actually query the
+        primitiveType of the CSSCalcValue instead of assuming a given
+        type based on its category (e.g. If category is CalcTime, then
+        assume type is CSS_MS, even though it would be CSS_S as well).
+
+        This would like to calculation errors such as:
+        calc(4s + 1s) -> 5ms
+
+        Because we would assume the unit is CSS_MS without actually
+        checking.
+
+        This patch is inspired by the following Blink revision
+        by <rhodovan.u-szeged@partner.samsung.com> and initial WebKit
+        patch from <tmeszaros.u-szeged@partner.samsung.com>:
+        https://src.chromium.org/viewvc/blink?view=rev&revision=179101
+
+        Test: fast/css/calc-with-angle-time-frequency.html
+
+        * css/CSSCalculationValue.h:
+        (WebCore::CSSCalcValue::primitiveType):
+        * css/CSSPrimitiveValue.cpp:
+        (WebCore::CSSPrimitiveValue::primitiveType):
+
+2015-01-17  Chris Dumez  <cdumez@apple.com>
+
         Generate shorthandForProperty() implementation from CSSPropertyNames.in
         https://bugs.webkit.org/show_bug.cgi?id=140556
 
index c43e17f..e4d52e7 100644 (file)
@@ -95,6 +95,7 @@ public:
     bool isNegative() const { return m_expression->doubleValue() < 0; }
     bool isPositive() const { return m_expression->doubleValue() > 0; }
     double computeLengthPx(const CSSToLengthConversionData&) const;
+    unsigned short primitiveType() const { return m_expression->primitiveType(); }
 
     Ref<CalculationValue> createCalculationValue(const CSSToLengthConversionData&) const;
     void setPermittedValueRange(CalculationPermittedValueRange);
index fe642e4..316f6c3 100644 (file)
@@ -198,11 +198,9 @@ unsigned short CSSPrimitiveValue::primitiveType() const
     case CalcPercentLength:
         return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH;
     case CalcAngle:
-        return CSSPrimitiveValue::CSS_DEG;
     case CalcTime:
-        return CSSPrimitiveValue::CSS_MS;
     case CalcFrequency:
-        return CSSPrimitiveValue::CSS_HZ;
+        return m_value.calc->primitiveType();
     case CalcOther:
         return CSSPrimitiveValue::CSS_UNKNOWN;
     }