Clamp out of range calc() values after font-style: oblique calc(...)

This fixes the bug referenced [here.]
(https://bugs.chromium.org/p/chromium/issues/detail?id=809943)

Values specified in a calc() function after an oblique now clamp to the
range of [-90, 90].

https://www.w3.org/TR/css-fonts-4/ - Restricts values to -90-90
https://drafts.csswg.org/css-values-3/#calc-range - Requires that the
results of Calc be clamped.

Bug: 809943
Change-Id: I474f034fc87018bf983c89fba52ed4a09994f924
Reviewed-on: https://chromium-review.googlesource.com/c/1410177
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Sushanth Rajasankar <Sushraja@microsoft.com>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#623808}
diff --git a/css/css-fonts/variations/at-font-face-descriptors.html b/css/css-fonts/variations/at-font-face-descriptors.html
index 942686c..cd1c22b 100644
--- a/css/css-fonts/variations/at-font-face-descriptors.html
+++ b/css/css-fonts/variations/at-font-face-descriptors.html
@@ -147,6 +147,8 @@
             { value: "oblique 20deg",           isValid: true,  expectedValue: "oblique", description: "'oblique' followed by default 20deg angle" },
             { value: "oblique 90deg",           isValid: true,  description: "'oblique' followed by maxumum 90 degree angle" },
             { value: "oblique -90deg",          isValid: true,  description: "'oblique' followed by minimum -90 degree angle" },
+            { value: "oblique calc(91deg)",     isValid: true,  expectedValue: "oblique 90deg", description: "'oblique' followed by calc with out of range value (should be clamped)" },
+            { value: "oblique calc(-91deg)",    isValid: true,  expectedValue: "oblique -90deg", description: "'oblique' followed by calc with out of range value (should be clamped)" },
             { value: "oblique 0rad",            isValid: true,  expectedValue: "oblique 0deg", description: "'oblique' followed by  angle in radians" },
             { value: "oblique 20",              isValid: false, description: "'oblique' followed by unit-less number" },
             { value: "oblique 20px",            isValid: false, description: "'oblique' followed by non-angle" },
diff --git a/css/css-fonts/variations/font-style-parsing.html b/css/css-fonts/variations/font-style-parsing.html
index 0973d63..cb5e42e 100644
--- a/css/css-fonts/variations/font-style-parsing.html
+++ b/css/css-fonts/variations/font-style-parsing.html
@@ -7,43 +7,54 @@
     <script src="/resources/testharnessreport.js"></script>
 </head>
 <body>
-
+    <div id="test"></div>
     <script>
-
         var testFontStyle = [
-            { style: "italic",            expectedResult: true,  message: "'italic' is valid" },
-            { style: "italic 20deg",      expectedResult: false, message: "'italic' followed by angle is invalid" },
-            { style: "italic a",          expectedResult: false, message: "'italic' followed by non-number is invalid" },
-            { style: "oblique",           expectedResult: true,  message: "'oblique' is valid" },
-            { style: "oblique 0deg",      expectedResult: true,  message: "'oblique' followed by zero degrees is valid" },
-            { style: "oblique 20deg",     expectedResult: true,  message: "'oblique' followed by positive angle in degrees is valid" },
-            { style: "oblique 0.5rad",    expectedResult: true,  message: "'oblique' followed by positive angle in radians is valid" },
-            { style: "oblique 20grad",    expectedResult: true,  message: "'oblique' followed by positive angle in gradians is valid" },
-            { style: "oblique 0.1turn",   expectedResult: true,  message: "'oblique' followed by positive angle in turns is valid" },
-            { style: "oblique 20px",      expectedResult: false, message: "'oblique' followed by number with invalid unit type is in valid" },
-            { style: "oblique -20deg",    expectedResult: true,  message: "'oblique' followed by negative angle is valid" },
-            { style: "oblique 20.1deg",   expectedResult: true,  message: "'oblique' followed by fractional angle is valid" },
-            { style: "oblique 90deg",     expectedResult: true,  message: "'oblique' followed by maxumum 90 degree angle is valid" },
-            { style: "oblique -90deg",    expectedResult: true,  message: "'oblique' followed by minimum -90 degree angle is valid" },
-            { style: "oblique 90.01deg",  expectedResult: false, message: "'oblique' followed by positive out of range angle is in invalid" },
-            { style: "oblique -90.01deg", expectedResult: false, message: "'oblique' followed by negative out of range angle is in invalid" },
-            { style: "oblique 10",        expectedResult: false, message: "'oblique' followed by unit-less value is invalid" },
-            { style: "oblique 20deg ",    expectedResult: true,  message: "'oblique' followed by positive angle is valid" },
-            { style: "oblique a",         expectedResult: false, message: "'oblique' followed by non-number is invalid" },
-            { style: "oblique 20deg a",   expectedResult: false, message: "'oblique' and angle followed by non-number is invalid" },
-            { style: "oblique -",         expectedResult: false, message: "'oblique' followed by isolated minus is invalid" },
-            { style: "oblique - 20deg",   expectedResult: false, message: "'oblique' followed by minus and angle separated by space is invalid" },
-            { style: "oblique -a",        expectedResult: false, message: "'oblique' followed by minus and non-number is invalid" },
-            { style: "oblique calc(50deg)",     expectedResult: true,  message: "'oblique' followed by calc is valid" },
-            { style: "oblique calc(-120deg)",   expectedResult: true,  message: "'oblique' followed by calc is valid even if it must be clamped (no computation)" },
-            { style: "oblique calc(6 * 20deg)", expectedResult: true,  message: "'oblique' followed by calc is valid even if it must be clamped (with computation)" },
-            { style: "oblique calc(0.1rad + 1deg)", expectedResult: true,  message: "'oblique' followed by calc is valid even if it mixes units (with computation)" }
+            { style: "italic",                      expectedResult: true,   message: "'italic' is valid" },
+            { style: "italic 20deg",                expectedResult: false,  message: "'italic' followed by angle is invalid" },
+            { style: "italic a",                    expectedResult: false,  message: "'italic' followed by non-number is invalid" },
+            { style: "oblique",                     expectedResult: true,   message: "'oblique' is valid" },
+            { style: "oblique 0deg",                expectedResult: true,   message: "'oblique' followed by zero degrees is valid" },
+            { style: "oblique 20deg",               expectedResult: true,   message: "'oblique' followed by positive angle in degrees is valid" },
+            { style: "oblique 0.5rad",              expectedResult: true,   message: "'oblique' followed by positive angle in radians is valid",    expectedValue: "oblique 28.6479deg" },
+            { style: "oblique 20grad",              expectedResult: true,   message: "'oblique' followed by positive angle in gradians is valid",   expectedValue: "oblique 18deg" },
+            { style: "oblique 0.1turn",             expectedResult: true,   message: "'oblique' followed by positive angle in turns is valid",      expectedValue: "oblique 36deg" },
+            { style: "oblique 20px",                expectedResult: false,  message: "'oblique' followed by number with invalid unit type is in valid" },
+            { style: "oblique -20deg",              expectedResult: true,   message: "'oblique' followed by negative angle is valid" },
+            { style: "oblique 20.5deg",             expectedResult: true,   message: "'oblique' followed by fractional angle is valid" },
+            { style: "oblique 90deg",               expectedResult: true,   message: "'oblique' followed by maxumum 90 degree angle is valid" },
+            { style: "oblique -90deg",              expectedResult: true,   message: "'oblique' followed by minimum -90 degree angle is valid" },
+            { style: "oblique 90.01deg",            expectedResult: false,  message: "'oblique' followed by positive out of range angle is in invalid" },
+            { style: "oblique -90.01deg",           expectedResult: false,  message: "'oblique' followed by negative out of range angle is in invalid" },
+            { style: "oblique 10",                  expectedResult: false,  message: "'oblique' followed by unit-less value is invalid" },
+            { style: "oblique 30deg",               expectedResult: true,   message: "'oblique' followed by positive angle is valid" },
+            { style: "oblique a",                   expectedResult: false,  message: "'oblique' followed by non-number is invalid" },
+            { style: "oblique 20deg a",             expectedResult: false,  message: "'oblique' and angle followed by non-number is invalid" },
+            { style: "oblique -",                   expectedResult: false,  message: "'oblique' followed by isolated minus is invalid" },
+            { style: "oblique - 20deg",             expectedResult: false,  message: "'oblique' followed by minus and angle separated by space is invalid" },
+            { style: "oblique -a",                  expectedResult: false,  message: "'oblique' followed by minus and non-number is invalid" },
+            { style: "oblique calc(50deg)",         expectedResult: true,   message: "'oblique' followed by calc is valid",                         expectedValue: "oblique 50deg" },
+            { style: "oblique calc(-120deg)",       expectedResult: true,   message: "'oblique' followed by calc is valid even if it must be clamped (no computation)",     expectedValue: "oblique -90deg" },
+            { style: "oblique calc(6 * 20deg)",     expectedResult: true,   message: "'oblique' followed by calc is valid even if it must be clamped (with computation)",   expectedValue: "oblique 90deg" },
+            { style: "oblique calc(10grad + 5deg)", expectedResult: true,   message: "'oblique' followed by calc is valid even if it mixes units (with computation)",       expectedValue: "oblique 14deg" }
         ];
 
         testFontStyle.forEach(function (testCase) {
-            test(() => { assert_equals(window.CSS.supports("font-style", testCase.style), testCase.expectedResult, "Font-style: " + testCase.message); }, "Font-style: " + testCase.message);
+            test(() => {
+                assert_equals(window.CSS.supports("font-style", testCase.style), testCase.expectedResult, "Font-style supports: " + testCase.message);
+            }, "Font-style (supports): " + testCase.message);
         });
 
+        testFontStyle.forEach(function (testCase) {
+            if (testCase.expectedResult) {
+                test(() => {
+                    let element = document.getElementById("test");
+                    element.style = "font-style: " + testCase.style;
+                    let expectedValue = (testCase.expectedValue) ? testCase.expectedValue : testCase.style;
+                    assert_equals(window.getComputedStyle(element).fontStyle, expectedValue, "Font-style computed style: " + testCase.message);
+                }, "Font-style (computed): " + testCase.message);
+            }
+        });
     </script>
 </body>
-</html>
+</html>
\ No newline at end of file