Title: [283073] trunk
Revision
283073
Author
commit-qu...@webkit.org
Date
2021-09-24 22:03:08 -0700 (Fri, 24 Sep 2021)

Log Message

Implement round,mod,rem functions for calc
https://bugs.webkit.org/show_bug.cgi?id=230073

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

LayoutTests/imported/w3c:

* web-platform-tests/css/css-values/round-function-expected.txt:
* web-platform-tests/css/css-values/round-mod-rem-computed-expected.txt: Added.
* web-platform-tests/css/css-values/round-mod-rem-computed.html: Added.
* web-platform-tests/css/css-values/round-mod-rem-invalid-expected.txt: Added.
* web-platform-tests/css/css-values/round-mod-rem-invalid.html: Added.
* web-platform-tests/css/css-values/round-mod-rem-serialize-expected.txt: Added.
* web-platform-tests/css/css-values/round-mod-rem-serialize.html: Added.
* web-platform-tests/css/support/numeric-testcommon.js:

Source/WebCore:

Implemented round, mod and rem calc functions. Involved adding css keywords for the functions
and the keywords associated with the round function, as well as implementing the parsing and
computation of the _expression_. The spec for these functions:
https://drafts.csswg.org/css-values-4/#round-func.

Tests: imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed.html
       imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid.html
       imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize.html

