Title: [282795] trunk
Revision
282795
Author
[email protected]
Date
2021-09-20 17:24:50 -0700 (Mon, 20 Sep 2021)

Log Message

Implement exp,log functions calc functions
https://bugs.webkit.org/show_bug.cgi?id=229897

Patch by Nikos Mouchtaris <[email protected]> on 2021-09-20
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-values/exp-log-compute.html: Added.
* web-platform-tests/css/css-values/exp-log-invalid.html: Added.
* web-platform-tests/css/css-values/exp-log-serialize.html: Added.

Source/WebCore:

Added support for calc functions exp and log. Involved adding exp and log CSS keywords and handling
for parsing these functions and their arguments as well as computing the result based on the arguments.
Spec for these functions: https://drafts.csswg.org/css-values-4/#exponent-funcs.

Tests: imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html
       imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html
       imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html

* css/CSSValueKeywords.in:
* css/calc/CSSCalcExpressionNodeParser.cpp:
(WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
* css/calc/CSSCalcOperationNode.cpp:
(WebCore::determineCategory):
(WebCore::functionFromOperator):
(WebCore::CSSCalcOperationNode::createLog):
(WebCore::CSSCalcOperationNode::createExp):
(WebCore::CSSCalcOperationNode::combineChildren):
(WebCore::CSSCalcOperationNode::simplifyNode):
(WebCore::functionPrefixForOperator):
(WebCore::CSSCalcOperationNode::evaluateOperator):
* css/calc/CSSCalcOperationNode.h:
* css/calc/CSSCalcValue.cpp:
(WebCore::createCSS):
(WebCore::CSSCalcValue::isCalcFunction):
* platform/calc/CalcExpressionOperation.cpp:
(WebCore::CalcExpressionOperation::evaluate const):
* platform/calc/CalcOperator.cpp:
(WebCore::operator<<):
* platform/calc/CalcOperator.h:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (282794 => 282795)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-09-21 00:24:50 UTC (rev 282795)
@@ -1,3 +1,14 @@
+2021-09-20  Nikos Mouchtaris  <[email protected]>
+
+        Implement exp,log functions calc functions
+        https://bugs.webkit.org/show_bug.cgi?id=229897
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/css/css-values/exp-log-compute.html: Added.
+        * web-platform-tests/css/css-values/exp-log-invalid.html: Added.
+        * web-platform-tests/css/css-values/exp-log-serialize.html: Added.
+
 2021-09-20  Youenn Fablet  <[email protected]>
 
         Make sure RTCRtpSender.setParameters returns an exception with a valid type

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute-expected.txt (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute-expected.txt	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,19 @@
+
+PASS log(1) should be used-value-equivalent to 0
+PASS log(10, 10) should be used-value-equivalent to 1
+PASS exp(0) should be used-value-equivalent to 1
+PASS calc(log(e) ) should be used-value-equivalent to 1
+PASS calc(e - exp(1)) should be used-value-equivalent to 0
+PASS calc(log( 1 + 1 + 2 /2 - 2) ) should be used-value-equivalent to 0
+PASS calc(log(1) + exp(0)) should be used-value-equivalent to 2
+PASS calc(exp(log(1) + exp(0)*2)) should be used-value-equivalent to 7.4
+PASS calc(log(log(1) + exp(0)*10)) should be used-value-equivalent to 2.3
+PASS calc(log(log(1) + exp(0)*20, 10)) should be used-value-equivalent to 1.3
+PASS calc(log(e)  / log(e) + exp(0)*2 * log(e)) should be used-value-equivalent to 3
+PASS calc(log((1 + 1) /2)  / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 2
+PASS calc(log((3 + 1) /2, 2)  / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 3
+PASS calc(log((3 + 1) /2, 2)  / log(e, e) + exp(0*1)*2 * log(e, e)) should be used-value-equivalent to 3
+PASS calc(exp(0) + 1) should be used-value-equivalent to 2
+PASS calc(log(exp(1))) should be used-value-equivalent to 1
+PASS calc(log(exp(log(e)))) should be used-value-equivalent to 1
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="author" title="Apple Inc">
+<script src=""
+<script src=""
+<script src=""
+<div id="target"></div>
+<script>
+// Simple tests
+test_math_used('log(1)', '0', {type:'number'});
+test_math_used('log(10, 10)', '1', {type:'number'});
+test_math_used('exp(0)', '1', {type:'number'});
+
+// Test e
+test_math_used('calc(log(e) )', '1', {type:'number', approx:0.1});
+test_math_used('calc(e - exp(1))', '0', {type:'number', approx:0.1});
+
+//General calculations
+test_math_used('calc(log( 1 + 1 + 2 /2 - 2) )', '0', {type:'number', approx:0.1});
+test_math_used('calc(log(1) + exp(0))', '2'), {type:'number', approx:0.1};
+test_math_used('calc(exp(log(1) + exp(0)*2))', '7.4'), {type:'number', approx:0.1};
+test_math_used('calc(log(log(1) + exp(0)*10))', '2.3'), {type:'number', approx:0.1};
+test_math_used('calc(log(log(1) + exp(0)*20, 10))', '1.3'), {type:'number', approx:0.1};
+test_math_used('calc(log(e)  / log(e) + exp(0)*2 * log(e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(log((1 + 1) /2)  / log(e) + exp(0*1)*2 * log(e))', '2', {type:'number', approx:0.1});
+test_math_used('calc(log((3 + 1) /2, 2)  / log(e) + exp(0*1)*2 * log(e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(log((3 + 1) /2, 2)  / log(e, e) + exp(0*1)*2 * log(e, e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(exp(0) + 1)', '2', {type:'number', approx:0.1});
+
+// Test nesting
+test_math_used('calc(log(exp(1)))', '1', {type:'number', approx:0.1});
+test_math_used('calc(log(exp(log(e))))', '1', {type:'number', approx:0.1});
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid-expected.txt (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid-expected.txt	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,50 @@
+
+PASS e.style['opacity'] = "exp()" should not set the property value
+PASS e.style['opacity'] = "exp( )" should not set the property value
+PASS e.style['opacity'] = "exp(,)" should not set the property value
+PASS e.style['opacity'] = "exp(1, )" should not set the property value
+PASS e.style['opacity'] = "exp(, 1)" should not set the property value
+PASS e.style['opacity'] = "exp(1 + )" should not set the property value
+PASS e.style['opacity'] = "exp(1 - )" should not set the property value
+PASS e.style['opacity'] = "exp(1 * )" should not set the property value
+PASS e.style['opacity'] = "exp(1 / )" should not set the property value
+PASS e.style['opacity'] = "exp(1 2)" should not set the property value
+PASS e.style['opacity'] = "exp(1, , 2)" should not set the property value
+PASS e.style['opacity'] = "log()" should not set the property value
+PASS e.style['opacity'] = "log( )" should not set the property value
+PASS e.style['opacity'] = "log(,)" should not set the property value
+PASS e.style['opacity'] = "log(1, )" should not set the property value
+PASS e.style['opacity'] = "log(, 1)" should not set the property value
+PASS e.style['opacity'] = "log(1 + )" should not set the property value
+PASS e.style['opacity'] = "log(1 - )" should not set the property value
+PASS e.style['opacity'] = "log(1 * )" should not set the property value
+PASS e.style['opacity'] = "log(1 / )" should not set the property value
+PASS e.style['opacity'] = "log(1 2)" should not set the property value
+PASS e.style['opacity'] = "log(1, , 2)" should not set the property value
+PASS e.style['opacity'] = "exp(0px)" should not set the property value
+PASS e.style['opacity'] = "exp(0s)" should not set the property value
+PASS e.style['opacity'] = "exp(0deg)" should not set the property value
+PASS e.style['opacity'] = "exp(0Hz)" should not set the property value
+PASS e.style['opacity'] = "exp(0dpi)" should not set the property value
+PASS e.style['opacity'] = "exp(0fr)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 1%)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0px)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0s)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0deg)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0Hz)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0dpi)" should not set the property value
+PASS e.style['opacity'] = "exp(1, 0fr)" should not set the property value
+PASS e.style['opacity'] = "log(0px)" should not set the property value
+PASS e.style['opacity'] = "log(0s)" should not set the property value
+PASS e.style['opacity'] = "log(0deg)" should not set the property value
+PASS e.style['opacity'] = "log(0Hz)" should not set the property value
+PASS e.style['opacity'] = "log(0dpi)" should not set the property value
+PASS e.style['opacity'] = "log(0fr)" should not set the property value
+PASS e.style['opacity'] = "log(1, 1%)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0px)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0s)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0deg)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0Hz)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0dpi)" should not set the property value
+PASS e.style['opacity'] = "log(1, 0fr)" should not set the property value
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="author" title="Apple Inc">
+<script src=""
+<script src=""
+<script src=""
+<script>
+function test_invalid_number(value) {
+  test_invalid_value('opacity', value);
+}
+
+// Syntax checking
+test_invalid_number('exp()');
+test_invalid_number('exp( )');
+test_invalid_number('exp(,)');
+test_invalid_number('exp(1, )');
+test_invalid_number('exp(, 1)');
+test_invalid_number('exp(1 + )');
+test_invalid_number('exp(1 - )');
+test_invalid_number('exp(1 * )');
+test_invalid_number('exp(1 / )');
+test_invalid_number('exp(1 2)');
+test_invalid_number('exp(1, , 2)');
+test_invalid_number('log()');
+test_invalid_number('log( )');
+test_invalid_number('log(,)');
+test_invalid_number('log(1, )');
+test_invalid_number('log(, 1)');
+test_invalid_number('log(1 + )');
+test_invalid_number('log(1 - )');
+test_invalid_number('log(1 * )');
+test_invalid_number('log(1 / )');
+test_invalid_number('log(1 2)');
+test_invalid_number('log(1, , 2)');
+
+// Type checking
+test_invalid_number('exp(0px)');
+test_invalid_number('exp(0s)');
+test_invalid_number('exp(0deg)');
+test_invalid_number('exp(0Hz)');
+test_invalid_number('exp(0dpi)');
+test_invalid_number('exp(0fr)');
+test_invalid_number('exp(1, 1%)');
+test_invalid_number('exp(1, 0px)');
+test_invalid_number('exp(1, 0s)');
+test_invalid_number('exp(1, 0deg)');
+test_invalid_number('exp(1, 0Hz)');
+test_invalid_number('exp(1, 0dpi)');
+test_invalid_number('exp(1, 0fr)');
+test_invalid_number('log(0px)');
+test_invalid_number('log(0s)');
+test_invalid_number('log(0deg)');
+test_invalid_number('log(0Hz)');
+test_invalid_number('log(0dpi)');
+test_invalid_number('log(0fr)');
+test_invalid_number('log(1, 1%)');
+test_invalid_number('log(1, 0px)');
+test_invalid_number('log(1, 0s)');
+test_invalid_number('log(1, 0deg)');
+test_invalid_number('log(1, 0Hz)');
+test_invalid_number('log(1, 0dpi)');
+test_invalid_number('log(1, 0fr)');
+</script>

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize-expected.txt (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize-expected.txt	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,18 @@
+
+FAIL 'exp(0)' as a specified value should serialize as 'calc(1)'. assert_equals: 'exp(0)' and 'calc(1)' should serialize the same in specified values. expected "calc(1)" but got "exp(0)"
+FAIL 'scale(exp(0))' as a specified value should serialize as 'scale(calc(1))'. assert_equals: 'scale(exp(0))' and 'scale(calc(1))' should serialize the same in specified values. expected "scale(calc(1))" but got "scale(exp(0))"
+PASS 'exp(0)' as a computed value should serialize as '1'.
+PASS 'scale(exp(0))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
+FAIL 'log(1)' as a specified value should serialize as 'calc(0)'. assert_equals: 'log(1)' and 'calc(0)' should serialize the same in specified values. expected "calc(0)" but got "log(1)"
+FAIL 'scale(log(1))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(log(1))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(log(1))"
+PASS 'log(1)' as a computed value should serialize as '0'.
+PASS 'scale(log(1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'.
+PASS 'calc(exp(0) + log(1) + log(1))' as a specified value should serialize as 'calc(1)'.
+PASS 'scale(calc(exp(0) + log(1) + log(1)))' as a specified value should serialize as 'scale(calc(1))'.
+PASS 'calc(exp(0) + log(1) + log(1))' as a computed value should serialize as '1'.
+PASS 'scale(calc(exp(0) + log(1) + log(1)))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
+PASS 'calc(log(1) + 0.5)' as a specified value should serialize as 'calc(0.5)'.
+PASS 'scale(calc(log(1) + 0.5))' as a specified value should serialize as 'scale(calc(0.5))'.
+PASS 'calc(log(1) + 0.5)' as a computed value should serialize as '0.5'.
+PASS 'scale(calc(log(1) + 0.5))' as a computed value should serialize as 'matrix(0.5, 0, 0, 0.5, 0, 0)'.
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html (0 => 282795)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html	2021-09-21 00:24:50 UTC (rev 282795)
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="author" title="Apple Inc">
+<script src=""
+<script src=""
+<script src=""
+<div id=target></div>
+<script>
+function test_serialization(t,s,c) {
+    test_specified_serialization('opacity', t, s);
+    test_specified_serialization('transform', `scale(${t})`, `scale(${s})`);
+    test_computed_serialization('opacity', t, c);
+    test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`);
+}
+
+test_serialization(
+    'exp(0)',
+    'calc(1)',
+    '1');
+test_serialization(
+    'log(1)',
+    'calc(0)',
+    '0');
+
+test_serialization(
+    'calc(exp(0) + log(1) + log(1))',
+    'calc(1)',
+    '1');
+
+test_serialization(
+    'calc(log(1) + 0.5)',
+    'calc(0.5)',
+    '0.5');
+</script>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (282794 => 282795)


--- trunk/Source/WebCore/ChangeLog	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/ChangeLog	2021-09-21 00:24:50 UTC (rev 282795)
@@ -1,3 +1,40 @@
+2021-09-20  Nikos Mouchtaris  <[email protected]>
+
+        Implement exp,log functions calc functions
+        https://bugs.webkit.org/show_bug.cgi?id=229897
+
+        Reviewed by Simon Fraser.
+
+        Added support for calc functions exp and log. Involved adding exp and log CSS keywords and handling
+        for parsing these functions and their arguments as well as computing the result based on the arguments.
+        Spec for these functions: https://drafts.csswg.org/css-values-4/#exponent-funcs. 
+
+        Tests: imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html
+               imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html
+               imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html
+
+        * css/CSSValueKeywords.in:
+        * css/calc/CSSCalcExpressionNodeParser.cpp:
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
+        * css/calc/CSSCalcOperationNode.cpp:
+        (WebCore::determineCategory):
+        (WebCore::functionFromOperator):
+        (WebCore::CSSCalcOperationNode::createLog):
+        (WebCore::CSSCalcOperationNode::createExp):
+        (WebCore::CSSCalcOperationNode::combineChildren):
+        (WebCore::CSSCalcOperationNode::simplifyNode):
+        (WebCore::functionPrefixForOperator):
+        (WebCore::CSSCalcOperationNode::evaluateOperator):
+        * css/calc/CSSCalcOperationNode.h:
+        * css/calc/CSSCalcValue.cpp:
+        (WebCore::createCSS):
+        (WebCore::CSSCalcValue::isCalcFunction):
+        * platform/calc/CalcExpressionOperation.cpp:
+        (WebCore::CalcExpressionOperation::evaluate const):
+        * platform/calc/CalcOperator.cpp:
+        (WebCore::operator<<):
+        * platform/calc/CalcOperator.h:
+
 2021-09-20  Ross Kirsling  <[email protected]>
 
         Unreviewed build fix for WinCairo with ENABLE_EXPERIMENTAL_FEATURES off.

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (282794 => 282795)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-21 00:24:50 UTC (rev 282795)
@@ -1351,6 +1351,8 @@
 cos
 e
 pi
+exp
+log
 
 from-image
 

Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (282794 => 282795)


--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-21 00:24:50 UTC (rev 282795)
@@ -129,6 +129,11 @@
         minArgumentCount = 3;
         maxArgumentCount = 3;
         break;
+
+    case CSSValueLog:
+        maxArgumentCount = 2;
+        break;
+    case CSSValueExp:
     case CSSValueSin:
     case CSSValueCos:
     case CSSValueTan:
@@ -187,6 +192,12 @@
     case CSSValueCalc:
         result = CSSCalcOperationNode::createSum(WTFMove(nodes));
         break;
+    case CSSValueLog:
+        result = CSSCalcOperationNode::createLog(WTFMove(nodes));
+        break;
+    case CSSValueExp:
+        result = CSSCalcOperationNode::createExp(WTFMove(nodes));
+        break;
     // TODO: clamp, sin, cos, tan, asin, acos, atan, atan2, pow, sqrt, hypot
     default:
         break;

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp (282794 => 282795)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-21 00:24:50 UTC (rev 282795)
@@ -79,6 +79,8 @@
     case CalcOperator::Min:
     case CalcOperator::Max:
     case CalcOperator::Clamp:
+    case CalcOperator::Log:
+    case CalcOperator::Exp:
         ASSERT_NOT_REACHED();
         return CalculationCategory::Other;
     }
@@ -150,6 +152,8 @@
         case CalcOperator::Min:
         case CalcOperator::Max:
         case CalcOperator::Clamp:
+        case CalcOperator::Log:
+        case CalcOperator::Exp:
             // The type of a min(), max(), or clamp() _expression_ is the result of adding the types of its comma-separated calculations
             return CalculationCategory::Other;
         }
@@ -267,6 +271,10 @@
         return CSSValueCos;
     case CalcOperator::Tan:
         return CSSValueTan;
+    case CalcOperator::Exp:
+        return CSSValueExp;
+    case CalcOperator::Log:
+        return CSSValueLog;
     }
     return CSSValueCalc;
 }
@@ -319,6 +327,40 @@
     return adoptRef(new CSSCalcOperationNode(newCategory, CalcOperator::Multiply, WTFMove(values)));
 }
 
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createLog(Vector<Ref<CSSCalcExpressionNode>>&& values)
+{
+    if (values.size() != 1 && values.size() != 2)
+        return nullptr;
+    for (auto& value : values) {
+        // TODO: Support infinity
+        if (value->category() != CalculationCategory::Number || !value->doubleValue(value->primitiveType())) {
+            LOG_WITH_STREAM(Calc, stream << "Failed to create log node because unable to determine category from " << prettyPrintNodes(values));
+            return nullptr;
+        }
+    }
+    
+    // TODO: Support infinity
+    if ((values.size() == 2 && values[1]->doubleValue(values[1]->primitiveType()) == 1)) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create log node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+
+    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, CalcOperator::Log, WTFMove(values)));
+}
+
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createExp(Vector<Ref<CSSCalcExpressionNode>>&& values)
+{
+    if (values.size() != 1)
+        return nullptr;
+
+    if (values[0]->category() != CalculationCategory::Number) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create exp node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+
+    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, CalcOperator::Exp, WTFMove(values)));
+}
+
 RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createMinOrMaxOrClamp(CalcOperator op, Vector<Ref<CSSCalcExpressionNode>>&& values, CalculationCategory destinationCategory)
 {
     ASSERT(op == CalcOperator::Min || op == CalcOperator::Max || op == CalcOperator::Clamp);
@@ -435,6 +477,13 @@
         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));
+        }
+        
+        if (isExpNode()) {
+            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));
@@ -630,7 +679,7 @@
     if (is<CSSCalcOperationNode>(rootNode)) {
         auto& calcOperationNode = downcast<CSSCalcOperationNode>(rootNode.get());
         // 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())
+        if (calcOperationNode.children().size() == 1 && depth && !calcOperationNode.isTrigNode() && !calcOperationNode.isExpNode())
             return WTFMove(calcOperationNode.children()[0]);
         
         if (calcOperationNode.isCalcSumNode()) {
@@ -649,6 +698,9 @@
         if (calcOperationNode.isTrigNode() && depth)
             calcOperationNode.combineChildren();
         
+        if (calcOperationNode.isExpNode() && depth)
+            calcOperationNode.combineChildren();
+        
         // If only one child remains, return the child (except at the root).
         auto shouldCombineParentWithOnlyChild = [](const CSSCalcOperationNode& parent, int depth)
         {
@@ -840,6 +892,8 @@
     case CalcOperator::Min: return "min(";
     case CalcOperator::Max: return "max(";
     case CalcOperator::Clamp: return "clamp(";
+    case CalcOperator::Exp: return "exp(";
+    case CalcOperator::Log: return "log(";
     }
     
     return "";
@@ -1056,7 +1110,19 @@
             return std::numeric_limits<double>::quiet_NaN();
         return std::tan(children[0]);
     }
+    case CalcOperator::Log: {
+        if (children.size() != 1 && children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        if (children.size() == 1)
+            return std::log(children[0]);
+        return std::log(children[0]) / std::log(children[1]);
     }
+    case CalcOperator::Exp: {
+        if (children.size() != 1)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::exp(children[0]);
+    }
+    }
     ASSERT_NOT_REACHED();
     return 0;
 }

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h (282794 => 282795)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-21 00:24:50 UTC (rev 282795)
@@ -38,6 +38,8 @@
     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 RefPtr<CSSCalcOperationNode> createLog(Vector<Ref<CSSCalcExpressionNode>>&& values);
+    static RefPtr<CSSCalcOperationNode> createExp(Vector<Ref<CSSCalcExpressionNode>>&& values);
 
     static Ref<CSSCalcExpressionNode> simplify(Ref<CSSCalcExpressionNode>&&);
 
@@ -48,6 +50,7 @@
     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 isExpNode() const { return m_operator == CalcOperator::Exp || m_operator == CalcOperator::Log; }
     bool shouldSortChildren() const { return isCalcSumNode() || isCalcProductNode(); }
 
     void hoistChildrenWithOperator(CalcOperator);

Modified: trunk/Source/WebCore/css/calc/CSSCalcValue.cpp (282794 => 282795)


--- trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-21 00:24:50 UTC (rev 282795)
@@ -180,7 +180,19 @@
                 return nullptr;
             return CSSCalcOperationNode::createMinOrMaxOrClamp(op, WTFMove(children), operationNode.destinationCategory());
         }
+        case CalcOperator::Log: {
+            auto children = createCSS(operationChildren, style);
+            if (children.size() != 1 && children.size() != 2)
+                return nullptr;
+            return CSSCalcOperationNode::createLog(WTFMove(children));
         }
+        case CalcOperator::Exp: {
+            auto children = createCSS(operationChildren, style);
+            if (children.size() != 1)
+                return nullptr;
+            return CSSCalcOperationNode::createExp(WTFMove(children));
+        }
+        }
         return nullptr;
     }
     case CalcExpressionNodeType::BlendLength: {
@@ -294,6 +306,8 @@
     case CSSValueSin:
     case CSSValueCos:
     case CSSValueTan:
+    case CSSValueExp:
+    case CSSValueLog:
         return true;
     default:
         return false;

Modified: trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp (282794 => 282795)


--- trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-21 00:24:50 UTC (rev 282795)
@@ -102,7 +102,19 @@
             return std::numeric_limits<double>::quiet_NaN();
         return std::tan(m_children[0]->evaluate(maxValue));
     }
+    case CalcOperator::Log: {
+        if (m_children.size() != 1 && m_children.size() != 2)
+            return std::numeric_limits<float>::quiet_NaN();
+        if (m_children.size() == 1)
+            return std::log(m_children[0]->evaluate(maxValue));
+        return std::log(m_children[0]->evaluate(maxValue)) / std::log(m_children[1]->evaluate(maxValue));
     }
+    case CalcOperator::Exp: {
+        if (m_children.size() != 1)
+            return std::numeric_limits<float>::quiet_NaN();
+        return std::exp(m_children[0]->evaluate(maxValue));
+    }
+    }
     ASSERT_NOT_REACHED();
     return std::numeric_limits<float>::quiet_NaN();
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.cpp (282794 => 282795)


--- trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-21 00:24:50 UTC (rev 282795)
@@ -43,6 +43,8 @@
     case CalcOperator::Sin: ts << "sin"; break;
     case CalcOperator::Cos: ts << "cos"; break;
     case CalcOperator::Tan: ts << "tan"; break;
+    case CalcOperator::Exp: ts << "exp"; break;
+    case CalcOperator::Log: ts << "log"; break;
     }
     return ts;
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.h (282794 => 282795)


--- trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-21 00:14:38 UTC (rev 282794)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-21 00:24:50 UTC (rev 282795)
@@ -41,6 +41,8 @@
     Sin,
     Cos,
     Tan,
+    Exp,
+    Log,
 };
 
 TextStream& operator<<(TextStream&, CalcOperator);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to