Title: [271362] trunk
Revision
271362
Author
[email protected]
Date
2021-01-11 08:56:58 -0800 (Mon, 11 Jan 2021)

Log Message

LayoutTests/imported/w3c:
Support lab(), lch(), gray() and color(lab ...) colors
https://bugs.webkit.org/show_bug.cgi?id=205675

Reviewed by Simon Fraser.

Update tests to use rectangles rather than text to make anti-aliasing differences
not cause failures. These changes will be upstreamed to the WebPlatformTests.

* web-platform-tests/css/css-color/lab-001-expected.html:
* web-platform-tests/css/css-color/lab-001.html:
* web-platform-tests/css/css-color/lab-002-expected.html:
* web-platform-tests/css/css-color/lab-002.html:
* web-platform-tests/css/css-color/lab-003-expected.html:
* web-platform-tests/css/css-color/lab-003.html:
* web-platform-tests/css/css-color/lab-004-expected.html:
* web-platform-tests/css/css-color/lab-004.html:
* web-platform-tests/css/css-color/lab-005-expected.html:
* web-platform-tests/css/css-color/lab-005.html:
* web-platform-tests/css/css-color/lab-006-expected.html:
* web-platform-tests/css/css-color/lab-006.html:
* web-platform-tests/css/css-color/lab-007-expected.html:
* web-platform-tests/css/css-color/lab-007.html:
* web-platform-tests/css/css-color/lch-001-expected.html:
* web-platform-tests/css/css-color/lch-001.html:
* web-platform-tests/css/css-color/lch-002-expected.html:
* web-platform-tests/css/css-color/lch-002.html:
* web-platform-tests/css/css-color/lch-003-expected.html:
* web-platform-tests/css/css-color/lch-003.html:
* web-platform-tests/css/css-color/lch-004-expected.html:
* web-platform-tests/css/css-color/lch-004.html:
* web-platform-tests/css/css-color/lch-005-expected.html:
* web-platform-tests/css/css-color/lch-005.html:
* web-platform-tests/css/css-color/lch-006-expected.html:
* web-platform-tests/css/css-color/lch-006.html:
* web-platform-tests/css/css-color/lch-007-expected.html:
* web-platform-tests/css/css-color/lch-007.html:

Source/WebCore:
Support lab(), lch() and color(lab ...) colors
https://bugs.webkit.org/show_bug.cgi?id=205675

Reviewed by Simon Fraser.

Original patch by Simon Fraser.

This adds parsing support for lab(), lch() and color(lab ...) CSS colors
(https://www.w3.org/TR/css-color-4/) and color type, conversion, and serialization
support for Lab and color type and conversion support for LCH (we store these color
canonically as Lab<float>, so serialization of LCH is never needed, much like HSL).

This change does not add support for the host platform layer (e.g. CoreGraphics, etc)
understanding of the Lab colorspace, and as such, when creating host color objects
(for instance via the cachedCGColor() helper) Lab<float> colors are converted to sRGB
first and then the host color is made. The ramification of this is for platforms that
use backingstores with greater than sRGB gamuts, Lab colors will be clampted to sRGB.
This should be rectified in a follow up change that adds proper creation of these host
objects but is being left off the initial change to limit changes.

Some of the imported tests have been updated to use rectangles rather than text to
avoid anti-aliasing issues and will be upstreamed to WPT following landing.

Tests:
    fast/css/parsing-lab-colors.html
    imported/w3c/web-platform-tests/css/css-color/lab-001.html
    imported/w3c/web-platform-tests/css/css-color/lab-002.html
    imported/w3c/web-platform-tests/css/css-color/lab-003.html
    imported/w3c/web-platform-tests/css/css-color/lab-004.html
    imported/w3c/web-platform-tests/css/css-color/lab-005.html
    imported/w3c/web-platform-tests/css/css-color/lab-006.html
    imported/w3c/web-platform-tests/css/css-color/lab-007.html
    imported/w3c/web-platform-tests/css/css-color/lch-001.html
    imported/w3c/web-platform-tests/css/css-color/lch-002.html
    imported/w3c/web-platform-tests/css/css-color/lch-003.html
    imported/w3c/web-platform-tests/css/css-color/lch-004.html
    imported/w3c/web-platform-tests/css/css-color/lch-005.html
    imported/w3c/web-platform-tests/css/css-color/lch-006.html
    imported/w3c/web-platform-tests/css/css-color/lch-007.html

* css/CSSValueKeywords.in:
Add "lab" and "lch" keywords.

* css/parser/CSSPropertyParser.cpp:
* css/parser/CSSPropertyParserHelpers.h:
* css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::parseOptionalAlpha):
(WebCore::CSSPropertyParserHelpers::parseLabParameters):
(WebCore::CSSPropertyParserHelpers::parseLCHParameters):
(WebCore::CSSPropertyParserHelpers::parseGrayParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunction):
Add support for parsing "lab(...)", "lch(...)", "gray(...)"
and "color(lab ...)", all of which create Lab<float> colors.

Also adds explicit UnitlessZeroQuirk flag to angle parsing to
allow parsing of newer specs that don't want to allow unitless zero
for angles. For now, I have left FIXMEs for the properties that
should probably disable it. This was not strictly necessary for this
change (as lch actaully allows unitless angles now), but it seems
like a solid move forward.

* platform/graphics/Color.h:
(WebCore::Color::Color):
Add overload of the Color constructor that takes a Lab<float> matching other
ColorSpace types.

* platform/graphics/ColorConversion.cpp:
(WebCore::convertFromD50WhitePointToD65WhitePoint):
(WebCore::convertFromD65WhitePointToD50WhitePoint):
(WebCore::toXYZA):
(WebCore::toLab):
(WebCore::toLCHA):
* platform/graphics/ColorConversion.h:
(WebCore::toLab):
(WebCore::toLCHA):
Add conversions to/from Lab to D65 white point XYZA (the white point we expect XYZA to be in), and conversion
from Lch to/from Lab.

* platform/graphics/ColorSerialization.cpp:
(WebCore::serialization):
(WebCore::serializationForCSS):
(WebCore::serializationForHTML):
(WebCore::serializationForRenderTreeAsText):
* platform/graphics/ColorSerialization.h:
Add serialization for Lab colors. We currently always serialize using the lab()
notation, which appears to be correct for at least colors declared using lab(),
lch() and gray(). Unclear if it is correct for colors declared with color(lab ...).
Opened https://github.com/w3c/csswg-drafts/issues/5825 to track getting a resolution
for "color(lab ...)".

* platform/graphics/ColorSpace.cpp:
(WebCore::operator<<):
* platform/graphics/ColorSpace.h:
Add Lab as a ColorSpace and text stream dumping for it.

* platform/graphics/ColorTypes.h:
(WebCore::Lab::Lab):
(WebCore::asColorComponents):
(WebCore::asLab):
Add Lab color type.

(WebCore::LCHA::LCHA):
(WebCore::asLCHA):
Add LCHA color type.

(WebCore::callWithColorType):
Add Lab to callWithColorType since it is now a valid ColorSpace.

* platform/graphics/cg/ColorSpaceCG.cpp:
(WebCore::labColorSpaceRef):
* platform/graphics/cg/ColorSpaceCG.h:
(WebCore::cachedCGColorSpace):
For now, return the sRGB color space to indicate to callers that they should do a conversion.

LayoutTests:
Support lab(), lch(), gray() and color(lab ...) colors
https://bugs.webkit.org/show_bug.cgi?id=205675

Reviewed by Simon Fraser.

Original patch by Simon Fraser.

Parsing tests for lab/lch/gray colors.

* TestExpectations: Unskip lab/lch tests.
* fast/css/parsing-lab-colors-expected.txt: Added.
* fast/css/parsing-lab-colors.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (271361 => 271362)


--- trunk/LayoutTests/ChangeLog	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/ChangeLog	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,3 +1,18 @@
+2021-01-11  Sam Weinig  <[email protected]>
+
+        Support lab(), lch(), gray() and color(lab ...) colors
+        https://bugs.webkit.org/show_bug.cgi?id=205675
+
+        Reviewed by Simon Fraser.
+
+        Original patch by Simon Fraser.
+
+        Parsing tests for lab/lch/gray colors.
+
+        * TestExpectations: Unskip lab/lch tests.
+        * fast/css/parsing-lab-colors-expected.txt: Added.
+        * fast/css/parsing-lab-colors.html: Added.
+
 2021-01-10  Antti Koivisto  <[email protected]>
 
         [LFC][Integration] Factor marked text style collection code out of InlineTextBox

Modified: trunk/LayoutTests/TestExpectations (271361 => 271362)


--- trunk/LayoutTests/TestExpectations	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/TestExpectations	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2017,22 +2017,6 @@
 webkit.org/b/148801 imported/w3c/web-platform-tests/css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht [ ImageOnlyFailure ]
 webkit.org/b/148801 imported/w3c/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht [ ImageOnlyFailure Pass ]
 
