Title: [282162] trunk
Revision
282162
Author
commit-qu...@webkit.org
Date
2021-09-08 12:05:05 -0700 (Wed, 08 Sep 2021)

Log Message

Implement sin, cos, tan, e and pi for calc
https://bugs.webkit.org/show_bug.cgi?id=229507

Patch by Nikos Mouchtaris <nmouchta...@apple.com> on 2021-09-08
Reviewed by Simon Fraser.

Source/WebCore:

Tests: css3/calc/simple-trig-functions.html
       css3/calc/trig-functions-with-constants.html

Add support for sin, cos, and tan functions within calc. Also add e and pi
constant values within calc.

* css/CSSValueKeywords.in:
Add sin,cos,e and pi keywords.

* css/calc/CSSCalcExpressionNodeParser.cpp:
(WebCore::getConstantTable):
Add helper function with table mapping e and pi keywords to their
approximate numerical value.

(WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
Add handling for creation of sin,cos,tan operation nodes.

(WebCore::CSSCalcExpressionNodeParser::parseValue):
Add handling for creation of primitive css value when constant is parsed.

* css/calc/CSSCalcOperationNode.cpp:
(WebCore::determineCategory):
Add sin,cos,tan to switch statement.

(WebCore::functionFromOperator):
Add sin,cos,tan to switch statement.

(WebCore::CSSCalcOperationNode::createTrig):
Add function for creation of sin,cos,tan operation node.

(WebCore::CSSCalcOperationNode::combineChildren):
Add handling for performing sin,cos,tan function on child node.

(WebCore::CSSCalcOperationNode::simplifyNode):
Add handling for sin,cos,tan.

(WebCore::CSSCalcOperationNode::primitiveType const):
Remove assert that is no longer correct. Trig functions take can take an
angle and return a number, so it is no longer the case that all children
of a node producing a number must be numbers themself.

(WebCore::CSSCalcOperationNode::doubleValue const):
Convert chilren nodes that are angles to radians.

(WebCore::functionPrefixForOperator):
Add handling for sin,cos,tan.

(WebCore::CSSCalcOperationNode::evaluateOperator):
Add functionality for sin,cos,tan functions.

* css/calc/CSSCalcOperationNode.h:
* css/calc/CSSCalcValue.cpp:
(WebCore::createCSS):
Add handling for creation of sin,cos,tan operation nodes.

(WebCore::CSSCalcValue::isCalcFunction):
Add handling for sin,cos,tan.

* platform/calc/CalcExpressionOperation.cpp:
(WebCore::CalcExpressionOperation::evaluate const):
Add functionality for sin,cos,tan function.

* platform/calc/CalcOperator.cpp:
(WebCore::operator<<):
Add handling for sin,cos,tan.

* platform/calc/CalcOperator.h:

LayoutTests:

* fast/css/calc-parsing.html:
Added parsing tests for sin, cos, tan, e and pi.

* css3/calc/trig-functions-with-constants.html: Added.
Added additional tests for expected behavior of sin, cos, tan, e and pi.

* LayoutTests/animations/calc-animation-test.html: Added.
Added animation test for expanding width of box given a width defined using a calc _expression_
Involving sin and cos.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (282161 => 282162)


--- trunk/LayoutTests/ChangeLog	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/LayoutTests/ChangeLog	2021-09-08 19:05:05 UTC (rev 282162)
@@ -1,3 +1,21 @@
+2021-09-08  Nikos Mouchtaris  <nmouchta...@apple.com>
+
+        Implement sin, cos, tan, e and pi for calc
+        https://bugs.webkit.org/show_bug.cgi?id=229507
+
+        Reviewed by Simon Fraser.
+
+        * fast/css/calc-parsing.html:
+        Added parsing tests for sin, cos, tan, e and pi.
+
+        * css3/calc/trig-functions-with-constants.html: Added.
+        Added additional tests for expected behavior of sin, cos, tan, e and pi.
+
+        * LayoutTests/animations/calc-animation-test.html: Added.
+        Added animation test for expanding width of box given a width defined using a calc _expression_
+        Involving sin and cos.
+        
+
 2021-09-08  Ayumi Kojima  <ayumi_koj...@apple.com>
 
         [ BigSur wk2 Debug ] http/tests/inspector/network/resource-request-headers.html is flaky failing.

Added: trunk/LayoutTests/animations/calc-animation-test-expected.txt (0 => 282162)


--- trunk/LayoutTests/animations/calc-animation-test-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/animations/calc-animation-test-expected.txt	2021-09-08 19:05:05 UTC (rev 282162)
@@ -0,0 +1,4 @@
+PASS - "width" property for "box" element at 0.5s saw something close to: 150
+PASS - "width" property for "box" element at 1s saw something close to: 200
+PASS - "width" property for "box" element at 1.99s saw something close to: 300
+

Added: trunk/LayoutTests/animations/calc-animation-test.html (0 => 282162)


--- trunk/LayoutTests/animations/calc-animation-test.html	                        (rev 0)
+++ trunk/LayoutTests/animations/calc-animation-test.html	2021-09-08 19:05:05 UTC (rev 282162)
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+
+@keyframes TheAnimation {
+    from { width: calc(100px*cos(0)); }
+    to   { width: calc(300px*sin(pi/2)); }
+}
+
+#box {
+    position:absolute;
+    height: 100px;
+    width: 100px;
+    background-color: blue;
+    animation-duration: 2s;
+    animation-timing-function: linear;
+    animation-name: TheAnimation;
+}
+</style>
+</head>
+<body>
+<div id="box"></div>
+<div id="result"></div>
+<script>
+var expectedValues = [
+    // [animation-name, time, element-id, property, expected-value, tolerance]
+    ["TheAnimation", 0.5, "box", "width", 150, 15],
+    ["TheAnimation", 1, "box", "width", 200, 15],
+    ["TheAnimation", 1.99, "box", "width", 300, 15],
+];
+runAnimationTest(expectedValues, undefined, undefined, undefined, false, undefined);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/css3/calc/trig-functions-with-constants-expected.txt (0 => 282162)