* css/CSSValueKeywords.in:
* css/calc/CSSCalcExpressionNodeParser.cpp:
(WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
(WebCore::checkRoundKeyword):
Addition of functionID to parsing so the round keywords are only parsed within round
function.
(WebCore::CSSCalcExpressionNodeParser::parseValue):
(WebCore::CSSCalcExpressionNodeParser::parseCalcValue):
(WebCore::CSSCalcExpressionNodeParser::parseCalcProduct):
(WebCore::CSSCalcExpressionNodeParser::parseCalcSum):
* css/calc/CSSCalcExpressionNodeParser.h:
* css/calc/CSSCalcOperationNode.cpp:
(WebCore::determineCategory):
(WebCore::functionFromOperator):
(WebCore::CSSCalcOperationNode::createStep):
(WebCore::validateRoundChildren):
(WebCore::CSSCalcOperationNode::createRound):
(WebCore::CSSCalcOperationNode::createRoundConstant):
(WebCore::CSSCalcOperationNode::combineChildren):
(WebCore::CSSCalcOperationNode::simplifyNode):
(WebCore::functionPrefixForOperator):
(WebCore::getNearestMultiples):
(WebCore::CSSCalcOperationNode::evaluateOperator):
* css/calc/CSSCalcOperationNode.h:
* css/calc/CSSCalcValue.cpp:
(WebCore::createCSS):
(WebCore::CSSCalcValue::isCalcFunction):
* platform/calc/CalcExpressionOperation.cpp:
(WebCore::getNearestMultiples):
(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 (283072 => 283073)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-09-25 05:03:08 UTC (rev 283073)
@@ -1,5 +1,21 @@
 2021-09-24  Nikos Mouchtaris  <nmouchta...@apple.com>
 
+        Implement round,mod,rem functions for calc
+        https://bugs.webkit.org/show_bug.cgi?id=230073
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/css/css-values/round-function-expected.txt:
+        * web-platform-tests/css/css-values/round-mod-rem-computed-expected.txt: Added.
+        * web-platform-tests/css/css-values/round-mod-rem-computed.html: Added.
+        * web-platform-tests/css/css-values/round-mod-rem-invalid-expected.txt: Added.
+        * web-platform-tests/css/css-values/round-mod-rem-invalid.html: Added.
+        * web-platform-tests/css/css-values/round-mod-rem-serialize-expected.txt: Added.
+        * web-platform-tests/css/css-values/round-mod-rem-serialize.html: Added.
+        * web-platform-tests/css/support/numeric-testcommon.js:
+
+2021-09-24  Nikos Mouchtaris  <nmouchta...@apple.com>
+
         Implement abs,sign calc functions
         https://bugs.webkit.org/show_bug.cgi?id=229786
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt (283072 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt	2021-09-25 05:03:08 UTC (rev 283073)
@@ -1,40 +1,40 @@
 
-FAIL round(23px, 10px) should be used-value-equivalent to 20px assert_equals: round(23px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(18px, 10px) should be used-value-equivalent to 20px assert_equals: round(18px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(15px, 10px) should be used-value-equivalent to 20px assert_equals: round(15px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(13px, 10px) should be used-value-equivalent to 10px assert_equals: round(13px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(-13px, 10px) should be used-value-equivalent to -10px assert_equals: round(-13px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(-18px, 10px) should be used-value-equivalent to -20px assert_equals: round(-18px, 10px) and -20px serialize to the same thing in used values. expected "-20px" but got "0px"
-FAIL round(nearest, 23px, 10px) should be used-value-equivalent to 20px assert_equals: round(nearest, 23px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(nearest, 18px, 10px) should be used-value-equivalent to 20px assert_equals: round(nearest, 18px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(nearest, 15px, 10px) should be used-value-equivalent to 20px assert_equals: round(nearest, 15px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(nearest, 13px, 10px) should be used-value-equivalent to 10px assert_equals: round(nearest, 13px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(nearest, -13px, 10px) should be used-value-equivalent to -10px assert_equals: round(nearest, -13px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(nearest, -18px, 10px) should be used-value-equivalent to -20px assert_equals: round(nearest, -18px, 10px) and -20px serialize to the same thing in used values. expected "-20px" but got "0px"
-FAIL round(down, 23px, 10px) should be used-value-equivalent to 20px assert_equals: round(down, 23px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(down, 18px, 10px) should be used-value-equivalent to 10px assert_equals: round(down, 18px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(down, 15px, 10px) should be used-value-equivalent to 10px assert_equals: round(down, 15px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(down, 13px, 10px) should be used-value-equivalent to 10px assert_equals: round(down, 13px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(down, -13px, 10px) should be used-value-equivalent to -20px assert_equals: round(down, -13px, 10px) and -20px serialize to the same thing in used values. expected "-20px" but got "0px"
-FAIL round(down, -18px, 10px) should be used-value-equivalent to -20px assert_equals: round(down, -18px, 10px) and -20px serialize to the same thing in used values. expected "-20px" but got "0px"
-FAIL round(up, 23px, 10px) should be used-value-equivalent to 30px assert_equals: round(up, 23px, 10px) and 30px serialize to the same thing in used values. expected "30px" but got "0px"
-FAIL round(up, 18px, 10px) should be used-value-equivalent to 20px assert_equals: round(up, 18px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(up, 15px, 10px) should be used-value-equivalent to 20px assert_equals: round(up, 15px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(up, 13px, 10px) should be used-value-equivalent to 20px assert_equals: round(up, 13px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(up, -13px, 10px) should be used-value-equivalent to -10px assert_equals: round(up, -13px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(up, -18px, 10px) should be used-value-equivalent to -10px assert_equals: round(up, -18px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(to-zero, 23px, 10px) should be used-value-equivalent to 20px assert_equals: round(to-zero, 23px, 10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(to-zero, 18px, 10px) should be used-value-equivalent to 10px assert_equals: round(to-zero, 18px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(to-zero, 15px, 10px) should be used-value-equivalent to 10px assert_equals: round(to-zero, 15px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(to-zero, 13px, 10px) should be used-value-equivalent to 10px assert_equals: round(to-zero, 13px, 10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(to-zero, -13px, 10px) should be used-value-equivalent to -10px assert_equals: round(to-zero, -13px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(to-zero, -18px, 10px) should be used-value-equivalent to -10px assert_equals: round(to-zero, -18px, 10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(23px, -10px) should be used-value-equivalent to 20px assert_equals: round(23px, -10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(18px, -10px) should be used-value-equivalent to 20px assert_equals: round(18px, -10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(15px, -10px) should be used-value-equivalent to 20px assert_equals: round(15px, -10px) and 20px serialize to the same thing in used values. expected "20px" but got "0px"
-FAIL round(13px, -10px) should be used-value-equivalent to 10px assert_equals: round(13px, -10px) and 10px serialize to the same thing in used values. expected "10px" but got "0px"
-FAIL round(-13px, -10px) should be used-value-equivalent to -10px assert_equals: round(-13px, -10px) and -10px serialize to the same thing in used values. expected "-10px" but got "0px"
-FAIL round(-18px, -10px) should be used-value-equivalent to -20px assert_equals: round(-18px, -10px) and -20px serialize to the same thing in used values. expected "-20px" but got "0px"
+PASS round(23px, 10px) should be used-value-equivalent to 20px
+PASS round(18px, 10px) should be used-value-equivalent to 20px
+PASS round(15px, 10px) should be used-value-equivalent to 20px
+PASS round(13px, 10px) should be used-value-equivalent to 10px
+PASS round(-13px, 10px) should be used-value-equivalent to -10px
+PASS round(-18px, 10px) should be used-value-equivalent to -20px
+PASS round(nearest, 23px, 10px) should be used-value-equivalent to 20px
+PASS round(nearest, 18px, 10px) should be used-value-equivalent to 20px
+PASS round(nearest, 15px, 10px) should be used-value-equivalent to 20px
+PASS round(nearest, 13px, 10px) should be used-value-equivalent to 10px
+PASS round(nearest, -13px, 10px) should be used-value-equivalent to -10px
+PASS round(nearest, -18px, 10px) should be used-value-equivalent to -20px
+PASS round(down, 23px, 10px) should be used-value-equivalent to 20px
+PASS round(down, 18px, 10px) should be used-value-equivalent to 10px
+PASS round(down, 15px, 10px) should be used-value-equivalent to 10px
+PASS round(down, 13px, 10px) should be used-value-equivalent to 10px
+PASS round(down, -13px, 10px) should be used-value-equivalent to -20px
+PASS round(down, -18px, 10px) should be used-value-equivalent to -20px
+PASS round(up, 23px, 10px) should be used-value-equivalent to 30px
+PASS round(up, 18px, 10px) should be used-value-equivalent to 20px
+PASS round(up, 15px, 10px) should be used-value-equivalent to 20px
+PASS round(up, 13px, 10px) should be used-value-equivalent to 20px
+PASS round(up, -13px, 10px) should be used-value-equivalent to -10px
+PASS round(up, -18px, 10px) should be used-value-equivalent to -10px
+PASS round(to-zero, 23px, 10px) should be used-value-equivalent to 20px
+PASS round(to-zero, 18px, 10px) should be used-value-equivalent to 10px
+PASS round(to-zero, 15px, 10px) should be used-value-equivalent to 10px
+PASS round(to-zero, 13px, 10px) should be used-value-equivalent to 10px
+PASS round(to-zero, -13px, 10px) should be used-value-equivalent to -10px
+PASS round(to-zero, -18px, 10px) should be used-value-equivalent to -10px
+PASS round(23px, -10px) should be used-value-equivalent to 20px
+PASS round(18px, -10px) should be used-value-equivalent to 20px
+PASS round(15px, -10px) should be used-value-equivalent to 20px
+PASS round(13px, -10px) should be used-value-equivalent to 10px
+PASS round(-13px, -10px) should be used-value-equivalent to -10px
+PASS round(-18px, -10px) should be used-value-equivalent to -20px
 PASS round(5, 0) should be used-value-equivalent to calc(NaN)
 PASS calc(-1 * round(5, 0)) should be used-value-equivalent to calc(NaN)
 PASS round(infinity, infinity) should be used-value-equivalent to calc(NaN)

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed-expected.txt (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed-expected.txt	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,91 @@
+
+PASS round(10,10) should be used-value-equivalent to 10
+PASS mod(1,1) should be used-value-equivalent to 0
+PASS rem(1,1) should be used-value-equivalent to 0
+PASS calc(round(100,10)) should be used-value-equivalent to 100
+PASS calc(round(up, 101,10)) should be used-value-equivalent to 110
+PASS calc(round(down, 106,10)) should be used-value-equivalent to 100
+PASS calc(round(to-zero,105, 10)) should be used-value-equivalent to 100
+PASS calc(round(to-zero,-105, 10)) should be used-value-equivalent to -100
+PASS calc(round(-100,10)) should be used-value-equivalent to -100
+PASS calc(round(up, -103,10)) should be used-value-equivalent to -100
+PASS mod(18,5) should be used-value-equivalent to 3
+PASS rem(18,5) should be used-value-equivalent to 3
+PASS mod(-140,-90) should be used-value-equivalent to -50
+PASS mod(-18,5) should be used-value-equivalent to 2
+PASS rem(-18,5) should be used-value-equivalent to -3
+PASS mod(140,-90) should be used-value-equivalent to -40
+PASS rem(140,-90) should be used-value-equivalent to 50
+PASS calc(round(round(100,10), 10)) should be used-value-equivalent to 100
+PASS calc(round(up, round(100,10) + 1,10)) should be used-value-equivalent to 110
+PASS calc(round(down, round(100,10) + 2 * 3,10)) should be used-value-equivalent to 100
+PASS calc(round(to-zero,round(100,10) * 2 - 95, 10)) should be used-value-equivalent to 100
+PASS calc(round(round(100,10)* -1,10)) should be used-value-equivalent to -100
+PASS calc(round(up, -103 + -103 / -103 - 1,10)) should be used-value-equivalent to -100
+PASS calc(mod(18,5) * 2 + mod(17,5)) should be used-value-equivalent to 8
+PASS calc(rem(mod(18,5),5)) should be used-value-equivalent to 3
+PASS calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1
+PASS calc(mod(-140,-90)) should be used-value-equivalent to -50
+PASS calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to -1
+PASS round(10px,6px) should be used-value-equivalent to 12px
+PASS round(10cm,6cm) should be used-value-equivalent to 12cm
+PASS round(10mm,6mm) should be used-value-equivalent to 12mm
+PASS round(10Q, 6Q) should be used-value-equivalent to 12Q
+PASS round(10in,6in) should be used-value-equivalent to 12in
+PASS round(10pc,6pc) should be used-value-equivalent to 12pc
+PASS round(10pt,6pt) should be used-value-equivalent to 12pt
+PASS round(10em,6em) should be used-value-equivalent to 12em
+PASS round(10ex,6ex) should be used-value-equivalent to 12ex
+PASS round(10ch,6ch) should be used-value-equivalent to 12ch
+PASS round(10rem,6rem) should be used-value-equivalent to 12rem
+PASS round(10vh,6vh) should be used-value-equivalent to 12vh
+PASS round(10vw,6vw) should be used-value-equivalent to 12vw
+PASS round(10vmin,6vmin) should be used-value-equivalent to 12vmin
+PASS round(10vmax,6vmax) should be used-value-equivalent to 12vmax
+PASS round(10s,6s) should be used-value-equivalent to 12s
+PASS round(10ms,6ms) should be used-value-equivalent to 12ms
+PASS round(10deg,6deg) should be used-value-equivalent to 12deg
+PASS round(10grad,6grad) should be used-value-equivalent to 12grad
+PASS round(10rad,6rad) should be used-value-equivalent to 12rad
+PASS round(10turn,6turn) should be used-value-equivalent to 12turn
+PASS mod(10px,6px) should be used-value-equivalent to 4px
+PASS mod(10cm,6cm) should be used-value-equivalent to 4cm
+PASS mod(10mm,6mm) should be used-value-equivalent to 4mm
+PASS mod(10Q, 6Q) should be used-value-equivalent to 4Q
+PASS mod(10in,6in) should be used-value-equivalent to 4in
+PASS mod(10pc,6pc) should be used-value-equivalent to 4pc
+PASS mod(10em,6em) should be used-value-equivalent to 4em
+PASS mod(10ex,6ex) should be used-value-equivalent to 4ex
+PASS mod(10ch,6ch) should be used-value-equivalent to 4ch
+PASS mod(10rem,6rem) should be used-value-equivalent to 4rem
+PASS mod(10vh,6vh) should be used-value-equivalent to 4vh
+PASS mod(10vw,6vw) should be used-value-equivalent to 4vw
+PASS mod(10vmin,6vmin) should be used-value-equivalent to 4vmin
+PASS mod(10vmax,6vmax) should be used-value-equivalent to 4vmax
+PASS mod(10s,6s) should be used-value-equivalent to 4s
+PASS mod(10ms,6ms) should be used-value-equivalent to 4ms
+PASS mod(10deg,6deg) should be used-value-equivalent to 4deg
+PASS mod(10grad,6grad) should be used-value-equivalent to 4grad
+PASS mod(10rad,6rad) should be used-value-equivalent to 4rad
+PASS mod(10turn,6turn) should be used-value-equivalent to 4turn
+PASS rem(10px,6px) should be used-value-equivalent to 4px
+PASS rem(10cm,6cm) should be used-value-equivalent to 4cm
+PASS rem(10mm,6mm) should be used-value-equivalent to 4mm
+PASS rem(10Q, 6Q) should be used-value-equivalent to 4Q
+PASS rem(10in,6in) should be used-value-equivalent to 4in
+PASS rem(10pc,6pc) should be used-value-equivalent to 4pc
+PASS rem(10em,6em) should be used-value-equivalent to 4em
+PASS rem(10ex,6ex) should be used-value-equivalent to 4ex
+PASS rem(10ch,6ch) should be used-value-equivalent to 4ch
+PASS rem(10rem,6rem) should be used-value-equivalent to 4rem
+PASS rem(10vh,6vh) should be used-value-equivalent to 4vh
+PASS rem(10vw,6vw) should be used-value-equivalent to 4vw
+PASS rem(10vmin,6vmin) should be used-value-equivalent to 4vmin
+PASS rem(10vmax,6vmax) should be used-value-equivalent to 4vmax
+PASS rem(10s,6s) should be used-value-equivalent to 4s
+PASS rem(10ms,6ms) should be used-value-equivalent to 4ms
+PASS rem(10deg,6deg) should be used-value-equivalent to 4deg
+PASS rem(10grad,6grad) should be used-value-equivalent to 4grad
+PASS rem(10rad,6rad) should be used-value-equivalent to 4rad
+PASS rem(10turn,6turn) should be used-value-equivalent to 4turn
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed.html (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed.html	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,111 @@
+<!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('round(10,10)', '10', {type:'number'});
+test_math_used('mod(1,1)', '0', {type:'number'});
+test_math_used('rem(1,1)', '0', {type:'number'});
+
+//Test basic round
+test_math_used('calc(round(100,10))', '100', {type:'number'});
+test_math_used('calc(round(up, 101,10))', '110', {type:'number'});
+test_math_used('calc(round(down, 106,10))', '100', {type:'number'});
+test_math_used('calc(round(to-zero,105, 10))', '100', {type:'number'});
+test_math_used('calc(round(to-zero,-105, 10))', '-100', {type:'number'});
+test_math_used('calc(round(-100,10))', '-100', {type:'number'});
+test_math_used('calc(round(up, -103,10))', '-100', {type:'number'});
+
+//Test basic mod/rem
+test_math_used('mod(18,5)', '3', {type:'number'});
+test_math_used('rem(18,5)', '3', {type:'number'});
+test_math_used('mod(-140,-90)', '-50', {type:'number'});
+test_math_used('mod(-18,5)', '2', {type:'number'});
+test_math_used('rem(-18,5)', '-3', {type:'number'});
+test_math_used('mod(140,-90)', '-40', {type:'number'});
+test_math_used('rem(140,-90)', '50', {type:'number'});
+
+//Test basic calculations
+test_math_used('calc(round(round(100,10), 10))', '100', {type:'number'});
+test_math_used('calc(round(up, round(100,10) + 1,10))', '110', {type:'number'});
+test_math_used('calc(round(down, round(100,10) + 2 * 3,10))', '100', {type:'number'});
+test_math_used('calc(round(to-zero,round(100,10) * 2 - 95, 10))', '100', {type:'number'});
+test_math_used('calc(round(round(100,10)* -1,10))', '-100', {type:'number'});
+test_math_used('calc(round(up, -103 + -103 / -103 - 1,10))', '-100', {type:'number'});
+test_math_used('calc(mod(18,5) * 2 + mod(17,5))', '8', {type:'number'});
+test_math_used('calc(rem(mod(18,5),5))', '3', {type:'number'});
+test_math_used('calc(rem(mod(18,5),mod(17,5)))', '1', {type:'number'});
+test_math_used('calc(mod(-140,-90))', '-50', {type:'number'});
+test_math_used('calc(mod(rem(1,18)* -1,5))', '-1', {type:'number'});
+
+// Type check
+test_math_used('round(10px,6px)', '12px');
+test_math_used('round(10cm,6cm)', '12cm');
+test_math_used('round(10mm,6mm)', '12mm');
+test_math_used('round(10Q, 6Q)', '12Q');
+test_math_used('round(10in,6in)', '12in');
+test_math_used('round(10pc,6pc)', '12pc');
+test_math_used('round(10pt,6pt)', '12pt');
+test_math_used('round(10em,6em)', '12em');
+test_math_used('round(10ex,6ex)', '12ex');
+test_math_used('round(10ch,6ch)', '12ch');
+test_math_used('round(10rem,6rem)', '12rem');
+test_math_used('round(10vh,6vh)', '12vh');
+test_math_used('round(10vw,6vw)', '12vw');
+test_math_used('round(10vmin,6vmin)', '12vmin');
+test_math_used('round(10vmax,6vmax)', '12vmax');
+test_math_used('round(10s,6s)', '12s');
+test_math_used('round(10ms,6ms)', '12ms');
+test_math_used('round(10deg,6deg)', '12deg', {type:'angle', approx:0.1});
+test_math_used('round(10grad,6grad)', '12grad', {type:'angle', approx:0.1});
+test_math_used('round(10rad,6rad)', '12rad',{type:'angle', approx:0.1});
+test_math_used('round(10turn,6turn)', '12turn',{type:'angle', approx:0.1});
+
+test_math_used('mod(10px,6px)', '4px');
+test_math_used('mod(10cm,6cm)', '4cm');
+test_math_used('mod(10mm,6mm)', '4mm');
+test_math_used('mod(10Q, 6Q)', '4Q');
+test_math_used('mod(10in,6in)', '4in');
+test_math_used('mod(10pc,6pc)', '4pc');
+test_math_used('mod(10em,6em)', '4em');
+test_math_used('mod(10ex,6ex)', '4ex');
+test_math_used('mod(10ch,6ch)', '4ch');
+test_math_used('mod(10rem,6rem)', '4rem');
+test_math_used('mod(10vh,6vh)', '4vh');
+test_math_used('mod(10vw,6vw)', '4vw');
+test_math_used('mod(10vmin,6vmin)', '4vmin');
+test_math_used('mod(10vmax,6vmax)', '4vmax');
+test_math_used('mod(10s,6s)', '4s');
+test_math_used('mod(10ms,6ms)', '4ms');
+test_math_used('mod(10deg,6deg)', '4deg', {type:'angle', approx:0.1});
+test_math_used('mod(10grad,6grad)', '4grad', {type:'angle', approx:0.1});
+test_math_used('mod(10rad,6rad)', '4rad',{type:'angle', approx:0.1});
+test_math_used('mod(10turn,6turn)', '4turn',{type:'angle', approx:0.1});
+
+test_math_used('rem(10px,6px)', '4px');
+test_math_used('rem(10cm,6cm)', '4cm');
+test_math_used('rem(10mm,6mm)', '4mm');
+test_math_used('rem(10Q, 6Q)', '4Q');
+test_math_used('rem(10in,6in)', '4in');
+test_math_used('rem(10pc,6pc)', '4pc');
+test_math_used('rem(10em,6em)', '4em');
+test_math_used('rem(10ex,6ex)', '4ex');
+test_math_used('rem(10ch,6ch)', '4ch');
+test_math_used('rem(10rem,6rem)', '4rem');
+test_math_used('rem(10vh,6vh)', '4vh');
+test_math_used('rem(10vw,6vw)', '4vw');
+test_math_used('rem(10vmin,6vmin)', '4vmin');
+test_math_used('rem(10vmax,6vmax)', '4vmax');
+test_math_used('rem(10s,6s)', '4s');
+test_math_used('rem(10ms,6ms)', '4ms');
+test_math_used('rem(10deg,6deg)', '4deg', {type:'angle', approx:0.1});
+test_math_used('rem(10grad,6grad)', '4grad', {type:'angle', approx:0.1});
+test_math_used('rem(10rad,6rad)', '4rad',{type:'angle', approx:0.1});
+test_math_used('rem(10turn,6turn)', '4turn',{type:'angle', approx:0.1});
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid-expected.txt (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid-expected.txt	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,79 @@
+
+PASS e.style['opacity'] = "round()" should not set the property value
+PASS e.style['opacity'] = "round( )" should not set the property value
+PASS e.style['opacity'] = "round(,)" should not set the property value
+PASS e.style['opacity'] = "round(1, )" should not set the property value
+PASS e.style['opacity'] = "round(, 1)" should not set the property value
+PASS e.style['opacity'] = "round(1 + )" should not set the property value
+PASS e.style['opacity'] = "round(1 - )" should not set the property value
+PASS e.style['opacity'] = "round(1 * )" should not set the property value
+PASS e.style['opacity'] = "round(1 / )" should not set the property value
+PASS e.style['opacity'] = "round(1 2)" should not set the property value
+PASS e.style['opacity'] = "round(nearest, 1 2)" should not set the property value
+PASS e.style['opacity'] = "round(1, nearest, 12)" should not set the property value
+PASS e.style['opacity'] = "round(1, nearest)" should not set the property value
+PASS e.style['opacity'] = "round(nearest, 1, nearest)" should not set the property value
+PASS e.style['opacity'] = "round(nearest, 1)" should not set the property value
+PASS e.style['opacity'] = "round(1, , 2)" should not set the property value
+PASS e.style['opacity'] = "mod()" should not set the property value
+PASS e.style['opacity'] = "mod( )" should not set the property value
+PASS e.style['opacity'] = "mod(,)" should not set the property value
+PASS e.style['opacity'] = "mod(1, )" should not set the property value
+PASS e.style['opacity'] = "mod(, 1)" should not set the property value
+PASS e.style['opacity'] = "mod(1 + )" should not set the property value
+PASS e.style['opacity'] = "mod(1 - )" should not set the property value
+PASS e.style['opacity'] = "mod(1 * )" should not set the property value
+PASS e.style['opacity'] = "mod(1 / )" should not set the property value
+PASS e.style['opacity'] = "mod(1 2)" should not set the property value
+PASS e.style['opacity'] = "mod(1, , 2)" should not set the property value
+PASS e.style['opacity'] = "rem()" should not set the property value
+PASS e.style['opacity'] = "rem( )" should not set the property value
+PASS e.style['opacity'] = "rem(,)" should not set the property value
+PASS e.style['opacity'] = "rem(1, )" should not set the property value
+PASS e.style['opacity'] = "rem(, 1)" should not set the property value
+PASS e.style['opacity'] = "rem(1 + )" should not set the property value
+PASS e.style['opacity'] = "rem(1 - )" should not set the property value
+PASS e.style['opacity'] = "rem(1 * )" should not set the property value
+PASS e.style['opacity'] = "rem(1 / )" should not set the property value
+PASS e.style['opacity'] = "rem(1 2)" should not set the property value
+PASS e.style['opacity'] = "rem(1, , 2)" should not set the property value
+PASS e.style['opacity'] = "round(0px)" should not set the property value
+PASS e.style['opacity'] = "round(0s)" should not set the property value
+PASS e.style['opacity'] = "round(0deg)" should not set the property value
+PASS e.style['opacity'] = "round(0Hz)" should not set the property value
+PASS e.style['opacity'] = "round(0dpi)" should not set the property value
+PASS e.style['opacity'] = "round(0fr)" should not set the property value
+PASS e.style['opacity'] = "round(1, 1%)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0px)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0s)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0deg)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0Hz)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0dpi)" should not set the property value
+PASS e.style['opacity'] = "round(1, 0fr)" should not set the property value
+PASS e.style['opacity'] = "mod(0px)" should not set the property value
+PASS e.style['opacity'] = "mod(0s)" should not set the property value
+PASS e.style['opacity'] = "mod(0deg)" should not set the property value
+PASS e.style['opacity'] = "mod(0Hz)" should not set the property value
+PASS e.style['opacity'] = "mod(0dpi)" should not set the property value
+PASS e.style['opacity'] = "mod(0fr)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 1%)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0px)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0s)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0deg)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0Hz)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0dpi)" should not set the property value
+PASS e.style['opacity'] = "mod(1, 0fr)" should not set the property value
+PASS e.style['opacity'] = "rem(0px)" should not set the property value
+PASS e.style['opacity'] = "rem(0s)" should not set the property value
+PASS e.style['opacity'] = "rem(0deg)" should not set the property value
+PASS e.style['opacity'] = "rem(0Hz)" should not set the property value
+PASS e.style['opacity'] = "rem(0dpi)" should not set the property value
+PASS e.style['opacity'] = "rem(0fr)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 1%)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0px)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0s)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0deg)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0Hz)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0dpi)" should not set the property value
+PASS e.style['opacity'] = "rem(1, 0fr)" should not set the property value
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid.html (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid.html	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,94 @@
+<!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('round()');
+test_invalid_number('round( )');
+test_invalid_number('round(,)');
+test_invalid_number('round(1, )');
+test_invalid_number('round(, 1)');
+test_invalid_number('round(1 + )');
+test_invalid_number('round(1 - )');
+test_invalid_number('round(1 * )');
+test_invalid_number('round(1 / )');
+test_invalid_number('round(1 2)');
+test_invalid_number('round(nearest, 1 2)');
+test_invalid_number('round(1, nearest, 12)');
+test_invalid_number('round(1, nearest)');
+test_invalid_number('round(nearest, 1, nearest)');
+test_invalid_number('round(nearest, 1)');
+test_invalid_number('round(1, , 2)');
+test_invalid_number('mod()');
+test_invalid_number('mod( )');
+test_invalid_number('mod(,)');
+test_invalid_number('mod(1, )');
+test_invalid_number('mod(, 1)');
+test_invalid_number('mod(1 + )');
+test_invalid_number('mod(1 - )');
+test_invalid_number('mod(1 * )');
+test_invalid_number('mod(1 / )');
+test_invalid_number('mod(1 2)');
+test_invalid_number('mod(1, , 2)');
+test_invalid_number('rem()');
+test_invalid_number('rem( )');
+test_invalid_number('rem(,)');
+test_invalid_number('rem(1, )');
+test_invalid_number('rem(, 1)');
+test_invalid_number('rem(1 + )');
+test_invalid_number('rem(1 - )');
+test_invalid_number('rem(1 * )');
+test_invalid_number('rem(1 / )');
+test_invalid_number('rem(1 2)');
+test_invalid_number('rem(1, , 2)');
+
+// Type checking
+test_invalid_number('round(0px)');
+test_invalid_number('round(0s)');
+test_invalid_number('round(0deg)');
+test_invalid_number('round(0Hz)');
+test_invalid_number('round(0dpi)');
+test_invalid_number('round(0fr)');
+test_invalid_number('round(1, 1%)');
+test_invalid_number('round(1, 0px)');
+test_invalid_number('round(1, 0s)');
+test_invalid_number('round(1, 0deg)');
+test_invalid_number('round(1, 0Hz)');
+test_invalid_number('round(1, 0dpi)');
+test_invalid_number('round(1, 0fr)');
+test_invalid_number('mod(0px)');
+test_invalid_number('mod(0s)');
+test_invalid_number('mod(0deg)');
+test_invalid_number('mod(0Hz)');
+test_invalid_number('mod(0dpi)');
+test_invalid_number('mod(0fr)');
+test_invalid_number('mod(1, 1%)');
+test_invalid_number('mod(1, 0px)');
+test_invalid_number('mod(1, 0s)');
+test_invalid_number('mod(1, 0deg)');
+test_invalid_number('mod(1, 0Hz)');
+test_invalid_number('mod(1, 0dpi)');
+test_invalid_number('mod(1, 0fr)');
+test_invalid_number('rem(0px)');
+test_invalid_number('rem(0s)');
+test_invalid_number('rem(0deg)');
+test_invalid_number('rem(0Hz)');
+test_invalid_number('rem(0dpi)');
+test_invalid_number('rem(0fr)');
+test_invalid_number('rem(1, 1%)');
+test_invalid_number('rem(1, 0px)');
+test_invalid_number('rem(1, 0s)');
+test_invalid_number('rem(1, 0deg)');
+test_invalid_number('rem(1, 0Hz)');
+test_invalid_number('rem(1, 0dpi)');
+test_invalid_number('rem(1, 0fr)');
+</script>

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize-expected.txt (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize-expected.txt	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,14 @@
+
+FAIL 'round(1.1,1)' as a specified value should serialize as 'calc(1)'. assert_equals: 'round(1.1,1)' and 'calc(1)' should serialize the same in specified values. expected "calc(1)" but got "round(nearest, 1.1, 1)"
+FAIL 'scale(round(1.1,1))' as a specified value should serialize as 'scale(calc(1))'. assert_equals: 'scale(round(1.1,1))' and 'scale(calc(1))' should serialize the same in specified values. expected "scale(calc(1))" but got "scale(round(nearest, 1.1, 1))"
+PASS 'round(1.1,1)' as a computed value should serialize as '1'.
+PASS 'scale(round(1.1,1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
+FAIL 'mod(1,1)' as a specified value should serialize as 'calc(0)'. assert_equals: 'mod(1,1)' and 'calc(0)' should serialize the same in specified values. expected "calc(0)" but got "mod(1, 1)"
+FAIL 'scale(mod(1,1))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(mod(1,1))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(mod(1, 1))"
+PASS 'mod(1,1)' as a computed value should serialize as '0'.
+PASS 'scale(mod(1,1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'.
+FAIL 'rem(1,1)' as a specified value should serialize as 'calc(0)'. assert_equals: 'rem(1,1)' and 'calc(0)' should serialize the same in specified values. expected "calc(0)" but got "rem(1, 1)"
+FAIL 'scale(rem(1,1))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(rem(1,1))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(rem(1, 1))"
+PASS 'rem(1,1)' as a computed value should serialize as '0'.
+PASS 'scale(rem(1,1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'.
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize.html (0 => 283073)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize.html	2021-09-25 05:03:08 UTC (rev 283073)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="author" title="Xiaocheng Hu" 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(calc(${c}))`);
+    test_computed_serialization('opacity', t, c);
+    test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`);
+}
+
+test_serialization(
+    'round(1.1,1)',
+    'calc(1)',
+    '1');
+test_serialization(
+    'mod(1,1)',
+    'calc(0)',
+    '0');
+test_serialization(
+    'rem(1,1)',
+    'calc(0)',
+    '0');
+</script>

Modified: trunk/Source/WebCore/ChangeLog (283072 => 283073)


--- trunk/Source/WebCore/ChangeLog	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/ChangeLog	2021-09-25 05:03:08 UTC (rev 283073)
@@ -1,3 +1,53 @@
+2021-09-24  Nikos Mouchtaris  <nmouchta...@apple.com>
+
+        Implement round,mod,rem functions for calc
+        https://bugs.webkit.org/show_bug.cgi?id=230073
+
+        Reviewed by Simon Fraser.
+
+        Implemented round, mod and rem calc functions. Involved adding css keywords for the functions
+        and the keywords associated with the round function, as well as implementing the parsing and 
+        computation of the _expression_. The spec for these functions: 
+        https://drafts.csswg.org/css-values-4/#round-func.
+
+        Tests: imported/w3c/web-platform-tests/css/css-values/round-mod-rem-computed.html
+               imported/w3c/web-platform-tests/css/css-values/round-mod-rem-invalid.html
+               imported/w3c/web-platform-tests/css/css-values/round-mod-rem-serialize.html
+
+        * css/CSSValueKeywords.in:
+        * css/calc/CSSCalcExpressionNodeParser.cpp:
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
+        (WebCore::checkRoundKeyword):
+        Addition of functionID to parsing so the round keywords are only parsed within round 
+        function.
+        (WebCore::CSSCalcExpressionNodeParser::parseValue):
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcValue):
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcProduct):
+        (WebCore::CSSCalcExpressionNodeParser::parseCalcSum):
+        * css/calc/CSSCalcExpressionNodeParser.h:
+        * css/calc/CSSCalcOperationNode.cpp:
+        (WebCore::determineCategory):
+        (WebCore::functionFromOperator):
+        (WebCore::CSSCalcOperationNode::createStep):
+        (WebCore::validateRoundChildren):
+        (WebCore::CSSCalcOperationNode::createRound):
+        (WebCore::CSSCalcOperationNode::createRoundConstant):
+        (WebCore::CSSCalcOperationNode::combineChildren):
+        (WebCore::CSSCalcOperationNode::simplifyNode):
+        (WebCore::functionPrefixForOperator):
+        (WebCore::getNearestMultiples):
+        (WebCore::CSSCalcOperationNode::evaluateOperator):
+        * css/calc/CSSCalcOperationNode.h:
+        * css/calc/CSSCalcValue.cpp:
+        (WebCore::createCSS):
+        (WebCore::CSSCalcValue::isCalcFunction):
+        * platform/calc/CalcExpressionOperation.cpp:
+        (WebCore::getNearestMultiples):
+        (WebCore::CalcExpressionOperation::evaluate const):
+        * platform/calc/CalcOperator.cpp:
+        (WebCore::operator<<):
+        * platform/calc/CalcOperator.h:
+
 2021-09-24  Simon Fraser  <simon.fra...@apple.com>
 
         Add a ScrollAnimations log channel

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (283072 => 283073)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-09-25 05:03:08 UTC (rev 283073)
@@ -1359,6 +1359,10 @@
 atan2
 abs
 sign
+mod
+rem
+to-zero
+nearest
 
 from-image
 

Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (283072 => 283073)


--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp	2021-09-25 05:03:08 UTC (rev 283073)
@@ -129,10 +129,18 @@
         minArgumentCount = 3;
         maxArgumentCount = 3;
         break;
-
     case CSSValueLog:
         maxArgumentCount = 2;
         break;
+    case CSSValueRound:
+        minArgumentCount = 2;
+        maxArgumentCount = 3;
+        break;
+    case CSSValueMod:
+    case CSSValueRem:
+        minArgumentCount = 2;
+        maxArgumentCount = 2;
+        break;
     case CSSValueExp:
     case CSSValueSin:
     case CSSValueCos:
@@ -163,7 +171,7 @@
             return false;
 
         RefPtr<CSSCalcExpressionNode> node;
-        if (!parseCalcSum(tokens, depth, node))
+        if (!parseCalcSum(tokens, functionID, depth, node))
             return false;
 
         ++argumentCount;
@@ -196,6 +204,15 @@
     case CSSValueTan:
         result = CSSCalcOperationNode::createTrig(CalcOperator::Tan, WTFMove(nodes));
         break;
+    case CSSValueRound:
+        result = CSSCalcOperationNode::createRound(WTFMove(nodes));
+        break;
+    case CSSValueMod:
+        result = CSSCalcOperationNode::createStep(CalcOperator::Mod, WTFMove(nodes));
+        break;
+    case CSSValueRem:
+        result = CSSCalcOperationNode::createStep(CalcOperator::Rem, WTFMove(nodes));
+        break;
     case CSSValueWebkitCalc:
     case CSSValueCalc:
         result = CSSCalcOperationNode::createSum(WTFMove(nodes));
@@ -232,8 +249,30 @@
     return !!result;
 }
 
-bool CSSCalcExpressionNodeParser::parseValue(CSSParserTokenRange& tokens, RefPtr<CSSCalcExpressionNode>& result)
+static bool checkRoundKeyword(CSSValueID functionID, RefPtr<CSSCalcExpressionNode>& result, CSSValueID constantID)
 {
+    if (functionID != CSSValueRound)
+        return false;
+    switch (constantID) {
+    case CSSValueNearest:
+        result = CSSCalcOperationNode::createRoundConstant(CalcOperator::Nearest);
+        return true;
+    case CSSValueToZero:
+        result = CSSCalcOperationNode::createRoundConstant(CalcOperator::ToZero);
+        return true;
+    case CSSValueUp:
+        result = CSSCalcOperationNode::createRoundConstant(CalcOperator::Up);
+        return true;
+    case CSSValueDown:
+        result = CSSCalcOperationNode::createRoundConstant(CalcOperator::Down);
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool CSSCalcExpressionNodeParser::parseValue(CSSParserTokenRange& tokens, CSSValueID functionID, RefPtr<CSSCalcExpressionNode>& result)
+{
     auto makeCSSCalcPrimitiveValueNode = [&] (CSSUnitType type, double value) -> bool {
         if (calcUnitCategory(type) == CalculationCategory::Other)
             return false;
@@ -246,6 +285,8 @@
 
     switch (token.type()) {
     case IdentToken: {
+        if (checkRoundKeyword(functionID, result, token.id()))
+            return true;
         auto value = m_symbolTable.get(token.id());
         value = value ? value : getConstantTable().get(token.id());
         if (!value)
@@ -266,7 +307,7 @@
     return false;
 }
 
-bool CSSCalcExpressionNodeParser::parseCalcValue(CSSParserTokenRange& tokens, int depth, RefPtr<CSSCalcExpressionNode>& result)
+bool CSSCalcExpressionNodeParser::parseCalcValue(CSSParserTokenRange& tokens, CSSValueID functionID, int depth, RefPtr<CSSCalcExpressionNode>& result)
 {
     if (checkDepthAndIndex(depth, tokens) != OK)
         return false;
@@ -289,16 +330,16 @@
         return parseCalcFunction(innerRange, functionId, depth + 1, result);
     }
 
-    return parseValue(tokens, result);
+    return parseValue(tokens, functionID, result);
 }
 
-bool CSSCalcExpressionNodeParser::parseCalcProduct(CSSParserTokenRange& tokens, int depth, RefPtr<CSSCalcExpressionNode>& result)
+bool CSSCalcExpressionNodeParser::parseCalcProduct(CSSParserTokenRange& tokens, CSSValueID functionID, int depth, RefPtr<CSSCalcExpressionNode>& result)
 {
     if (checkDepthAndIndex(depth, tokens) != OK)
         return false;
 
     RefPtr<CSSCalcExpressionNode> firstValue;
-    if (!parseCalcValue(tokens, depth, firstValue))
+    if (!parseCalcValue(tokens, functionID, depth, firstValue))
         return false;
 
     Vector<Ref<CSSCalcExpressionNode>> nodes;
@@ -310,7 +351,7 @@
         tokens.consumeIncludingWhitespace();
         
         RefPtr<CSSCalcExpressionNode> nextValue;
-        if (!parseCalcValue(tokens, depth, nextValue) || !nextValue)
+        if (!parseCalcValue(tokens, functionID, depth, nextValue) || !nextValue)
             return false;
 
         if (operatorCharacter == static_cast<char>(CalcOperator::Divide))
@@ -331,13 +372,13 @@
     return !!result;
 }
 
-bool CSSCalcExpressionNodeParser::parseCalcSum(CSSParserTokenRange& tokens, int depth, RefPtr<CSSCalcExpressionNode>& result)
+bool CSSCalcExpressionNodeParser::parseCalcSum(CSSParserTokenRange& tokens, CSSValueID functionID, int depth, RefPtr<CSSCalcExpressionNode>& result)
 {
     if (checkDepthAndIndex(depth, tokens) != OK)
         return false;
 
     RefPtr<CSSCalcExpressionNode> firstValue;
-    if (!parseCalcProduct(tokens, depth, firstValue))
+    if (!parseCalcProduct(tokens, functionID, depth, firstValue))
         return false;
 
     Vector<Ref<CSSCalcExpressionNode>> nodes;
@@ -357,7 +398,7 @@
         tokens.consumeIncludingWhitespace();
 
         RefPtr<CSSCalcExpressionNode> nextValue;
-        if (!parseCalcProduct(tokens, depth, nextValue) || !nextValue)
+        if (!parseCalcProduct(tokens, functionID, depth, nextValue) || !nextValue)
             return false;
 
         if (operatorCharacter == static_cast<char>(CalcOperator::Subtract))

Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h (283072 => 283073)


--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h	2021-09-25 05:03:08 UTC (rev 283073)
@@ -49,12 +49,12 @@
 private:
     char operatorValue(const CSSParserToken&);
 
-    bool parseValue(CSSParserTokenRange&, RefPtr<CSSCalcExpressionNode>&);
-    bool parseValueTerm(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&);
+    bool parseValue(CSSParserTokenRange&, CSSValueID, RefPtr<CSSCalcExpressionNode>&);
+    bool parseValueTerm(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&);
     bool parseCalcFunction(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&);
-    bool parseCalcSum(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&);
-    bool parseCalcProduct(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&);
-    bool parseCalcValue(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&);
+    bool parseCalcSum(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&);
+    bool parseCalcProduct(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&);
+    bool parseCalcValue(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&);
 
     CalculationCategory m_destinationCategory;
     const CSSCalcSymbolTable& m_symbolTable;

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp (283072 => 283073)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2021-09-25 05:03:08 UTC (rev 283073)
@@ -87,6 +87,13 @@
     case CalcOperator::Atan2:
     case CalcOperator::Abs:
     case CalcOperator::Sign:
+    case CalcOperator::Mod:
+    case CalcOperator::Rem:
+    case CalcOperator::Round:
+    case CalcOperator::Up:
+    case CalcOperator::Down:
+    case CalcOperator::Nearest:
+    case CalcOperator::ToZero:
         ASSERT_NOT_REACHED();
         return CalculationCategory::Other;
     }
@@ -166,6 +173,13 @@
         case CalcOperator::Acos:
         case CalcOperator::Atan:
         case CalcOperator::Atan2:
+        case CalcOperator::Mod:
+        case CalcOperator::Rem:
+        case CalcOperator::Round:
+        case CalcOperator::Up:
+        case CalcOperator::Down:
+        case CalcOperator::Nearest:
+        case CalcOperator::ToZero:
             // The type of a min(), max(), or clamp() _expression_ is the result of adding the types of its comma-separated calculations
             return CalculationCategory::Other;
         }
@@ -299,6 +313,20 @@
         return CSSValueAbs;
     case CalcOperator::Sign:
         return CSSValueSign;
+    case CalcOperator::Mod:
+        return CSSValueMod;
+    case CalcOperator::Rem:
+        return CSSValueRem;
+    case CalcOperator::Round:
+        return CSSValueRound;
+    case CalcOperator::Up:
+        return CSSValueUp;
+    case CalcOperator::Down:
+        return CSSValueDown;
+    case CalcOperator::Nearest:
+        return CSSValueNearest;
+    case CalcOperator::ToZero:
+        return CSSValueToZero;
     }
     return CSSValueCalc;
 }
@@ -476,6 +504,68 @@
     return adoptRef(new CSSCalcOperationNode(newCategory, op, WTFMove(values)));
 }
 
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createStep(CalcOperator op, Vector<Ref<CSSCalcExpressionNode>>&& values)
+{
+    if (values.size() != 2)
+        return nullptr;
+
+    if (values[0]->category() != values[1]->category()) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create stepped value node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+    
+    if (!values[1]->doubleValue(values[1]->primitiveType())) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create stepped value node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+
+    return adoptRef(new CSSCalcOperationNode(values[0]->category(), op, WTFMove(values)));
+}
+
+static bool validateRoundChildren(Vector<Ref<CSSCalcExpressionNode>>& values)
+{
+    // for 3 children 1st node must be round constant
+    if (values.size() == 3) {
+        if (!is<CSSCalcOperationNode>(values[0]) || !(downcast<CSSCalcOperationNode>(values[0].get()).isRoundOperation()))
+            return false;
+    }
+    // for 2 children should not have round constant anywhere but first node of 3
+    for (size_t i = values.size() == 2 ? 0 : 1; i < values.size(); i++) {
+        if (is<CSSCalcOperationNode>(values[i])) {
+            if (downcast<CSSCalcOperationNode>(values[i].get()).isRoundConstant())
+                return false;
+        }
+    }
+    // check that two categories of numerical values are the same
+    return values.rbegin()[1]->category() == values.rbegin()[0]->category();
+    
+}
+
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createRound(Vector<Ref<CSSCalcExpressionNode>>&& values)
+{
+    if (values.size() != 2 && values.size() != 3)
+        return nullptr;
+    
+    if (!validateRoundChildren(values)) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create round node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+    
+    CalcOperator roundType = values.size() == 2 ?  CalcOperator::Nearest : downcast<CSSCalcOperationNode>(values[0].get()).calcOperator();
+    if (values.size() == 3)
+        values.remove(0);
+    if (!values[1]->doubleValue(values[1]->primitiveType())) {
+        LOG_WITH_STREAM(Calc, stream << "Failed to create round node because unable to determine category from " << prettyPrintNodes(values));
+        return nullptr;
+    }
+    return adoptRef(new CSSCalcOperationNode(values.rbegin()[0]->category(), roundType, WTFMove(values)));
+}
+
+RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createRoundConstant(CalcOperator op)
+{
+    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, op, { }));
+}
+
 void CSSCalcOperationNode::hoistChildrenWithOperator(CalcOperator op)
 {
     ASSERT(op == CalcOperator::Add || op == CalcOperator::Multiply);
@@ -710,6 +800,20 @@
         m_children.clear();
         m_children.append(WTFMove(newChild));
     }
+    if (isSteppedNode()) {
+        auto combinedUnitType = m_children[0]->primitiveType();
+        double resolvedValue = doubleValue(combinedUnitType);
+        auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, combinedUnitType));
+        m_children.clear();
+        m_children.append(WTFMove(newChild));
+    }
+    if (isRoundOperation()) {
+        auto combinedUnitType = m_children[0]->primitiveType();
+        double resolvedValue = doubleValue(combinedUnitType);
+        auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, combinedUnitType));
+        m_children.clear();
+        m_children.append(WTFMove(newChild));
+    }
 }
 
 // https://drafts.csswg.org/css-values-4/#simplify-a-calculation-tree
@@ -798,6 +902,11 @@
         if (calcOperationNode.isSignNode() && depth)
             calcOperationNode.combineChildren();
 
+        if (calcOperationNode.isSteppedNode() && depth)
+            calcOperationNode.combineChildren();
+        
+        if (calcOperationNode.isRoundOperation() && depth)
+            calcOperationNode.combineChildren();
         // If only one child remains, return the child (except at the root).
         auto shouldCombineParentWithOnlyChild = [](const CSSCalcOperationNode& parent, int depth)
         {
@@ -1003,6 +1112,13 @@
     case CalcOperator::Atan2: return "atan2(";
     case CalcOperator::Abs: return "abs(";
     case CalcOperator::Sign: return "sign(";
+    case CalcOperator::Mod: return "mod(";
+    case CalcOperator::Rem: return "rem(";
+    case CalcOperator::Round: return "round(";
+    case CalcOperator::Up: return "round(up, ";
+    case CalcOperator::Down: return "round(down, ";
+    case CalcOperator::Nearest: return "round(nearest, ";
+    case CalcOperator::ToZero: return "round(to-zero, ";
     }
     
     return "";
@@ -1157,6 +1273,13 @@
     return true;
 }
 
+static std::pair<double, double> getNearestMultiples(double a, double b)
+{
+    double lowerB = std::floor(a / std::abs(b))*std::abs(b);
+    double upperB = lowerB + std::abs(b);
+    return std::make_pair(lowerB, upperB);
+}
+
 double CSSCalcOperationNode::evaluateOperator(CalcOperator op, const Vector<double>& children)
 {
     switch (op) {
@@ -1265,7 +1388,57 @@
             return -1;
         return children[0];
     }
+    case CalcOperator::Mod: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        float left = children[0];
+        float right = children[1];
+        if (!right)
+            return std::numeric_limits<double>::quiet_NaN();
+        if ((left < 0) == (right < 0))
+            return std::fmod(left, right);
+        return std::remainder(left, right);
     }
+    case CalcOperator::Rem: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        float left = children[0];
+        float right = children[1];
+        if (!right)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::fmod(left, right);
+    }
+    case CalcOperator::Round:
+        return std::numeric_limits<double>::quiet_NaN();
+    case CalcOperator::Up: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(children[0], children[1]);
+        return ret.second;
+    }
+    case CalcOperator::Down: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(children[0], children[1]);
+        return ret.first;
+    }
+    case CalcOperator::Nearest: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(children[0], children[1]);
+        auto upperB = ret.second;
+        auto lowerB = ret.first;
+        return std::abs(upperB - children[0]) <= std::abs(children[1]) / 2 ? upperB : lowerB;
+    }
+    case CalcOperator::ToZero: {
+        if (children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(children[0], children[1]);
+        auto upperB = ret.second;
+        auto lowerB = ret.first;
+        return std::abs(upperB) < std::abs(lowerB) ? upperB : lowerB;
+    }
+    }
     ASSERT_NOT_REACHED();
     return 0;
 }

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h (283072 => 283073)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2021-09-25 05:03:08 UTC (rev 283073)
@@ -43,6 +43,9 @@
     static RefPtr<CSSCalcOperationNode> createInverseTrig(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values);
     static RefPtr<CSSCalcOperationNode> createAtan2(Vector<Ref<CSSCalcExpressionNode>>&& values);
     static RefPtr<CSSCalcOperationNode> createSign(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values);
+    static RefPtr<CSSCalcOperationNode> createStep(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values);
+    static RefPtr<CSSCalcOperationNode> createRound(Vector<Ref<CSSCalcExpressionNode>>&& values);
+    static RefPtr<CSSCalcOperationNode> createRoundConstant(CalcOperator);
     static Ref<CSSCalcExpressionNode> simplify(Ref<CSSCalcExpressionNode>&&);
 
     static void buildCSSText(const CSSCalcExpressionNode&, StringBuilder&);
@@ -57,6 +60,9 @@
     bool isAtan2Node() const { return m_operator == CalcOperator::Atan2; }
     bool isSignNode() const { return m_operator == CalcOperator::Abs || m_operator == CalcOperator::Sign; }
     bool shouldSortChildren() const { return isCalcSumNode() || isCalcProductNode(); }
+    bool isSteppedNode() const { return m_operator == CalcOperator::Mod || m_operator == CalcOperator::Rem || m_operator == CalcOperator::Round; }
+    bool isRoundOperation() const { return m_operator == CalcOperator::Down || m_operator == CalcOperator::Up || m_operator == CalcOperator::ToZero || m_operator == CalcOperator::Nearest; }
+    bool isRoundConstant() const { return (isRoundOperation()) && !m_children.size(); }
 
     void hoistChildrenWithOperator(CalcOperator);
     void combineChildren();

Modified: trunk/Source/WebCore/css/calc/CSSCalcValue.cpp (283072 => 283073)


--- trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/css/calc/CSSCalcValue.cpp	2021-09-25 05:03:08 UTC (rev 283073)
@@ -213,7 +213,21 @@
                 return nullptr;
             return CSSCalcOperationNode::createSign(op, WTFMove(children));
         }
+        case CalcOperator::Mod:
+        case CalcOperator::Rem:
+        case CalcOperator::Round: {
+            auto children = createCSS(operationChildren, style);
+            if (children.size() != 2)
+                return nullptr;
+            return CSSCalcOperationNode::createStep(op, WTFMove(children));
         }
+        case CalcOperator::Nearest:
+        case CalcOperator::ToZero:
+        case CalcOperator::Up:
+        case CalcOperator::Down: {
+            return CSSCalcOperationNode::createRoundConstant(op);
+        }
+        }
         return nullptr;
     }
     case CalcExpressionNodeType::BlendLength: {
@@ -335,6 +349,9 @@
     case CSSValueAtan2:
     case CSSValueAbs:
     case CSSValueSign:
+    case CSSValueRound:
+    case CSSValueMod:
+    case CSSValueRem:
         return true;
     default:
         return false;

Modified: trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp (283072 => 283073)


--- trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp	2021-09-25 05:03:08 UTC (rev 283073)
@@ -31,6 +31,14 @@
 
 namespace WebCore {
 
+static std::pair<double, double> getNearestMultiples(double a, double b)
+{
+    auto absB = std::abs(b);
+    double lowerB = std::floor(a / absB) * absB;
+    double upperB = lowerB + absB;
+    return std::make_pair(lowerB, upperB);
+}
+
 float CalcExpressionOperation::evaluate(float maxValue) const
 {
     switch (m_operator) {
@@ -148,7 +156,59 @@
             return -1;
         return m_children[0]->evaluate(maxValue);
     }
+    case CalcOperator::Mod: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        float left = m_children[0]->evaluate(maxValue);
+        float right = m_children[1]->evaluate(maxValue);
+        if (!right)
+            return std::numeric_limits<double>::quiet_NaN();
+        if ((left < 0) == (right < 0))
+            return std::fmod(left, right);
+        return std::remainder(left, right);
     }
+    case CalcOperator::Rem: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        float left = m_children[0]->evaluate(maxValue);
+        float right = m_children[1]->evaluate(maxValue);
+        if (!right)
+            return std::numeric_limits<double>::quiet_NaN();
+        return std::fmod(left, right);
+    }
+    case CalcOperator::Round:
+        return std::numeric_limits<double>::quiet_NaN();
+    case CalcOperator::Up: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(m_children[0]->evaluate(maxValue), m_children[1]->evaluate(maxValue));
+        return ret.second;
+    }
+    case CalcOperator::Down: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(m_children[0]->evaluate(maxValue), m_children[1]->evaluate(maxValue));
+        return ret.first;
+    }
+    case CalcOperator::Nearest: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto a = m_children[0]->evaluate(maxValue);
+        auto b = m_children[1]->evaluate(maxValue);
+        auto ret = getNearestMultiples(a, b);
+        auto upperB = ret.second;
+        auto lowerB = ret.first;
+        return std::abs(upperB - a) <= std::abs(b) / 2 ? upperB : lowerB;
+    }
+    case CalcOperator::ToZero: {
+        if (m_children.size() != 2)
+            return std::numeric_limits<double>::quiet_NaN();
+        auto ret = getNearestMultiples(m_children[0]->evaluate(maxValue), m_children[1]->evaluate(maxValue));
+        auto upperB = ret.second;
+        auto lowerB = ret.first;
+        return std::abs(upperB) < std::abs(lowerB) ? upperB : lowerB;
+    }
+    }
     ASSERT_NOT_REACHED();
     return std::numeric_limits<float>::quiet_NaN();
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.cpp (283072 => 283073)


--- trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.cpp	2021-09-25 05:03:08 UTC (rev 283073)
@@ -51,6 +51,13 @@
     case CalcOperator::Atan2: ts << "atan2"; break;
     case CalcOperator::Abs: ts << "abs"; break;
     case CalcOperator::Sign: ts << "sign"; break;
+    case CalcOperator::Mod: ts << "mod"; break;
+    case CalcOperator::Rem: ts << "rem"; break;
+    case CalcOperator::Round: ts << "round"; break;
+    case CalcOperator::Up: ts << "up"; break;
+    case CalcOperator::Down: ts << "down"; break;
+    case CalcOperator::ToZero: ts << "to-zero"; break;
+    case CalcOperator::Nearest: ts << "nearest"; break;
     }
     return ts;
 }

Modified: trunk/Source/WebCore/platform/calc/CalcOperator.h (283072 => 283073)


--- trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-25 03:39:35 UTC (rev 283072)
+++ trunk/Source/WebCore/platform/calc/CalcOperator.h	2021-09-25 05:03:08 UTC (rev 283073)
@@ -49,6 +49,13 @@
     Atan2,
     Abs,
     Sign,
+    Mod,
+    Rem,
+    Round,
+    Nearest,
+    Up,
+    Down,
+    ToZero,
 };
 
 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