-# lab/lch not supported
-imported/w3c/web-platform-tests/css/css-color/lab-001.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-002.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-003.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-004.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-005.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-006.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lab-007.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-001.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-002.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-003.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-004.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-005.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-006.html [ Skip ]
-imported/w3c/web-platform-tests/css/css-color/lch-007.html [ Skip ]
-
 # Initial failures on the import of css-color
 imported/w3c/web-platform-tests/css/css-color/t31-color-text-a.xht [ ImageOnlyFailure ]
 

Added: trunk/LayoutTests/fast/css/parsing-lab-colors-expected.txt (0 => 271362)


--- trunk/LayoutTests/fast/css/parsing-lab-colors-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/parsing-lab-colors-expected.txt	2021-01-11 16:56:58 UTC (rev 271362)
@@ -0,0 +1,71 @@
+Test the parsing of lab, lch and gray colors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+lab()
+PASS computedStyle("background-color", "lab(0% 0 0)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 / 1)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 / 0.5)") is "lab(0% 0 0 / 0.5)"
+PASS computedStyle("background-color", "lab(20% 0 10/0.5)") is "lab(20% 0 10 / 0.5)"
+PASS computedStyle("background-color", "lab(20% 0 10/50%)") is "lab(20% 0 10 / 0.5)"
+PASS computedStyle("background-color", "lab(400% 0 10/50%)") is "lab(400% 0 10 / 0.5)"
+PASS computedStyle("background-color", "lab(50% -160 160)") is "lab(50% -160 160)"
+PASS computedStyle("background-color", "lab(50% -200 200)") is "lab(50% -200 200)"
+PASS computedStyle("background-color", "lab(0% 0 0 / -10%)") is "lab(0% 0 0 / 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 / 110%)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 / 300%)") is "lab(0% 0 0)"
+
+lch()
+PASS computedStyle("background-color", "lch(0% 0 0deg)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "lch(0% 0 0deg / 1)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "lch(0% 0 0deg / 0.5)") is "lab(0% 0 0 / 0.5)"
+PASS computedStyle("background-color", "lch(100% 230 0deg / 0.5)") is "lab(100% 230 0 / 0.5)"
+PASS computedStyle("background-color", "lch(20% 50 20deg/0.5)") is "lab(20% 46.98463 17.101006 / 0.5)"
+PASS computedStyle("background-color", "lch(20% 50 20deg/50%)") is "lab(20% 46.98463 17.101006 / 0.5)"
+PASS computedStyle("background-color", "lch(10% 20 20deg / -10%)") is "lab(10% 18.793852 6.8404026 / 0)"
+PASS computedStyle("background-color", "lch(10% 20 20deg / 110%)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(10% 20 1.28rad)") is "lab(10% 5.7343025 19.160316)"
+PASS computedStyle("background-color", "lch(10% 20 380deg)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(10% 20 -340deg)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(10% 20 740deg)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(10% 20 -700deg)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(0% 0 0 / 0.5)") is "lab(0% 0 0 / 0.5)"
+PASS computedStyle("background-color", "lch(10% 20 20 / 110%)") is "lab(10% 18.793852 6.8404026)"
+PASS computedStyle("background-color", "lch(10% 20 -700)") is "lab(10% 18.793852 6.8404026)"
+
+color(lab )
+PASS computedStyle("background-color", "color(lab 0% 0 0)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 / 1)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 / 0.5)") is "lab(0% 0 0 / 0.5)"
+PASS computedStyle("background-color", "color(lab 20% 0 10/0.5)") is "lab(20% 0 10 / 0.5)"
+PASS computedStyle("background-color", "color(lab 20% 0 10/50%)") is "lab(20% 0 10 / 0.5)"
+PASS computedStyle("background-color", "color(lab 400% 0 10/50%)") is "lab(400% 0 10 / 0.5)"
+PASS computedStyle("background-color", "color(lab 50% -160 160)") is "lab(50% -160 160)"
+PASS computedStyle("background-color", "color(lab 50% -200 200)") is "lab(50% -200 200)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 / -10%)") is "lab(0% 0 0 / 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 / 110%)") is "lab(0% 0 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 / 300%)") is "lab(0% 0 0)"
+
+Test invalid values
+PASS computedStyle("background-color", "lab(0 0 0)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(0% 0% 0)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 1)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(0% 0 0 10%)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(0% 0 0deg)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(0% 0% 0deg)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(40% 0 0deg)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(0 0 0 / 0.5)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(20% 10 10deg 10)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(20% 10 10deg 10 / 0.5)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0 0 0)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0% 0% 0)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 1)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0 10%)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0% 0 0deg)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 0% 0% 0deg)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color(lab 40% 0 0deg)") is "rgba(0, 0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/css/parsing-lab-colors.html (0 => 271362)