--- trunk/LayoutTests/css3/calc/trig-functions-with-constants-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/calc/trig-functions-with-constants-expected.txt	2021-09-08 19:05:05 UTC (rev 282162)
@@ -0,0 +1,105 @@
+Tests functionality of sin, cos, tan, e and pi
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+element.style["width"] = "calc(sin(pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(pi - 3.14159265358979323846) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(e - 2.7182818284590452354) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(30deg + 1.0471967rad ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(30deg - 0.523599rad ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(3.14159 / 2 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(100grad) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(0 / 2 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(tan(30deg + 0.261799rad ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(tan(0.7853975rad ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(tan(3.14159 / 4 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(0.25turn) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(sin(cos(pi) + 1)) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(pi - 3.14159265358979323846) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(e - 2.7182818284590452354) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(30deg + 1.0471967rad ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(30deg - 0.523599rad ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(3.14159 / 2 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(100grad) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(0 / 2 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(tan(30deg + 0.261799rad ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(tan(0.7853975rad ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(tan(3.14159 / 4 + 1 - 1) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(0.25turn) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(sin(cos(pi) + 1)) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(tan(pi/4)*pi/2) * 100px)"
+PASS 100 is 100
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/css3/calc/trig-functions-with-constants.html (0 => 282162)


--- trunk/LayoutTests/css3/calc/trig-functions-with-constants.html	                        (rev 0)
+++ trunk/LayoutTests/css3/calc/trig-functions-with-constants.html	2021-09-08 19:05:05 UTC (rev 282162)
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+    <body>
+        <script src=""
+        <div id="testDiv"></div>
+        <script>
+            description("Tests functionality of sin, cos, tan, e and pi");
+
+            var element = document.getElementById("testDiv");
+            
+            function testProperty(propertyName)
+            {
+                
+                function testValue(_expression_, computedValue)
+                {
+                    debug('');
+                    element.style[propertyName] = '999px';
+                    evalAndLog(`element.style["${propertyName}"] = "${_expression_}"`);
+                    var value = Math.round(getComputedStyle(element).getPropertyValue(propertyName).slice(0,-2));
+                    shouldBe(`${value}`, computedValue);
+                }
+
+                //Test pi
+                testValue('calc(sin(pi/2) * 100px)', '100');
+                testValue('calc(cos(pi - 3.14159265358979323846) * 100px)', '100');
+
+                //Test e
+                testValue('calc(cos(e - 2.7182818284590452354) * 100px)', '100');
+                
+                //Test units
+                testValue('calc(sin(30deg + 1.0471967rad ) * 100px)', '100');
+                testValue('calc(cos(30deg - 0.523599rad ) * 100px)', '100');
+                testValue('calc(sin(3.14159 / 2 + 1 - 1) * 100px)', '100');
+                testValue('calc(sin(100grad) * 100px)', '100');
+                testValue('calc(cos(0 / 2 + 1 - 1) * 100px)', '100');
+                testValue('calc(tan(30deg + 0.261799rad ) * 100px)', '100');
+                testValue('calc(tan(0.7853975rad ) * 100px)', '100');
+                testValue('calc(tan(3.14159 / 4 + 1 - 1) * 100px)', '100');
+                testValue('calc(sin(0.25turn) * 100px)', '100');
+
+                //Test nesting
+                testValue('calc(cos(sin(cos(pi) + 1)) * 100px)', '100');
+                testValue('calc(sin(tan(pi/4)*pi/2) * 100px)', '100');
+                testValue('calc(sin(tan(pi/4)*pi/2) * 100px)', '100');
+                testValue('calc(sin(tan(pi/4)*pi/2) * 100px)', '100');
+            }
+
+            testProperty("width");
+            testProperty("min-width");
+        </script>
+    </body>
+</html>
+
+

