- 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);