--- trunk/LayoutTests/fast/css/parsing-lab-colors.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/parsing-lab-colors.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -0,0 +1,110 @@
+<html>
+    <script src=""
+</head>
+<body>
+<script>
+    description("Test the parsing of lab, lch and gray colors.");
+
+    function computedStyle(property, value)
+    {
+        var div = document.createElement("div");
+        document.body.appendChild(div);
+        div.style.setProperty(property, value);
+        var computedValue = getComputedStyle(div).getPropertyValue(property);
+        document.body.removeChild(div);
+        return computedValue;
+    }
+
+    function innerStyle(property, value)
+    {
+        var div = document.createElement("div");
+        div.style.setProperty(property, value);
+        return div.style.getPropertyValue(property);
+    }
+
+    function testComputed(property, value, expected)
+    {
+        shouldBeEqualToString('computedStyle("' + property + '", "' + value + '")', expected);
+    }
+
+    function testInner(property, value, expected)
+    {
+        if (expected === null)
+            expected = "";
+        shouldBeEqualToString('innerStyle("' + property + '", "' + value + '")', expected);
+    }
+
+    debug('lab()');
+    testComputed("background-color", "lab(0% 0 0)", "lab(0% 0 0)");
+    testComputed("background-color", "lab(0% 0 0 / 1)", "lab(0% 0 0)");
+    testComputed("background-color", "lab(0% 0 0 / 0.5)", "lab(0% 0 0 / 0.5)");
+    testComputed("background-color", "lab(20% 0 10/0.5)", "lab(20% 0 10 / 0.5)");
+    testComputed("background-color", "lab(20% 0 10/50%)", "lab(20% 0 10 / 0.5)");
+    testComputed("background-color", "lab(400% 0 10/50%)", "lab(400% 0 10 / 0.5)");
+    testComputed("background-color", "lab(50% -160 160)", "lab(50% -160 160)");
+    testComputed("background-color", "lab(50% -200 200)", "lab(50% -200 200)");
+    testComputed("background-color", "lab(0% 0 0 / -10%)", "lab(0% 0 0 / 0)");
+    testComputed("background-color", "lab(0% 0 0 / 110%)", "lab(0% 0 0)");
+    testComputed("background-color", "lab(0% 0 0 / 300%)", "lab(0% 0 0)");
+
+    debug('');
+    debug('lch()');
+    testComputed("background-color", "lch(0% 0 0deg)", "lab(0% 0 0)");
+    testComputed("background-color", "lch(0% 0 0deg / 1)", "lab(0% 0 0)");
+    testComputed("background-color", "lch(0% 0 0deg / 0.5)", "lab(0% 0 0 / 0.5)");
+    testComputed("background-color", "lch(100% 230 0deg / 0.5)", "lab(100% 230 0 / 0.5)");
+    testComputed("background-color", "lch(20% 50 20deg/0.5)", "lab(20% 46.98463 17.101006 / 0.5)");
+    testComputed("background-color", "lch(20% 50 20deg/50%)", "lab(20% 46.98463 17.101006 / 0.5)");
+    testComputed("background-color", "lch(10% 20 20deg / -10%)", "lab(10% 18.793852 6.8404026 / 0)");
+    testComputed("background-color", "lch(10% 20 20deg / 110%)", "lab(10% 18.793852 6.8404026)");
+    testComputed("background-color", "lch(10% 20 1.28rad)", "lab(10% 5.7343025 19.160316)");
+    testComputed("background-color", "lch(10% 20 380deg)", "lab(10% 18.793852 6.8404026)");
+    testComputed("background-color", "lch(10% 20 -340deg)", "lab(10% 18.793852 6.8404026)");
+    testComputed("background-color", "lch(10% 20 740deg)", "lab(10% 18.793852 6.8404026)");
+    testComputed("background-color", "lch(10% 20 -700deg)", "lab(10% 18.793852 6.8404026)");
+    // hue (the third argument) can be either an angle or number, with number interpreted as degrees.
+    testComputed("background-color", "lch(0% 0 0 / 0.5)", "lab(0% 0 0 / 0.5)"); 
+    testComputed("background-color", "lch(10% 20 20 / 110%)", "lab(10% 18.793852 6.8404026)");
+    testComputed("background-color", "lch(10% 20 -700)", "lab(10% 18.793852 6.8404026)");
+
+    debug('');
+    debug('color(lab )');
+    testComputed("background-color", "color(lab 0% 0 0)", "lab(0% 0 0)");
+    testComputed("background-color", "color(lab 0% 0 0 / 1)", "lab(0% 0 0)");
+    testComputed("background-color", "color(lab 0% 0 0 / 0.5)", "lab(0% 0 0 / 0.5)");
+    testComputed("background-color", "color(lab 20% 0 10/0.5)", "lab(20% 0 10 / 0.5)");
+    testComputed("background-color", "color(lab 20% 0 10/50%)", "lab(20% 0 10 / 0.5)");
+    testComputed("background-color", "color(lab 400% 0 10/50%)", "lab(400% 0 10 / 0.5)");
+    testComputed("background-color", "color(lab 50% -160 160)", "lab(50% -160 160)");
+    testComputed("background-color", "color(lab 50% -200 200)", "lab(50% -200 200)");
+    testComputed("background-color", "color(lab 0% 0 0 / -10%)", "lab(0% 0 0 / 0)");
+    testComputed("background-color", "color(lab 0% 0 0 / 110%)", "lab(0% 0 0)");
+    testComputed("background-color", "color(lab 0% 0 0 / 300%)", "lab(0% 0 0)");
+
+    debug('');
+    debug('Test invalid values');
+    testComputed("background-color", "lab(0 0 0)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(0% 0% 0)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(0% 0 0 1)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(0% 0 0 10%)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(0% 0 0deg)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(0% 0% 0deg)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lab(40% 0 0deg)", "rgba(0, 0, 0, 0)");
+
+    testComputed("background-color", "lch(0 0 0 / 0.5)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lch(20% 10 10deg 10)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "lch(20% 10 10deg 10 / 0.5)", "rgba(0, 0, 0, 0)");
+
+    testComputed("background-color", "color(lab 0 0 0)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 0% 0% 0)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 0% 0 0 1)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 0% 0 0 10%)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 0% 0 0deg)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 0% 0% 0deg)", "rgba(0, 0, 0, 0)");
+    testComputed("background-color", "color(lab 40% 0 0deg)", "rgba(0, 0, 0, 0)");
+
+</script>
+    
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,3 +1,42 @@
+2021-01-11  Sam Weinig  <[email protected]>
+
+        Support lab(), lch(), gray() and color(lab ...) colors
+        https://bugs.webkit.org/show_bug.cgi?id=205675
+
+        Reviewed by Simon Fraser.
+
+        Update tests to use rectangles rather than text to make anti-aliasing differences
+        not cause failures. These changes will be upstreamed to the WebPlatformTests.
+
+        * web-platform-tests/css/css-color/lab-001-expected.html:
+        * web-platform-tests/css/css-color/lab-001.html:
+        * web-platform-tests/css/css-color/lab-002-expected.html:
+        * web-platform-tests/css/css-color/lab-002.html:
+        * web-platform-tests/css/css-color/lab-003-expected.html:
+        * web-platform-tests/css/css-color/lab-003.html:
+        * web-platform-tests/css/css-color/lab-004-expected.html:
+        * web-platform-tests/css/css-color/lab-004.html:
+        * web-platform-tests/css/css-color/lab-005-expected.html:
+        * web-platform-tests/css/css-color/lab-005.html:
+        * web-platform-tests/css/css-color/lab-006-expected.html:
+        * web-platform-tests/css/css-color/lab-006.html:
+        * web-platform-tests/css/css-color/lab-007-expected.html:
+        * web-platform-tests/css/css-color/lab-007.html:
+        * web-platform-tests/css/css-color/lch-001-expected.html:
+        * web-platform-tests/css/css-color/lch-001.html:
+        * web-platform-tests/css/css-color/lch-002-expected.html:
+        * web-platform-tests/css/css-color/lch-002.html:
+        * web-platform-tests/css/css-color/lch-003-expected.html:
+        * web-platform-tests/css/css-color/lch-003.html:
+        * web-platform-tests/css/css-color/lch-004-expected.html:
+        * web-platform-tests/css/css-color/lch-004.html:
+        * web-platform-tests/css/css-color/lch-005-expected.html:
+        * web-platform-tests/css/css-color/lch-005.html:
+        * web-platform-tests/css/css-color/lch-006-expected.html:
+        * web-platform-tests/css/css-color/lch-006.html:
+        * web-platform-tests/css/css-color/lch-007-expected.html:
+        * web-platform-tests/css/css-color/lch-007.html:
+
 2021-01-08  Alex Christensen  <[email protected]>
 
         REGRESSION(r267402): [ macOS iOS Release ] imported/w3c/web-platform-tests/user-timing/measure-l3.any.worker.html is a flaky failure

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,10 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Green text reference</title>
+<title>Green square reference</title>
 <style>
-    .test { color: #008000}
+    .test { background-color: #008000; width: 12em; height: 12em;}
 </style>
 <body>
-    <p class="test">Test passes if this text is green</p>
+    <p>Test passes if you see a green square, and no red.</p>
+    <div class="test"></div>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-001.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,11 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lab() with no alpha">
 <style>
-    .test {color: lab(46.277% -47.562 48.583)} /* green (sRGB #008000) converted to Lab */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: #008000; width: 12em; height: 6em; margin-bottom: 0}
+    .test { background-color: lab(46.277% -47.562 48.583)} /* green (sRGB #008000) converted to Lab */
 </style>
 <body>
-    <p class="test">Test passes if this text is green</p>
+    <p>Test passes if you see a green square, and no red.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,10 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Black text reference</title>
+<title>Black block reference</title>
 <style>
-    .test { color: #000000}
+    .test { background-color: #000000; width: 12em; height: 12em;}
 </style>
 <body>
-    <p class="test">Test passes if this text is black</p>
+    <p>Test passes if you see a black square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-002.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,12 +3,13 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lab() with no alpha">
 <style>
-    .test { color: red; }
-    .test { color: lab(0% 0 0)} /* black (sRGB #000000) converted to Lab */
+    .test { background-color: red; width: 12em; height: 12em; }
+    .test { background-color: lab(0% 0 0) } /* black (sRGB #000000) converted to Lab */
 </style>
 <body>
-    <p class="test">Test passes if this text is black</p>
+    <p>Test passes if you see a black square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,11 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>White text reference</title>
+<title>White block reference</title>
 <style>
-    .test { color: #FFFFFF; background-color: #333; padding: 3px}
+    body { background-color: grey; }
+    .test { background-color: #FFFFFF; width: 12em; height: 12em;}
 </style>
 <body>
-    <p class="test">Test passes if this text is white</p>
+    <p>Test passes if you see a white square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-003.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,12 +3,14 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lab() with no alpha">
 <style>
-    .test { color: red; background-color: #333; padding: 3px;}
-    .test { color: lab(100% 0 0);} /* white (sRGB #FFFFFF) converted to Lab */
+    body { background-color: grey; }
+    .test { background-color: red; width: 12em; height: 12em; }
+    .test { background-color: lab(100% 0 0);} /* white (sRGB #FFFFFF) converted to Lab */
 </style>
 <body>
-    <p class="test">Test passes if this text is white</p>
+    <p>Test passes if you see a white square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(75.62% 30.45% 47.56%)} /* lab(50 50 0) converted to sRGB */
+    .test { background-color:rgb(75.62% 30.45% 47.56%); width: 12em; height: 12em;} /* lab(50 50 0) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-004.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -6,12 +6,12 @@
 <link rel="match" href=""
 <meta name="assert" content="lab() with no alpha, positive a axis">
 <style>
-    .test { color: red; }
-    .test { color: lab(50% 50 0)}
-    .match { color: rgb(75.62%, 30.45%, 47.56%)} /* lab(50 50 0) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(75.62%, 30.45%, 47.56%); width: 12em; height: 6em; margin-bottom: 0}/* lab(50 50 0) converted to sRGB */
+    .test { background-color: lab(50% 50 0)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lab(70 -45 0) converted to sRGB */
+    .test { background-color: rgb(10.79%, 75.55%, 66.40%); width: 12em; height: 12em;} /* lab(70 -45 0) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-005.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -6,12 +6,12 @@
 <link rel="match" href=""
 <meta name="assert" content="lab() with no alpha, negative a axis">
 <style>
-    .test { color: red; }
-    .test { color: lab(70% -45 0)}
-    .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lab(70 -45 0) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(10.79%, 75.55%, 66.40%); width: 12em; height: 6em; margin-bottom: 0} /* lab(70 -45 0) converted to sRGB */
+    .test { background-color: lab(70% -45 0)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lab(70 0 70) converted to sRGB */
+    .test { background-color: rgb(76.62%, 66.36%, 5.58%); width: 12em; height: 12em;} /* lab(70 0 70) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-006.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -6,12 +6,12 @@
 <link rel="match" href=""
 <meta name="assert" content="lab() with no alpha, positive b axis">
 <style>
-    .test { color: red; }
-    .test { color: lab(70% 0 70)}
-    .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lab(70 0 70) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(76.62%, 66.36%, 5.58%); width: 12em; height: 6em; margin-bottom: 0} /* lab(70 0 70) converted to sRGB */
+    .test { background-color: lab(70% 0 70)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lab(55 0 -60) converted to sRGB */
+    .test { background-color: rgb(12.81%, 53.10%, 92.76%); width: 12em; height: 12em;} /* lab(55 0 -60) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lab-007.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -6,12 +6,12 @@
 <link rel="match" href=""
 <meta name="assert" content="lab() with no alpha, negative b axis">
 <style>
-    .test { color: red; }
-    .test { color: lab(55% 0 -60)}
-    .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lab(55 0 -60) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(12.81%, 53.10%, 92.76%); width: 12em; height: 6em; margin-bottom: 0} /* lab(55 0 -60) converted to sRGB */
+    .test { background-color: lab(55% 0 -60)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,11 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Green text reference</title>
+<title>Green block reference</title>
 <style>
+    .test { background-color: #008000; width: 12em; height: 12em;}
     .test { color: #008000}
 </style>
 <body>
-    <p class="test">Test passes if this text is green</p>
+    <p>Test passes if you see a green square, and no red.</p>
+    <div class="test"></div>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-001.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,11 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lch() with no alpha">
 <style>
-    .test {color: lch(46.277% 67.945 134.427)} /* green (sRGB #008000) converted to LCH */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: #008000; width: 12em; height: 6em; margin-bottom: 0}
+    .test { background-color: lch(46.277% 67.945 134.427)} /* green (sRGB #008000) converted to LCH */
 </style>
 <body>
-    <p class="test">Test passes if this text is green</p>
+    <p>Test passes if you see a green square, and no red.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,10 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Black text reference</title>
+<title>Black block reference</title>
 <style>
-    .test { color: #000000}
+    .test { background-color: #000000; width: 12em; height: 12em;}
 </style>
 <body>
-    <p class="test">Test passes if this text is black</p>
+    <p>Test passes if you see a black square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-002.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,12 +3,13 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lch() with no alpha">
 <style>
-    .test { color: red; }
-    .test { color: lch(0% 0 0)} /* black (sRGB #000000) converted to LCH */
+    .test { background-color: red; width: 12em; height: 12em; }
+    .test { background-color: lch(0% 0 0) } /* black (sRGB #000000) converted to Lab */
 </style>
 <body>
-    <p class="test">Test passes if this text is black</p>
+    <p>Test passes if you see a black square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,9 +1,11 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>White text reference</title>
+<title>White block reference</title>
 <style>
-    .test { color: #FFFFFF; background-color: #333; padding: 3px}
+    body { background-color: grey; }
+    .test { background-color: #FFFFFF; width: 12em; height: 12em;}
 </style>
 <body>
-    <p class="test">Test passes if this text is white</p>
+    <p>Test passes if you see a white square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-003.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -6,9 +6,11 @@
 <link rel="match" href=""
 <meta name="assert" content="lch() with no alpha">
 <style>
-    .test { color: red; background-color: #333; padding: 3px;}
-    .test { color: lch(100% 0 0);} /* white (sRGB #FFFFFF) converted to LCH */
+    body { background-color: grey; }
+    .test { background-color: red; width: 12em; height: 12em; }
+    .test { background-color: lch(100% 0 0);} /* white (sRGB #FFFFFF) converted to Lab */
 </style>
 <body>
-    <p class="test">Test passes if this text is white</p>
+    <p>Test passes if you see a white square, and no red.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(75.62% 30.45% 47.56%)} /* lab(50 50 0) converted to sRGB */
+    .test { background-color:rgb(75.62% 30.45% 47.56%); width: 12em; height: 12em;} /* lch(50 50 0) converted to sRGB (happens to be the same as lab(50 50 0)*/
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-004.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,15 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lch() with no alpha, positive a axis">
 <style>
-    .test { color: red; }
-    .test { color: lch(50% 50 0)}
-    .match { color: rgb(75.62%, 30.45%, 47.56%)} /* lch(50 50 0) converted to sRGB (happens to be the same as lab(50 50 0)*/
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(75.62%, 30.45%, 47.56%); width: 12em; height: 6em; margin-bottom: 0} /* lch(50 50 0) converted to sRGB (happens to be the same as lab(50 50 0)*/
+    .test { background-color: lch(50% 50 0)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lab(70 -45 0) converted to sRGB */
+    .test { background-color: rgb(10.79%, 75.55%, 66.40%); width: 12em; height: 12em;} /* lch(70 45 180) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-005.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,15 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lch() with no alpha, negative a axis">
 <style>
-    .test { color: red; }
-    .test { color: lch(70% 45 -180)}
-    .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lch(70 45 180) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(10.79%, 75.55%, 66.40%); width: 12em; height: 6em; margin-bottom: 0} /* lch(70 45 180) converted to sRGB */
+    .test { background-color: lch(70% 45 -180)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lab(70 0 70) converted to sRGB */
+    .test { background-color: rgb(76.62%, 66.36%, 5.58%); width: 12em; height: 12em;} /* lch(70 70 90) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-006.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,15 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lch() with no alpha, positive b axis">
 <style>
-    .test { color: red; }
-    .test { color: lch(70% 70 90)}
-    .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lch(70 70 90) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(76.62%, 66.36%, 5.58%); width: 12em; height: 6em; margin-bottom: 0} /* lch(70 70 90) converted to sRGB */
+    .test { background-color: lch(70% 70 90)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007-expected.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007-expected.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007-expected.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -2,10 +2,9 @@
 <meta charset="utf-8">
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <style>
-    .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lab(55 0 -60) converted to sRGB */
+    .test { background-color: rgb(27.38% 51.92% 91.25%); width: 12em; height: 12em;} /* lch(55% 58 275) converted to sRGB */
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="test"> </p>
 </body>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007.html (271361 => 271362)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007.html	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/lch-007.html	2021-01-11 16:56:58 UTC (rev 271362)
@@ -3,15 +3,15 @@
 <title>CSS Color 4: Specifying Lab and LCH</title>
 <link rel="author" title="Chris Lilley" href=""
 <link rel="help" href=""
-<link rel="match" href=""
+<link rel="match" href=""
 <meta name="assert" content="lab() with no alpha, negative b axis">
 <style>
-    .test { color: red; }
-    .test { color: lch(56% 58 275)}
-    .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lch(56 58 275) converted to sRGB */
+    .test { background-color: red; width: 12em; height: 6em; margin-top:0}
+    .ref { background-color: rgb(27.38% 51.92% 91.25%); width: 12em; height: 6em; margin-bottom: 0} /* lch(55% 58 275) converted to sRGB */
+    .test { background-color: lch(55% 58 275)} 
 </style>
 <body>
-    <p>Test passes if the two lines of filler text are the same color.</p>
-    <p class="test">Filler text. Filler text. Filler text. </p>
-    <p class="match">Filler text. Filler text. Filler text. </p>
+    <p>Test passes if you see a single square, and not two rectangles of different colors.</p>
+    <p class="ref"> </p>
+    <p class="test"> </p>
 </body>

Modified: trunk/Source/WebCore/ChangeLog (271361 => 271362)


--- trunk/Source/WebCore/ChangeLog	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/ChangeLog	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1,3 +1,120 @@
+2021-01-11  Sam Weinig  <[email protected]>
+
+        Support lab(), lch() and color(lab ...) colors
+        https://bugs.webkit.org/show_bug.cgi?id=205675
+
+        Reviewed by Simon Fraser.
+
+        Original patch by Simon Fraser.
+
+        This adds parsing support for lab(), lch() and color(lab ...) CSS colors 
+        (https://www.w3.org/TR/css-color-4/) and color type, conversion, and serialization 
+        support for Lab and color type and conversion support for LCH (we store these color 
+        canonically as Lab<float>, so serialization of LCH is never needed, much like HSL).
+
+        This change does not add support for the host platform layer (e.g. CoreGraphics, etc)
+        understanding of the Lab colorspace, and as such, when creating host color objects
+        (for instance via the cachedCGColor() helper) Lab<float> colors are converted to sRGB
+        first and then the host color is made. The ramification of this is for platforms that
+        use backingstores with greater than sRGB gamuts, Lab colors will be clampted to sRGB.
+        This should be rectified in a follow up change that adds proper creation of these host
+        objects but is being left off the initial change to limit changes.
+
+        Some of the imported tests have been updated to use rectangles rather than text to
+        avoid anti-aliasing issues and will be upstreamed to WPT following landing.
+
+        Tests: 
+            fast/css/parsing-lab-colors.html
+            imported/w3c/web-platform-tests/css/css-color/lab-001.html
+            imported/w3c/web-platform-tests/css/css-color/lab-002.html
+            imported/w3c/web-platform-tests/css/css-color/lab-003.html
+            imported/w3c/web-platform-tests/css/css-color/lab-004.html
+            imported/w3c/web-platform-tests/css/css-color/lab-005.html
+            imported/w3c/web-platform-tests/css/css-color/lab-006.html
+            imported/w3c/web-platform-tests/css/css-color/lab-007.html
+            imported/w3c/web-platform-tests/css/css-color/lch-001.html
+            imported/w3c/web-platform-tests/css/css-color/lch-002.html
+            imported/w3c/web-platform-tests/css/css-color/lch-003.html
+            imported/w3c/web-platform-tests/css/css-color/lch-004.html
+            imported/w3c/web-platform-tests/css/css-color/lch-005.html
+            imported/w3c/web-platform-tests/css/css-color/lch-006.html
+            imported/w3c/web-platform-tests/css/css-color/lch-007.html
+
+        * css/CSSValueKeywords.in:
+        Add "lab" and "lch" keywords.
+
+        * css/parser/CSSPropertyParser.cpp:
+        * css/parser/CSSPropertyParserHelpers.h:
+        * css/parser/CSSPropertyParserHelpers.cpp:
+        (WebCore::CSSPropertyParserHelpers::parseOptionalAlpha):
+        (WebCore::CSSPropertyParserHelpers::parseLabParameters):
+        (WebCore::CSSPropertyParserHelpers::parseLCHParameters):
+        (WebCore::CSSPropertyParserHelpers::parseGrayParameters):
+        (WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):
+        (WebCore::CSSPropertyParserHelpers::parseColorFunction):
+        Add support for parsing "lab(...)", "lch(...)", "gray(...)"
+        and "color(lab ...)", all of which create Lab<float> colors.
+
+        Also adds explicit UnitlessZeroQuirk flag to angle parsing to
+        allow parsing of newer specs that don't want to allow unitless zero
+        for angles. For now, I have left FIXMEs for the properties that
+        should probably disable it. This was not strictly necessary for this
+        change (as lch actaully allows unitless angles now), but it seems
+        like a solid move forward.
+
+        * platform/graphics/Color.h:
+        (WebCore::Color::Color):
+        Add overload of the Color constructor that takes a Lab<float> matching other
+        ColorSpace types.
+
+        * platform/graphics/ColorConversion.cpp:
+        (WebCore::convertFromD50WhitePointToD65WhitePoint):
+        (WebCore::convertFromD65WhitePointToD50WhitePoint):
+        (WebCore::toXYZA):
+        (WebCore::toLab):
+        (WebCore::toLCHA):
+        * platform/graphics/ColorConversion.h:
+        (WebCore::toLab):
+        (WebCore::toLCHA):
+        Add conversions to/from Lab to D65 white point XYZA (the white point we expect XYZA to be in), and conversion
+        from Lch to/from Lab. 
+
+        * platform/graphics/ColorSerialization.cpp:
+        (WebCore::serialization):
+        (WebCore::serializationForCSS):
+        (WebCore::serializationForHTML):
+        (WebCore::serializationForRenderTreeAsText):
+        * platform/graphics/ColorSerialization.h:
+        Add serialization for Lab colors. We currently always serialize using the lab()
+        notation, which appears to be correct for at least colors declared using lab(),
+        lch() and gray(). Unclear if it is correct for colors declared with color(lab ...).
+        Opened https://github.com/w3c/csswg-drafts/issues/5825 to track getting a resolution
+        for "color(lab ...)".
+
+        * platform/graphics/ColorSpace.cpp:
+        (WebCore::operator<<):
+        * platform/graphics/ColorSpace.h:
+        Add Lab as a ColorSpace and text stream dumping for it.
+
+        * platform/graphics/ColorTypes.h:
+        (WebCore::Lab::Lab):
+        (WebCore::asColorComponents):
+        (WebCore::asLab):
+        Add Lab color type.
+
+        (WebCore::LCHA::LCHA):
+        (WebCore::asLCHA):
+        Add LCHA color type.
+        
+        (WebCore::callWithColorType):
+        Add Lab to callWithColorType since it is now a valid ColorSpace.
+
+        * platform/graphics/cg/ColorSpaceCG.cpp:
+        (WebCore::labColorSpaceRef):
+        * platform/graphics/cg/ColorSpaceCG.h:
+        (WebCore::cachedCGColorSpace):
+        For now, return the sRGB color space to indicate to callers that they should do a conversion.
+
 2021-01-11  Yoshiaki Jitsukawa  <[email protected]>
 
         [PlayStation] Add MiniBrowser

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (271361 => 271362)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-01-11 16:56:58 UTC (rev 271362)
@@ -1264,6 +1264,8 @@
 rgba
 hsl
 hsla
+lab
+lch
 //color
 
 // transform

Modified: trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp (271361 => 271362)


--- trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -981,7 +981,8 @@
     if (keyword->valueID() != CSSValueOblique || range.atEnd())
         return CSSFontStyleRangeValue::create(keyword.releaseNonNull());
 
-    if (auto firstAngle = consumeAngle(range, cssParserMode)) {
+    // FIXME: This should probably not allow the unitless zero.
+    if (auto firstAngle = consumeAngle(range, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow)) {
         auto firstAngleInDegrees = firstAngle->doubleValue(CSSUnitType::CSS_DEG);
         if (!isFontStyleAngleInRange(firstAngleInDegrees))
             return nullptr;
@@ -990,7 +991,9 @@
             result->append(firstAngle.releaseNonNull());
             return CSSFontStyleRangeValue::create(keyword.releaseNonNull(), WTFMove(result));
         }
-        auto secondAngle = consumeAngle(range, cssParserMode);
+
+        // FIXME: This should probably not allow the unitless zero.
+        auto secondAngle = consumeAngle(range, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
         if (!secondAngle)
             return nullptr;
         auto secondAngleInDegrees = secondAngle->doubleValue(CSSUnitType::CSS_DEG);
@@ -1900,12 +1903,12 @@
     case CSSValueSkewX:
     case CSSValueSkewY:
     case CSSValueSkew:
-        parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid);
+        parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
         if (!parsedValue)
             return nullptr;
         if (functionId == CSSValueSkew && consumeCommaIncludingWhitespace(args)) {
             transformValue->append(*parsedValue);
-            parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid);
+            parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
             if (!parsedValue)
                 return nullptr;
         }
@@ -1956,7 +1959,7 @@
     case CSSValueRotate3d:
         if (!consumeNumbers(args, transformValue, 3) || !consumeCommaIncludingWhitespace(args))
             return nullptr;
-        parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid);
+        parsedValue = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
         if (!parsedValue)
             return nullptr;
         break;
@@ -2122,7 +2125,7 @@
 
         // Then, attempt to parse an angle. We try this as a fallback rather than the first option because
         // a unitless 0 angle would be consumed as an angle.
-        parsedValue = consumeAngle(range, cssParserMode, UnitlessQuirk::Forbid);
+        parsedValue = consumeAngle(range, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
         if (parsedValue) {
             // If we had already parsed an angle or numbers but not 3 in a row, this value is invalid.
             if (angle || (list->length() && list->length() != 3))
@@ -2242,7 +2245,7 @@
         return nullptr;
     }
     
-    return consumeAngle(range, mode, UnitlessQuirk::Allow);
+    return consumeAngle(range, mode, UnitlessQuirk::Allow, UnitlessZeroQuirk::Allow);
 }
 
 static RefPtr<CSSValue> consumePaintOrder(CSSParserTokenRange& range)

Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (271361 => 271362)


--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -296,12 +296,17 @@
     return nullptr;
 }
 
-inline bool shouldAcceptUnitlessValue(double value, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+inline bool shouldAcceptUnitlessValue(double value, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
 {
     // FIXME: Presentational HTML attributes shouldn't use the CSS parser for lengths
-    return value == 0
-        || isUnitLessValueParsingEnabledForMode(cssParserMode)
-        || (cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow);
+
+    if (value == 0 && unitlessZero == UnitlessZeroQuirk::Allow)
+        return true;
+
+    if (isUnitLessValueParsingEnabledForMode(cssParserMode))
+        return true;
+    
+    return cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow;
 }
 
 Optional<LengthRaw> consumeLengthRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
@@ -339,7 +344,7 @@
         return { { token.unitType(), range.consumeIncludingWhitespace().numericValue() } };
     }
     if (token.type() == NumberToken) {
-        if (!shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless)
+        if (!shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, UnitlessZeroQuirk::Allow)
             || (valueRange == ValueRangeNonNegative && token.numericValue() < 0))
             return WTF::nullopt;
         if (std::isinf(token.numericValue()))
@@ -464,7 +469,7 @@
     return nullptr;
 }
 
-Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
 {
     const CSSParserToken& token = range.peek();
     if (token.type() == DimensionToken) {
@@ -480,7 +485,7 @@
         }
     }
 
-    if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless))
+    if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
         return { { CSSUnitType::CSS_DEG, range.consumeIncludingWhitespace().numericValue() } };
 
     if (token.type() != FunctionToken)
@@ -490,7 +495,7 @@
     return calcParser.consumeAngleRaw();
 }
 
-RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
 {
     const CSSParserToken& token = range.peek();
     if (token.type() == FunctionToken) {
@@ -502,13 +507,13 @@
         return nullptr;
     }
 
-    if (auto angle = consumeAngleRaw(range, cssParserMode, unitless))
+    if (auto angle = consumeAngleRaw(range, cssParserMode, unitless, unitlessZero))
         return CSSValuePool::singleton().createValue(angle->value, angle->type);
 
     return nullptr;
 }
 
-static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
 {
     const CSSParserToken& token = range.peek();
     if (token.type() == DimensionToken) {
@@ -522,7 +527,7 @@
             return nullptr;
         }
     }
-    if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless))
+    if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
         return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG);
 
     if (token.type() == PercentageToken)
@@ -549,7 +554,7 @@
 {
     const CSSParserToken& token = range.peek();
     CSSUnitType unit = token.unitType();
-    bool acceptUnitless = token.type() == NumberToken && unitless == UnitlessQuirk::Allow && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless);
+    bool acceptUnitless = token.type() == NumberToken && unitless == UnitlessQuirk::Allow && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, UnitlessZeroQuirk::Allow);
     if (acceptUnitless)
         unit = CSSUnitType::CSS_MS;
     if (token.type() == DimensionToken || acceptUnitless) {
@@ -748,7 +753,7 @@
     ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId() == CSSValueHsla);
     CSSParserTokenRange args = consumeFunction(range);
     double angleInDegrees;
-    if (auto angle = consumeAngleRaw(args, cssParserMode, UnitlessQuirk::Forbid))
+    if (auto angle = consumeAngleRaw(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
         angleInDegrees = CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
     else {
         if (!consumeNumberRaw(args, angleInDegrees))
@@ -792,49 +797,158 @@
     return convertToComponentBytes(toSRGBA(HSLA<float> { static_cast<float>(colorArray[0]), static_cast<float>(colorArray[1]), static_cast<float>(colorArray[2]), static_cast<float>(alpha) }));
 }
 
-static Color parseColorFunctionParameters(CSSParserTokenRange& range)
+static Optional<float> parseOptionalAlpha(CSSParserTokenRange& range)
 {
-    ASSERT(range.peek().functionId() == CSSValueColor);
+    if (!consumeSlashIncludingWhitespace(range))
+        return 1.0f;
+
+    if (auto alphaParameter = consumePercentRaw(range, ValueRangeAll))
+        return clampTo<float>(*alphaParameter / 100.0, 0.0, 1.0);
+
+    double alphaParameter;
+    if (!consumeNumberRaw(range, alphaParameter, ValueRangeAll))
+        return WTF::nullopt;
+
+    return clampTo<float>(alphaParameter, 0.0, 1.0);
+}
+
+static Color parseLabParameters(CSSParserTokenRange& range)
+{
+    ASSERT(range.peek().functionId() == CSSValueLab);
     CSSParserTokenRange args = consumeFunction(range);
 
-    ColorSpace colorSpace;
-    switch (args.peek().id()) {
-    case CSSValueSRGB:
-        colorSpace = ColorSpace::SRGB;
-        break;
-    case CSSValueDisplayP3:
-        colorSpace = ColorSpace::DisplayP3;
-        break;
-    default:
+    auto lightness = consumePercentRaw(args, ValueRangeAll);
+    if (!lightness)
         return { };
+
+    double aValue;
+    if (!consumeNumberRaw(args, aValue, ValueRangeAll))
+        return { };
+
+    double bValue;
+    if (!consumeNumberRaw(args, bValue, ValueRangeAll))
+        return { };
+
+    auto alpha = parseOptionalAlpha(args);
+    if (!alpha)
+        return { };
+
+    if (!args.atEnd())
+        return { };
+
+    return Lab<float> { static_cast<float>(*lightness), static_cast<float>(aValue), static_cast<float>(bValue), *alpha };
+}
+
+static Color parseLCHParameters(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    ASSERT(range.peek().functionId() == CSSValueLch);
+    CSSParserTokenRange args = consumeFunction(range);
+
+    auto lightness = consumePercentRaw(args, ValueRangeAll);
+    if (!lightness)
+        return Color();
+
+    double chromaValue;
+    if (!consumeNumberRaw(args, chromaValue, ValueRangeAll))
+        return { };
+
+    double angleInDegrees;
+    if (auto hueValue = consumeAngleRaw(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
+        angleInDegrees = CSSPrimitiveValue::computeDegrees(hueValue->type, hueValue->value);
+    else {
+        if (!consumeNumberRaw(args, angleInDegrees, ValueRangeAll))
+            return { };
     }
-    consumeIdent(args);
 
-    double colorChannels[4] = { 0, 0, 0, 1 };
+    angleInDegrees = fmod(angleInDegrees, 360.0);
+    if (angleInDegrees < 0.0)
+        angleInDegrees += 360.0;
+
+    auto alpha = parseOptionalAlpha(args);
+    if (!alpha)
+        return { };
+
+    if (!args.atEnd())
+        return { };
+
+    return toLab(LCHA<float> { static_cast<float>(*lightness), static_cast<float>(chromaValue), static_cast<float>(angleInDegrees), *alpha });
+}
+
+template<typename ColorType>
+static Color parseColorFunctionForSRGBOrDisplayP3Parameters(CSSParserTokenRange& args)
+{
+    ASSERT(args.peek().id() == CSSValueSRGB || args.peek().id() == CSSValueDisplayP3);
+    consumeIdentRaw(args);
+
+    double colorChannels[3] = { 0, 0, 0 };
     for (int i = 0; i < 3; ++i) {
         double value;
         if (consumeNumberRaw(args, value))
-            colorChannels[i] = std::max(0.0, std::min(1.0, value));
+            colorChannels[i] = value;
         else
             break;
     }
 
-    if (consumeSlashIncludingWhitespace(args)) {
-        auto alphaParameter = consumePercent(args, ValueRangeAll);
-        if (!alphaParameter)
-            alphaParameter = consumeNumber(args, ValueRangeAll);
-        if (!alphaParameter)
-            return { };
+    auto alpha = parseOptionalAlpha(args);
+    if (!alpha)
+        return { };
 
-        colorChannels[3] = std::max(0.0, std::min(1.0, alphaParameter->isPercentage() ? (alphaParameter->doubleValue() / 100) : alphaParameter->doubleValue()));
+    return ColorType { clampTo<float>(colorChannels[0], 0.0, 1.0), clampTo<float>(colorChannels[1], 0.0, 1.0), clampTo<float>(colorChannels[2], 0.0, 1.0), *alpha };
+}
+
+static Color parseColorFunctionForLabParameters(CSSParserTokenRange& args)
+{
+    ASSERT(args.peek().id() == CSSValueLab);
+    consumeIdentRaw(args);
+
+    auto lightness = consumePercentRaw(args, ValueRangeAll);
+    if (!lightness)
+        return { };
+
+    double aValue;
+    if (!consumeNumberRaw(args, aValue, ValueRangeAll))
+        return { };
+
+    double bValue;
+    if (!consumeNumberRaw(args, bValue, ValueRangeAll))
+        return { };
+
+    auto alpha = parseOptionalAlpha(args);
+    if (!alpha)
+        return { };
+
+    return Lab<float> { static_cast<float>(*lightness), static_cast<float>(aValue), static_cast<float>(bValue), *alpha };
+}
+
+static Color parseColorFunctionParameters(CSSParserTokenRange& range)
+{
+    ASSERT(range.peek().functionId() == CSSValueColor);
+    CSSParserTokenRange args = consumeFunction(range);
+
+    Color color;
+    switch (args.peek().id()) {
+    case CSSValueSRGB:
+        color = parseColorFunctionForSRGBOrDisplayP3Parameters<SRGBA<float>>(args);
+        break;
+    case CSSValueDisplayP3:
+        color = parseColorFunctionForSRGBOrDisplayP3Parameters<DisplayP3<float>>(args);
+        break;
+    case CSSValueLab:
+        color = parseColorFunctionForLabParameters(args);
+        break;
+    default:
+        return { };
     }
 
+    if (!color.isValid())
+        return { };
+
     // FIXME: Support the comma-separated list of fallback color values.
 
     if (!args.atEnd())
         return { };
 
-    return Color { ColorComponents { static_cast<float>(colorChannels[0]), static_cast<float>(colorChannels[1]), static_cast<float>(colorChannels[2]), static_cast<float>(colorChannels[3]) }, colorSpace };
+    return color;
 }
 
 static Optional<SRGBA<uint8_t>> parseHexColor(CSSParserTokenRange& range, bool acceptQuirkyColors)
@@ -888,6 +1002,12 @@
     case CSSValueHsla:
         color = parseHSLParameters(colorRange, cssParserMode);
         break;
+    case CSSValueLab:
+        color = parseLabParameters(colorRange);
+        break;
+    case CSSValueLch:
+        color = parseLCHParameters(colorRange, cssParserMode);
+        break;
     case CSSValueColor:
         color = parseColorFunctionParameters(colorRange);
         break;
@@ -1272,7 +1392,7 @@
     
     auto consumeStopPosition = [&] {
         return gradient.gradientType() == CSSConicGradient
-            ? consumeAngleOrPercent(range, mode, ValueRangeAll, UnitlessQuirk::Forbid)
+            ? consumeAngleOrPercent(range, mode, ValueRangeAll, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow)
             : consumeLengthOrPercent(range, mode, ValueRangeAll);
     };
 
@@ -1446,7 +1566,7 @@
     RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, gradientType);
 
     bool expectComma = true;
-    RefPtr<CSSPrimitiveValue> angle = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid);
+    RefPtr<CSSPrimitiveValue> angle = consumeAngle(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
     if (angle)
         result->setAngle(angle.releaseNonNull());
     else if (gradientType == CSSPrefixedLinearGradient || consumeIdent<CSSValueTo>(args)) {
@@ -1482,7 +1602,8 @@
     bool expectComma = false;
     if (args.peek().type() == IdentToken) {
         if (consumeIdent<CSSValueFrom>(args)) {
-            auto angle = consumeAngle(args, context.mode, UnitlessQuirk::Forbid);
+            // FIXME: Unlike linear-gradient, conic-gradients are not specified to allow unitless 0 angles - https://www.w3.org/TR/css-images-4/#valdef-conic-gradient-angle.
+            auto angle = consumeAngle(args, context.mode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
             if (!angle)
                 return nullptr;
             result->setAngle(WTFMove(angle));
@@ -1782,7 +1903,7 @@
             return filterValue;
 
         if (filterType == CSSValueHueRotate)
-            parsedValue = consumeAngle(args, context.mode, UnitlessQuirk::Forbid);
+            parsedValue = consumeAngle(args, context.mode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow);
         else if (filterType == CSSValueBlur)
             parsedValue = consumeLength(args, HTMLStandardMode, ValueRangeNonNegative);
         else {
@@ -1957,7 +2078,8 @@
     ASSERT(ident == CSSValueOblique);
 #if ENABLE(VARIATION_FONTS)
     if (!range.atEnd()) {
-        if (auto angle = consumeAngleRaw(range, cssParserMode)) {
+        // FIXME: This angle does specify that unitless 0 is allowed - see https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
+        if (auto angle = consumeAngleRaw(range, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow)) {
             if (isFontStyleAngleInRange(CSSPrimitiveValue::computeDegrees(angle->type, angle->value)))
                 return { { CSSValueOblique, WTFMove(angle) } };
             return WTF::nullopt;

Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h (271361 => 271362)


--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -55,6 +55,7 @@
 CSSParserTokenRange consumeFunction(CSSParserTokenRange&);
 
 enum class UnitlessQuirk { Allow, Forbid };
+enum class UnitlessZeroQuirk { Allow, Forbid };
 enum class AllowXResolutionUnit { Allow, Forbid };
 
 struct AngleRaw {
@@ -81,8 +82,8 @@
 RefPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange&, ValueRange);
 Optional<LengthOrPercentRaw> consumeLengthOrPercentRaw(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
 RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
-Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid);
-RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid);
+Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid, UnitlessZeroQuirk = UnitlessZeroQuirk::Forbid);
+RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid, UnitlessZeroQuirk = UnitlessZeroQuirk::Forbid);
 RefPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
 RefPtr<CSSPrimitiveValue> consumeResolution(CSSParserTokenRange&, AllowXResolutionUnit = AllowXResolutionUnit::Forbid);
 

Modified: trunk/Source/WebCore/platform/graphics/Color.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/Color.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/Color.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -58,6 +58,7 @@
 //    - 4x float (0-1) sRGBA, stored in a reference counted sub-object
 //    - 4x float (0-1) Linear sRGBA, stored in a reference counted sub-object
 //    - 4x float (0-1) DisplayP3, stored in a reference counted sub-object
+//    - 4x float (0-1) Lab, stored in a reference counted sub-object
 //
 // Additionally, the inline 8-bit sRGBA can have an optional "semantic" bit set on it,
 // which indicates the color originated from a CSS semantic color name.

Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.cpp (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorConversion.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -28,7 +28,7 @@
 
 #include "ColorComponents.h"
 #include "ColorMatrix.h"
-#include "ColorTypes.h"
+#include <wtf/MathExtras.h>
 
 namespace WebCore {
 
@@ -134,6 +134,119 @@
     return asXYZA(linearDisplayP3ToXYZMatrix.transformedColorComponents(asColorComponents(color)));
 }
 
+static XYZA<float> convertFromD50WhitePointToD65WhitePoint(const XYZA<float>& color)
+{
+    // http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
+    constexpr ColorMatrix<3, 3> D50ToD65Matrix {
+         0.9555766f, -0.0230393f, 0.0631636f,
+        -0.0282895f,  1.0099416f, 0.0210077f,
+         0.0122982f, -0.0204830f, 1.3299098f
+    };
+    return asXYZA(D50ToD65Matrix.transformedColorComponents(asColorComponents(color)));
+}
+
+static XYZA<float> convertFromD65WhitePointToD50WhitePoint(const XYZA<float>& color)
+{
+    // http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
+    constexpr ColorMatrix<3, 3> D65ToD50Matrix {
+         1.0478112f, 0.0228866f, -0.0501270f,
+         0.0295424f, 0.9904844f, -0.0170491f,
+        -0.0092345f, 0.0150436f,  0.7521316f
+    };
+    return asXYZA(D65ToD50Matrix.transformedColorComponents(asColorComponents(color)));
+}
+
+static constexpr float LABe = 216.0f / 24389.0f;
+static constexpr float LABk = 24389.0f / 27.0f;
+static constexpr float D50WhiteValues[] = { 0.96422f, 1.0f, 0.82521f };
+
+XYZA<float> toXYZA(const Lab<float>& color)
+{
+    float f1 = (color.lightness + 16.0f) / 116.0f;
+    float f0 = f1 + (color.a / 500.0f);
+    float f2 = f1 - (color.b / 200.0f);
+
+    auto computeXAndZ = [](float t) {
+        float tCubed = t * t * t;
+        if (tCubed > LABe)
+            return tCubed;
+
+        return (116.0f * t - 16.0f) / LABk;
+    };
+
+    auto computeY = [](float t) {
+        if (t > (LABk * LABe)) {
+            float value = (t + 16.0) / 116.0;
+            return value * value * value;
+        }
+
+        return t / LABk;
+    };
+
+    float x = D50WhiteValues[0] * computeXAndZ(f0);
+    float y = D50WhiteValues[1] * computeY(color.lightness);
+    float z = D50WhiteValues[2] * computeXAndZ(f2);
+
+    XYZA<float> result { x, y, z, color.alpha };
+
+    // We expect XYZA colors to be using the D65 white point, unlike Lab, which uses a
+    // D50 white point, so as a final step, use the Bradford transform to convert the
+    // resulting XYZA color to a D65 white point.
+    return convertFromD50WhitePointToD65WhitePoint(result);
+}
+
+Lab<float> toLab(const XYZA<float>& color)
+{
+    // We expect XYZA colors to be using the D65 white point, unlike Lab, which uses a
+    // D50 white point, so as a first step, use the Bradford transform to convert the
+    // incoming XYZA color to D50 white point.
+    auto colorWithD50WhitePoint = convertFromD65WhitePointToD50WhitePoint(color);
+
+    float x = colorWithD50WhitePoint.x / D50WhiteValues[0];
+    float y = colorWithD50WhitePoint.y / D50WhiteValues[1];
+    float z = colorWithD50WhitePoint.z / D50WhiteValues[2];
+
+    auto fTransform = [](float value) {
+        return value > LABe ? std::cbrt(value) : (LABk * value + 16.0f) / 116.0f;
+    };
+
+    float f0 = fTransform(x);
+    float f1 = fTransform(y);
+    float f2 = fTransform(z);
+
+    float lightness = (116.0f * f1) - 16.0f;
+    float a = 500.0f * (f0 - f1);
+    float b = 200.0f * (f1 - f2);
+
+    return { lightness, a, b, colorWithD50WhitePoint.alpha };
+}
+
+LCHA<float> toLCHA(const Lab<float>& color)
+{
+    // https://www.w3.org/TR/css-color-4/#lab-to-lch
+    float hue = rad2deg(atan2(color.b, color.a));
+
+    return {
+        color.lightness,
+        std::hypot(color.a, color.b),
+        hue >= 0 ? hue : hue + 360,
+        color.alpha
+    };
+}
+
+Lab<float> toLab(const LCHA<float>& color)
+{
+    // https://www.w3.org/TR/css-color-4/#lch-to-lab
+    float hueAngleRadians = deg2rad(color.hue);
+
+    return {
+        color.lightness,
+        color.chroma * std::cos(hueAngleRadians),
+        color.chroma * std::sin(hueAngleRadians),
+        color.alpha
+    };
+}
+
 HSLA<float> toHSLA(const SRGBA<float>& color)
 {
     // http://en.wikipedia.org/wiki/HSL_color_space.
@@ -263,6 +376,16 @@
     return toDisplayP3(toLinearDisplayP3(color));
 }
 
+XYZA<float> toXYZA(const LCHA<float>& color)
+{
+    return toXYZA(toLab(color));
+}
+
+LCHA<float> toLCHA(const XYZA<float>& color)
+{
+    return toLCHA(toLab(color));
+}
+
 XYZA<float> toXYZA(const HSLA<float>& color)
 {
     return toXYZA(toSRGBA(color));

Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorConversion.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -71,6 +71,20 @@
 WEBCORE_EXPORT DisplayP3<float> toDisplayP3(const LinearDisplayP3<float>&);
 
 
+// Lab
+WEBCORE_EXPORT XYZA<float> toXYZA(const Lab<float>&);
+WEBCORE_EXPORT Lab<float> toLab(const XYZA<float>&);
+// Additions
+WEBCORE_EXPORT LCHA<float> toLCHA(const Lab<float>&);
+
+
+// LCHA
+WEBCORE_EXPORT XYZA<float> toXYZA(const LCHA<float>&);
+WEBCORE_EXPORT LCHA<float> toLCHA(const XYZA<float>&);
+// Additions
+WEBCORE_EXPORT Lab<float> toLab(const LCHA<float>&);
+
+
 // HSLA
 WEBCORE_EXPORT XYZA<float> toXYZA(const HSLA<float>&);
 WEBCORE_EXPORT HSLA<float> toHSLA(const XYZA<float>&);
@@ -91,6 +105,8 @@
 constexpr LinearSRGBA<float> toLinearSRGBA(const LinearSRGBA<float>& color) { return color; }
 constexpr DisplayP3<float> toDisplayP3(const DisplayP3<float>& color) { return color; }
 constexpr LinearDisplayP3<float> toLinearDisplayP3(const LinearDisplayP3<float>& color) { return color; }
+constexpr Lab<float> toLab(const Lab<float>& color) { return color; }
+constexpr LCHA<float> toLCHA(const LCHA<float>& color) { return color; }
 constexpr HSLA<float> toHSLA(const HSLA<float>& color) { return color; }
 constexpr CMYKA<float> toCMYKA(const CMYKA<float>& color) { return color; }
 constexpr XYZA<float> toXYZA(const XYZA<float>& color) { return color; }
@@ -121,6 +137,16 @@
     return toLinearDisplayP3(toXYZA(color));
 }
 
+template<typename T> Lab<float> toLab(const T& color)
+{
+    return toLab(toXYZA(color));
+}
+
+template<typename T> LCHA<float> toLCHA(const T& color)
+{
+    return toLCHA(toXYZA(color));
+}
+
 template<typename T> HSLA<float> toHSLA(const T& color)
 {
     return toHSLA(toXYZA(color));

Modified: trunk/Source/WebCore/platform/graphics/ColorSerialization.cpp (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorSerialization.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorSerialization.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -96,6 +96,8 @@
         return "linear-srgb"_s;
     case ColorSpace::DisplayP3:
         return "display-p3"_s;
+    case ColorSpace::Lab:
+        return "lab"_s;
     }
 
     ASSERT_NOT_REACHED();
@@ -161,7 +163,28 @@
     return serialization(color);
 }
 
+// Lab<float> overloads
 
+String serializationForCSS(const Lab<float>& color)
+{
+    // https://www.w3.org/TR/css-color-4/#serializing-lab-lch
+
+    auto [c1, c2, c3, alpha] = color;
+    if (WTF::areEssentiallyEqual(alpha, 1.0f))
+        return makeString("lab(", c1, "% ", c2, ' ', c3, ')');
+    return makeString("lab(", c1, "% ", c2, ' ', c3, " / ", alpha, ')');
+}
+
+String serializationForHTML(const Lab<float>& color)
+{
+    return serializationForCSS(color);
+}
+
+String serializationForRenderTreeAsText(const Lab<float>& color)
+{
+    return serializationForCSS(color);
+}
+
 // Color overloads
 
 String serializationForCSS(const Color& color)

Modified: trunk/Source/WebCore/platform/graphics/ColorSerialization.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorSerialization.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorSerialization.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -32,6 +32,7 @@
 class Color;
 
 template<typename> struct DisplayP3;
+template<typename> struct Lab;
 template<typename> struct LinearSRGBA;
 template<typename> struct SRGBA;
 
@@ -55,6 +56,10 @@
 WEBCORE_EXPORT String serializationForHTML(const DisplayP3<float>&);
 WEBCORE_EXPORT String serializationForRenderTreeAsText(const DisplayP3<float>&);
 
+WEBCORE_EXPORT String serializationForCSS(const Lab<float>&);
+WEBCORE_EXPORT String serializationForHTML(const Lab<float>&);
+WEBCORE_EXPORT String serializationForRenderTreeAsText(const Lab<float>&);
+
 WEBCORE_EXPORT String serializationForCSS(const Color&);
 WEBCORE_EXPORT String serializationForHTML(const Color&);
 WEBCORE_EXPORT String serializationForRenderTreeAsText(const Color&);

Modified: trunk/Source/WebCore/platform/graphics/ColorSpace.cpp (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorSpace.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorSpace.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -42,6 +42,9 @@
     case ColorSpace::DisplayP3:
         ts << "DisplayP3";
         break;
+    case ColorSpace::Lab:
+        ts << "L*a*b";
+        break;
     }
     return ts;
 }

Modified: trunk/Source/WebCore/platform/graphics/ColorSpace.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorSpace.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorSpace.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -34,7 +34,8 @@
 enum class ColorSpace : uint8_t {
     SRGB,
     LinearRGB,
-    DisplayP3
+    DisplayP3,
+    Lab
 };
 
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ColorSpace);

Modified: trunk/Source/WebCore/platform/graphics/ColorTypes.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/ColorTypes.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/ColorTypes.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -247,6 +247,93 @@
 }
 
 
+template<typename T> struct Lab : ColorWithAlphaHelper<Lab<T>> {
+    using ComponentType = T;
+    static constexpr auto colorSpace = ColorSpace::Lab;
+
+    constexpr Lab(T lightness, T a, T b, T alpha = ComponentTraits<T>::maxValue)
+        : lightness { lightness }
+        , a { a }
+        , b { b }
+        , alpha { alpha }
+    {
+    }
+
+    constexpr Lab()
+        : Lab { ComponentTraits<T>::minValue, ComponentTraits<T>::minValue, ComponentTraits<T>::minValue, ComponentTraits<T>::minValue }
+    {
+    }
+
+    T lightness;
+    T a;
+    T b;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const Lab<T>& c)
+{
+    return { c.lightness, c.a, c.b, c.alpha };
+}
+
+template<typename T> constexpr Lab<T> asLab(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> constexpr bool operator==(const Lab<T>& a, const Lab<T>& b)
+{
+    return asColorComponents(a) == asColorComponents(b);
+}
+
+template<typename T> constexpr bool operator!=(const Lab<T>& a, const Lab<T>& b)
+{
+    return !(a == b);
+}
+
+
+template<typename T> struct LCHA : ColorWithAlphaHelper<LCHA<T>> {
+    using ComponentType = T;
+
+    constexpr LCHA(T lightness, T chroma, T hue, T alpha = ComponentTraits<T>::maxValue)
+        : lightness { lightness }
+        , chroma { chroma }
+        , hue { hue }
+        , alpha { alpha }
+    {
+    }
+
+    constexpr LCHA()
+        : LCHA { ComponentTraits<T>::minValue, ComponentTraits<T>::minValue, ComponentTraits<T>::minValue, ComponentTraits<T>::minValue }
+    {
+    }
+
+    T lightness;
+    T chroma;
+    T hue;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const LCHA<T>& c)
+{
+    return { c.lightness, c.chroma, c.hue, c.alpha };
+}
+
+template<typename T> constexpr LCHA<T> asLCHA(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> constexpr bool operator==(const LCHA<T>& a, const LCHA<T>& b)
+{
+    return asColorComponents(a) == asColorComponents(b);
+}
+
+template<typename T> constexpr bool operator!=(const LCHA<T>& a, const LCHA<T>& b)
+{
+    return !(a == b);
+}
+
+
 template<typename T> struct HSLA : ColorWithAlphaHelper<HSLA<T>> {
     using ComponentType = T;
 
@@ -379,6 +466,8 @@
         return std::invoke(std::forward<Functor>(functor), asLinearSRGBA(components));
     case ColorSpace::DisplayP3:
         return std::invoke(std::forward<Functor>(functor), asDisplayP3(components));
+    case ColorSpace::Lab:
+        return std::invoke(std::forward<Functor>(functor), asLab(components));
     }
 
     ASSERT_NOT_REACHED();

Modified: trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp	2021-01-11 16:56:58 UTC (rev 271362)
@@ -82,6 +82,12 @@
     return displayP3ColorSpace;
 }
 
+CGColorSpaceRef labColorSpaceRef()
+{
+    // FIXME: Add support for conversion to Lab on supported platforms.
+    return sRGBColorSpaceRef();
+}
+
 CGColorSpaceRef extendedSRGBColorSpaceRef()
 {
     static CGColorSpaceRef extendedSRGBColorSpace;

Modified: trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h (271361 => 271362)


--- trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h	2021-01-11 16:44:31 UTC (rev 271361)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h	2021-01-11 16:56:58 UTC (rev 271362)
@@ -34,6 +34,7 @@
 WEBCORE_EXPORT CGColorSpaceRef sRGBColorSpaceRef();
 WEBCORE_EXPORT CGColorSpaceRef linearRGBColorSpaceRef();
 WEBCORE_EXPORT CGColorSpaceRef displayP3ColorSpaceRef();
+WEBCORE_EXPORT CGColorSpaceRef labColorSpaceRef();
 WEBCORE_EXPORT CGColorSpaceRef extendedSRGBColorSpaceRef();
 
 static inline CGColorSpaceRef cachedCGColorSpace(ColorSpace colorSpace)
@@ -45,6 +46,8 @@
         return linearRGBColorSpaceRef();
     case ColorSpace::DisplayP3:
         return displayP3ColorSpaceRef();
+    case ColorSpace::Lab:
+        return labColorSpaceRef();
     }
     ASSERT_NOT_REACHED();
     return sRGBColorSpaceRef();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to