Modified: trunk/LayoutTests/fast/css/calc-parsing-expected.txt (282161 => 282162)


--- trunk/LayoutTests/fast/css/calc-parsing-expected.txt	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/LayoutTests/fast/css/calc-parsing-expected.txt	2021-09-08 19:05:05 UTC (rev 282162)
@@ -52,6 +52,30 @@
 PASS element.style['width'] is "clamp(100px, 0%, 1%)"
 PASS getComputedStyle(element).getPropertyValue('width') is "100px"
 
+element.style["width"] = "calc(sin(90deg) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(45deg  +  45deg ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos( 0 ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos( 30deg - 30deg ) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(tan(45deg)*100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(tan(30deg + 15deg) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(sin(pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["width"] = "calc(cos(e - e) * 100px)"
+PASS 100 is 100
+
 element.style["width"] = "calc(100px, 200px)"
 PASS element.style['width'] is "999px"
 PASS getComputedStyle(element).getPropertyValue('width') is "999px"
@@ -104,6 +128,42 @@
 PASS element.style['width'] is "999px"
 PASS getComputedStyle(element).getPropertyValue('width') is "999px"
 
+element.style["width"] = "calc(sin(90px) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(sin(30deg + 1.0471967rad, 0) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(cos( 0 ,) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(cos( () 30deg - 0.523599rad ) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(tan(45deg ) ) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(tan(30deg, + 0.261799rad) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(sin(piiii/4) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(sin(e e/4) * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
+element.style["width"] = "calc(sin() * 100px)"
+PASS element.style['width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('width') is "999px"
+
 element.style["min-width"] = "calc(100px)"
 PASS element.style['min-width'] is "calc(100px)"
 PASS getComputedStyle(element).getPropertyValue('min-width') is "100px"
@@ -152,6 +212,30 @@
 PASS element.style['min-width'] is "clamp(100px, 0%, 1%)"
 PASS getComputedStyle(element).getPropertyValue('min-width') is "clamp(100px, 0%, 1%)"
 
+element.style["min-width"] = "calc(sin(90deg) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(45deg  +  45deg ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos( 0 ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos( 30deg - 30deg ) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(tan(45deg)*100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(tan(30deg + 15deg) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(sin(pi/2) * 100px)"
+PASS 100 is 100
+
+element.style["min-width"] = "calc(cos(e - e) * 100px)"
+PASS 100 is 100
+
 element.style["min-width"] = "calc(100px, 200px)"
 PASS element.style['min-width'] is "999px"
 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
@@ -203,6 +287,42 @@
 element.style["min-width"] = "clamp(1px,2px,2px,4px)"
 PASS element.style['min-width'] is "999px"
 PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(sin(90px) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(sin(30deg + 1.0471967rad, 0) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(cos( 0 ,) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(cos( () 30deg - 0.523599rad ) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(tan(45deg ) ) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(tan(30deg, + 0.261799rad) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(sin(piiii/4) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(sin(e e/4) * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
+
+element.style["min-width"] = "calc(sin() * 100px)"
+PASS element.style['min-width'] is "999px"
+PASS getComputedStyle(element).getPropertyValue('min-width') is "999px"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/css/calc-parsing.html (282161 => 282162)


--- trunk/LayoutTests/fast/css/calc-parsing.html	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/LayoutTests/fast/css/calc-parsing.html	2021-09-08 19:05:05 UTC (rev 282162)
@@ -19,6 +19,15 @@
                     shouldBeEqualToString(`element.style['${propertyName}']`, `${specifiedValue}`);
                     shouldBeEqualToString(`getComputedStyle(element).getPropertyValue('${propertyName}')`, `${computedValue}`);
                 }
+                
+                function testValue(_expression_, computedValue)
+                {
+                    debug('');
+                    element.style[propertyName] = '999px';
+                    evalAndLog(`element.style["${propertyName}"] = "${_expression_}"`);
+                    var value = Math.round(getComputedStyle(element).getPropertyValue(propertyName).slice(0,-2));
+                    shouldBe(`${value}`, computedValue);
+                }
 
                 // Valid expressions.
                 testExpression('calc(100px)', 'calc(100px)', '100px');
@@ -33,6 +42,14 @@
                 testExpression('min(100px,0%)', 'min(100px, 0%)', propertyName == 'width' ? '0px' : "min(100px, 0%)");
                 testExpression('max(100px,0%)', 'max(100px, 0%)', propertyName == 'width' ? '100px' : "max(100px, 0%)");
                 testExpression('clamp(100px,0%,1%)', 'clamp(100px, 0%, 1%)', propertyName == 'width' ? '100px' : "clamp(100px, 0%, 1%)");
+                testValue('calc(sin(90deg) * 100px)', '100');
+                testValue('calc(sin(45deg  +  45deg ) * 100px)', '100');
+                testValue('calc(cos( 0 ) * 100px)', '100');
+                testValue('calc(cos( 30deg - 30deg ) * 100px)', '100');
+                testValue('calc(tan(45deg)*100px)', '100');
+                testValue('calc(tan(30deg + 15deg) * 100px)', '100');
+                testValue('calc(sin(pi/2) * 100px)', '100');
+                testValue('calc(cos(e - e) * 100px)', '100');
 
                 // Non-parsing expressions.
                 testExpression('calc(100px, 200px)', '999px', '999px');
@@ -48,6 +65,15 @@
                 testExpression('clamp(200px,,300px)', '999px', '999px');
                 testExpression('clamp((),,300px)', '999px', '999px');
                 testExpression('clamp(1px,2px,2px,4px)', '999px', '999px');
+                testExpression('calc(sin(90px) * 100px)', '999px', '999px');
+                testExpression('calc(sin(30deg + 1.0471967rad, 0) * 100px)', '999px', '999px');
+                testExpression('calc(cos( 0 ,) * 100px)', '999px', '999px');
+                testExpression('calc(cos( () 30deg - 0.523599rad ) * 100px)', '999px', '999px');
+                testExpression('calc(tan(45deg ) ) * 100px)', '999px', '999px');
+                testExpression('calc(tan(30deg, + 0.261799rad) * 100px)', '999px', '999px');
+                testExpression('calc(sin(piiii/4) * 100px)', '999px', '999px');
+                testExpression('calc(sin(e e/4) * 100px)', '999px', '999px');
+                testExpression('calc(sin() * 100px)', '999px', '999px');
             }
 
             testProperty("width");

Modified: trunk/Source/WebCore/ChangeLog (282161 => 282162)


--- trunk/Source/WebCore/ChangeLog	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/ChangeLog	2021-09-08 19:05:05 UTC (rev 282162)
@@ -1,3 +1,78 @@
+2021-09-08  Nikos Mouchtaris  <nmouchta...@apple.com>
+
+        Implement sin, cos, tan, e and pi for calc
+        https://bugs.webkit.org/show_bug.cgi?id=229507
+
+        Reviewed by Simon Fraser.
+
+        Tests: css3/calc/simple-trig-functions.html
+               css3/calc/trig-functions-with-constants.html
+        
+        Add support for sin, cos, and tan functions within calc. Also add e and pi
+        constant values within calc.
+        
+        * css/CSSValueKeywords.in:
+        Add sin,cos,e and pi keywords.
+        
+        * css/calc/CSSCalcExpressionNodeParser.cpp:
+        (WebCore::getConstantTable):
+        Add helper function with table mapping e and pi keywords to their
+        approximate numerical value.
+        
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
+        Add handling for creation of sin,cos,tan operation nodes.
+        
+        (WebCore::CSSCalcExpressionNodeParser::parseValue):
+        Add handling for creation of primitive css value when constant is parsed.
+        
+        * css/calc/CSSCalcOperationNode.cpp:
+        (WebCore::determineCategory):
+        Add sin,cos,tan to switch statement.
+        
+        (WebCore::functionFromOperator):
+        Add sin,cos,tan to switch statement.
+        
+        (WebCore::CSSCalcOperationNode::createTrig):
+        Add function for creation of sin,cos,tan operation node.
+        
+        (WebCore::CSSCalcOperationNode::combineChildren):
+        Add handling for performing sin,cos,tan function on child node.
+        
+        (WebCore::CSSCalcOperationNode::simplifyNode):
+        Add handling for sin,cos,tan.
+        
+        (WebCore::CSSCalcOperationNode::primitiveType const):
+        Remove assert that is no longer correct. Trig functions take can take an
+        angle and return a number, so it is no longer the case that all children
+        of a node producing a number must be numbers themself.
+        
+        (WebCore::CSSCalcOperationNode::doubleValue const):
+        Convert chilren nodes that are angles to radians.
+        
+        (WebCore::functionPrefixForOperator):
+        Add handling for sin,cos,tan.
+        
+        (WebCore::CSSCalcOperationNode::evaluateOperator):
+        Add functionality for sin,cos,tan functions.
+        
+        * css/calc/CSSCalcOperationNode.h:
+        * css/calc/CSSCalcValue.cpp:
+        (WebCore::createCSS):
+        Add handling for creation of sin,cos,tan operation nodes.
+        
+        (WebCore::CSSCalcValue::isCalcFunction):
+        Add handling for sin,cos,tan.
+        
+        * platform/calc/CalcExpressionOperation.cpp:
+        (WebCore::CalcExpressionOperation::evaluate const):
+        Add functionality for sin,cos,tan function.
+        
+        * platform/calc/CalcOperator.cpp:
+        (WebCore::operator<<):
+        Add handling for sin,cos,tan.
+        
+        * platform/calc/CalcOperator.h:
+
 2021-09-08  Kimmo Kinnunen  <kkinnu...@apple.com>
 
         webgl/2.0.y/conformance/extensions/webgl-compressed-texture-etc.html fails on Metal

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (282161 => 282162)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-08 19:05:05 UTC (rev 282162)
@@ -1351,6 +1351,10 @@
 min
 max
 clamp
+sin
+cos
+e
+pi
 
 from-image
 

Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (282161 => 282162)


--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-08 19:05:05 UTC (rev 282162)
@@ -95,6 +95,11 @@
     NoMoreTokens
 };
 
+static const CSSCalcSymbolTable getConstantTable()
+{
+    return { { CSSValuePi, CSSUnitType::CSS_NUMBER, piDouble }, { CSSValueE, CSSUnitType::CSS_NUMBER, std::exp(1.0) } };
+}
+
 static ParseState checkDepthAndIndex(int depth, CSSParserTokenRange tokens)
 {
     if (tokens.atEnd())
@@ -124,6 +129,9 @@
         minArgumentCount = 3;
         maxArgumentCount = 3;
         break;
+    case CSSValueSin:
+    case CSSValueCos:
+    case CSSValueTan:
     case CSSValueCalc:
         maxArgumentCount = 1;
         break;
@@ -166,6 +174,15 @@
     case CSSValueClamp:
         result = CSSCalcOperationNode::createMinOrMaxOrClamp(CalcOperator::Clamp, WTFMove(nodes), m_destinationCategory);
         break;
+    case CSSValueSin:
+        result = CSSCalcOperationNode::createTrig(CalcOperator::Sin, WTFMove(nodes));
+        break;
+    case CSSValueCos:
+        result = CSSCalcOperationNode::createTrig(CalcOperator::Cos, WTFMove(nodes));
+        break;
+    case CSSValueTan:
+        result = CSSCalcOperationNode::createTrig(CalcOperator::Tan, WTFMove(nodes));
+        break;
     case CSSValueWebkitCalc:
     case CSSValueCalc:
         result = CSSCalcOperationNode::createSum(WTFMove(nodes));
@@ -193,6 +210,7 @@
     switch (token.type()) {
     case IdentToken: {
         auto value = m_symbolTable.get(token.id());
+        value = value ? value : getConstantTable().get(token.id());
         if (!value)
             return false;
         return makeCSSCalcPrimitiveValueNode(value->type, value->value);

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp (282161 => 282162)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-08 19:05:05 UTC (rev 282162)
@@ -72,6 +72,9 @@
         if (rightCategory != CalculationCategory::Number || rightSide.isZero())
             return CalculationCategory::Other;
         return leftCategory;
+    case CalcOperator::Sin:
+    case CalcOperator::Cos:
+    case CalcOperator::Tan:
     case CalcOperator::Min:
     case CalcOperator::Max:
     case CalcOperator::Clamp:
@@ -140,7 +143,9 @@
                 return CalculationCategory::Other;
             break;
         }
-
+        case CalcOperator::Sin:
+        case CalcOperator::Cos:
+        case CalcOperator::Tan:
         case CalcOperator::Min:
         case CalcOperator::Max:
         case CalcOperator::Clamp:
@@ -255,6 +260,12 @@
         return CSSValueMax;
     case CalcOperator::Clamp:
         return CSSValueClamp;
+    case CalcOperator::Sin:
+        return CSSValueSin;
+    case CalcOperator::Cos:
+        return CSSValueCos;
+    case CalcOperator::Tan:
+        return CSSValueTan;
     }
     return CSSValueCalc;
 }
@@ -341,6 +352,20 @@
     return adoptRef(new CSSCalcOperationNode(category.value(), op, WTFMove(values)));
 }
 
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createTrig(CalcOperator op, Vector<Ref<CSSCalcExpressionNode>>&& values)
+{
+    if (values.size() != 1)
+        return nullptr;
+    
+    auto childCategory = values[0]->category();
+    if (childCategory != CalculationCategory::Number && childCategory != CalculationCategory::Angle) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create trig node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+
+    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, op, WTFMove(values)));
+}
+
 void CSSCalcOperationNode::hoistChildrenWithOperator(CalcOperator op)
 {
     ASSERT(op == CalcOperator::Add || op == CalcOperator::Multiply);
@@ -405,9 +430,17 @@
 
 void CSSCalcOperationNode::combineChildren()
 {
-    if (m_children.size() < 2)
+    if (m_children.size() < 2) {
+        if (m_children.size() == 1 && isTrigNode()) {
+            double resolvedValue = doubleValue(m_children[0]->primitiveType());
+            auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, CSSUnitType::CSS_NUMBER));
+
+            m_children.clear();
+            m_children.append(WTFMove(newChild));
+        }
         return;
-
+    }
+    
     if (shouldSortChildren()) {
         // <https://drafts.csswg.org/css-values-4/#sort-a-calculations-children>
         std::stable_sort(m_children.begin(), m_children.end(), [](const auto& first, const auto& second) {
@@ -595,8 +628,8 @@
     // using its children, expressed in the result’s canonical unit.
     if (is<CSSCalcOperationNode>(rootNode)) {
         auto& calcOperationNode = downcast<CSSCalcOperationNode>(rootNode.get());
-        // Don't simplify at the root, otherwise we lose track of the operation for serialization.
-        if (calcOperationNode.children().size() == 1 && depth)
+        // Simplify operations with only one child node (other than root and operations that only need one node).
+        if (calcOperationNode.children().size() == 1 && depth && !calcOperationNode.isTrigNode())
             return WTFMove(calcOperationNode.children()[0]);
         
         if (calcOperationNode.isCalcSumNode()) {
@@ -611,7 +644,10 @@
         
         if (calcOperationNode.isMinOrMaxNode())
             calcOperationNode.combineChildren();
-
+        
+        if (calcOperationNode.isTrigNode())
+            calcOperationNode.combineChildren();
+        
         // If only one child remains, return the child (except at the root).
         auto shouldCombineParentWithOnlyChild = [](const CSSCalcOperationNode& parent, int depth)
         {
@@ -676,12 +712,7 @@
     auto unitCategory = category();
     switch (unitCategory) {
     case CalculationCategory::Number:
-#if ASSERT_ENABLED
-        for (auto& child : m_children)
-            ASSERT(child->category() == CalculationCategory::Number);
-#endif
         return CSSUnitType::CSS_NUMBER;
-
     case CalculationCategory::Percent: {
         if (m_children.isEmpty())
             return CSSUnitType::CSS_UNKNOWN;
@@ -748,6 +779,8 @@
         CSSUnitType childType = unitType;
         if (allowNumbers && unitType != CSSUnitType::CSS_NUMBER && child->primitiveType() == CSSUnitType::CSS_NUMBER)
             childType = CSSUnitType::CSS_NUMBER;
+        if (isTrigNode() && unitType != CSSUnitType::CSS_NUMBER)
+            childType = CSSUnitType::CSS_RAD;
         return child->doubleValue(childType);
     }));
 }
@@ -800,6 +833,9 @@
     case CalcOperator::Divide:
         ASSERT_NOT_REACHED();
         return "";
+    case CalcOperator::Sin: return "sin(";
+    case CalcOperator::Cos: return "cos(";
+    case CalcOperator::Tan: return "tan(";
     case CalcOperator::Min: return "min(";
     case CalcOperator::Max: return "max(";
     case CalcOperator::Clamp: return "clamp(";
@@ -1004,7 +1040,22 @@
         double max = children[2];
         return std::max(min, std::min(value, max));
     }
+    case CalcOperator::Sin: {
+        if (children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::sin(children[0]);
     }
+    case CalcOperator::Cos: {
+        if (children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::cos(children[0]);
+    }
+    case CalcOperator::Tan: {
+        if (children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::tan(children[0]);
+    }
+    }
     ASSERT_NOT_REACHED();
     return 0;
 }

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h (282161 => 282162)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-08 19:05:05 UTC (rev 282162)
@@ -37,6 +37,7 @@
     static RefPtr<CSSCalcOperationNode> createSum(Vector<Ref<CSSCalcExpressionNode>>&& values);
     static RefPtr<CSSCalcOperationNode> createProduct(Vector<Ref<CSSCalcExpressionNode>>&& values);
     static RefPtr<CSSCalcOperationNode> createMinOrMaxOrClamp(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values, CalculationCategory destinationCategory);
+    static RefPtr<CSSCalcOperationNode> createTrig(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values);
 
     static Ref<CSSCalcExpressionNode> simplify(Ref<CSSCalcExpressionNode>&&);
 
@@ -46,6 +47,7 @@
     bool isCalcSumNode() const { return m_operator == CalcOperator::Add; }
     bool isCalcProductNode() const { return m_operator == CalcOperator::Multiply; }
     bool isMinOrMaxNode() const { return m_operator == CalcOperator::Min || m_operator == CalcOperator::Max; }
+    bool isTrigNode() const { return m_operator == CalcOperator::Sin || m_operator == CalcOperator::Cos || m_operator == CalcOperator::Tan; }
     bool shouldSortChildren() const { return isCalcSumNode() || isCalcProductNode(); }
 
     void hoistChildrenWithOperator(CalcOperator);

Modified: trunk/Source/WebCore/css/calc/CSSCalcValue.cpp (282161 => 282162)


--- trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-08 19:05:05 UTC (rev 282162)
@@ -164,6 +164,14 @@
 
             return CSSCalcOperationNode::createProduct(createCSS(operationChildren, style));
         }
+        case CalcOperator::Cos:
+        case CalcOperator::Tan:
+        case CalcOperator::Sin: {
+            auto children = createCSS(operationChildren, style);
+            if (children.size() != 1)
+                return nullptr;
+            return CSSCalcOperationNode::createTrig(op, WTFMove(children));
+        }
         case CalcOperator::Min:
         case CalcOperator::Max:
         case CalcOperator::Clamp: {
@@ -283,6 +291,9 @@
     case CSSValueMin:
     case CSSValueMax:
     case CSSValueClamp:
+    case CSSValueSin:
+    case CSSValueCos:
+    case CSSValueTan:
         return true;
     default:
         return false;

Modified: trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp (282161 => 282162)


--- trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-08 19:05:05 UTC (rev 282162)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "CalcExpressionOperation.h"
 
+#include <cmath>
 #include <wtf/text/TextStream.h>
 
 namespace WebCore {
@@ -86,7 +87,22 @@
         float max = m_children[2]->evaluate(maxValue);
         return std::max(min, std::min(value, max));
     }
+    case CalcOperator::Sin: {
+        if (m_children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::sin(m_children[0]->evaluate(maxValue));
     }
+    case CalcOperator::Cos: {
+        if (m_children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::cos(m_children[0]->evaluate(maxValue));
+    }
+    case CalcOperator::Tan: {
+        if (m_children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::tan(m_children[0]->evaluate(maxValue));
+    }
+    }
     ASSERT_NOT_REACHED();
     return std::numeric_limits<float>::quiet_NaN();
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.cpp (282161 => 282162)


--- trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-08 19:05:05 UTC (rev 282162)
@@ -40,6 +40,9 @@
     case CalcOperator::Min: ts << "min"; break;
     case CalcOperator::Max: ts << "max"; break;
     case CalcOperator::Clamp: ts << "clamp"; break;
+    case CalcOperator::Sin: ts << "sin"; break;
+    case CalcOperator::Cos: ts << "cos"; break;
+    case CalcOperator::Tan: ts << "tan"; break;
     }
     return ts;
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.h (282161 => 282162)


--- trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-08 18:52:25 UTC (rev 282161)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-08 19:05:05 UTC (rev 282162)
@@ -38,6 +38,9 @@
     Min = 0,
     Max,
     Clamp,
+    Sin,
+    Cos,
+    Tan,
 };
 
 TextStream& operator<<(TextStream&, CalcOperator);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to