Diff
Modified: trunk/LayoutTests/ChangeLog (289395 => 289396)
--- trunk/LayoutTests/ChangeLog 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/ChangeLog 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1,3 +1,13 @@
+2022-02-08 Sam Weinig <wei...@apple.com>
+
+ Conversion to a color space with a smaller gamut should perform gamut mapping
+ https://bugs.webkit.org/show_bug.cgi?id=236200
+
+ Reviewed by Darin Adler.
+
+ * platform/gtk/TestExpectations:
+ Add more tests that are only failing on the GTK bots due to a small floating point issues that needs further investigation.
+
2022-02-08 Youenn Fablet <you...@apple.com>
LibWebRTCCodecs SharedVideoFrameWriters can deadlock in case of GPUProcess crash
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1,3 +1,22 @@
+2022-02-08 Sam Weinig <wei...@apple.com>
+
+ Conversion to a color space with a smaller gamut should perform gamut mapping
+ https://bugs.webkit.org/show_bug.cgi?id=236200
+
+ Reviewed by Darin Adler.
+
+ Update tests to include more examples that force gamut mapping and update the results
+ of a few existing ones to account for the new algorithm.
+
+ * web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt:
+ * web-platform-tests/css/css-color/parsing/color-mix-computed.html:
+ * web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt:
+ * web-platform-tests/css/css-color/parsing/color-mix-valid.html:
+ * web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt:
+ * web-platform-tests/css/css-color/parsing/relative-color-computed.html:
+ * web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt:
+ * web-platform-tests/css/css-color/parsing/relative-color-valid.html:
+
2022-02-07 Chris Dumez <cdu...@apple.com>
Add support for sharing Shared Workers (including across WebProcesses)
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt 2022-02-08 18:57:30 UTC (rev 289396)
@@ -62,6 +62,15 @@
PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))'
PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))'
PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))'
+PASS Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))'
PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))'
PASS Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))'
@@ -125,6 +134,15 @@
PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))'
PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))'
PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))'
+PASS Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
+PASS Property color value 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
PASS Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))'
PASS Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))'
PASS Property color value 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))'
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html 2022-02-08 18:57:30 UTC (rev 289396)
@@ -97,7 +97,17 @@
test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`));
test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
+ test_computed_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_computed_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_computed_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_computed_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_computed_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
+
test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
test_computed_value(`color`, `color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
@@ -170,6 +180,16 @@
test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`));
test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
+ test_computed_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_computed_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_computed_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_computed_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_computed_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
+
for (const colorSpace of [ "lch", "oklch" ]) {
test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`);
test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg) 25%, ${colorSpace}(50% 60 70deg))`, `${colorSpace}(40% 50 60)`);
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt 2022-02-08 18:57:30 UTC (rev 289396)
@@ -62,6 +62,15 @@
PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value
PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value
PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value
PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value
PASS e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value
@@ -125,6 +134,15 @@
PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value
PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value
PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
+PASS e.style['color'] = "color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value
PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value
PASS e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html 2022-02-08 18:57:30 UTC (rev 289396)
@@ -97,7 +97,17 @@
test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`));
test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
+ test_valid_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_valid_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_valid_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_valid_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_valid_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
+
test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
test_valid_value(`color`, `color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
@@ -170,6 +180,16 @@
test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`));
test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
+ test_valid_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_valid_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_valid_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_valid_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_valid_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
+
for (const colorSpace of [ "lch", "oklch" ]) {
test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`);
test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg) 25%, ${colorSpace}(50% 60 70deg))`, `${colorSpace}(40% 50 60)`);
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt 2022-02-08 18:57:30 UTC (rev 289396)
@@ -5,6 +5,14 @@
PASS Property color value 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)'
PASS Property color value 'rgb(from rgb(from rebeccapurple r g b) r g b)'
PASS Property color value 'rgb(from color(display-p3 0 1 0) r g b / alpha)'
+PASS Property color value 'rgb(from lab(100% 104.3 -50.9) r g b)'
+PASS Property color value 'rgb(from lab(0% 104.3 -50.9) r g b)'
+PASS Property color value 'rgb(from lch(100% 116 334) r g b)'
+PASS Property color value 'rgb(from lch(0% 116 334) r g b)'
+PASS Property color value 'rgb(from oklab(100% 0.365 -0.16) r g b)'
+PASS Property color value 'rgb(from oklab(0% 0.365 -0.16) r g b)'
+PASS Property color value 'rgb(from oklch(100% 0.399 336.3) r g b)'
+PASS Property color value 'rgb(from oklch(0% 0.399 336.3) r g b)'
PASS Property color value 'rgb(from rebeccapurple 0 0 0)'
PASS Property color value 'rgb(from rebeccapurple 0 0 0 / 0)'
PASS Property color value 'rgb(from rebeccapurple 0 g b / alpha)'
@@ -74,6 +82,14 @@
PASS Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)'
PASS Property color value 'hsl(from hsl(from rebeccapurple h s l) h s l)'
PASS Property color value 'hsl(from color(display-p3 0 1 0) h s l / alpha)'
+PASS Property color value 'hsl(from lab(100% 104.3 -50.9) h s l)'
+PASS Property color value 'hsl(from lab(0% 104.3 -50.9) h s l)'
+PASS Property color value 'hsl(from lch(100% 116 334) h s l)'
+PASS Property color value 'hsl(from lch(0% 116 334) h s l)'
+PASS Property color value 'hsl(from oklab(100% 0.365 -0.16) h s l)'
+PASS Property color value 'hsl(from oklab(0% 0.365 -0.16) h s l)'
+PASS Property color value 'hsl(from oklch(100% 0.399 336.3) h s l)'
+PASS Property color value 'hsl(from oklch(0% 0.399 336.3) h s l)'
PASS Property color value 'hsl(from rebeccapurple 0 0% 0%)'
PASS Property color value 'hsl(from rebeccapurple 0deg 0% 0%)'
PASS Property color value 'hsl(from rebeccapurple 0 0% 0% / 0)'
@@ -128,6 +144,14 @@
PASS Property color value 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)'
PASS Property color value 'hwb(from hwb(from rebeccapurple h w b) h w b)'
PASS Property color value 'hwb(from color(display-p3 0 1 0) h w b / alpha)'
+PASS Property color value 'hwb(from lab(100% 104.3 -50.9) h w b)'
+PASS Property color value 'hwb(from lab(0% 104.3 -50.9) h w b)'
+PASS Property color value 'hwb(from lch(100% 116 334) h w b)'
+PASS Property color value 'hwb(from lch(0% 116 334) h w b)'
+PASS Property color value 'hwb(from oklab(100% 0.365 -0.16) h w b)'
+PASS Property color value 'hwb(from oklab(0% 0.365 -0.16) h w b)'
+PASS Property color value 'hwb(from oklch(100% 0.399 336.3) h w b)'
+PASS Property color value 'hwb(from oklch(0% 0.399 336.3) h w b)'
PASS Property color value 'hwb(from rebeccapurple 0 0% 0%)'
PASS Property color value 'hwb(from rebeccapurple 0deg 0% 0%)'
PASS Property color value 'hwb(from rebeccapurple 0 0% 0% / 0)'
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html 2022-02-08 18:57:30 UTC (rev 289396)
@@ -33,8 +33,16 @@
// Test nesting relative colors.
test_computed_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_computed_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_computed_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_computed_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_computed_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_computed_value(`color`, `rgb(from rebeccapurple 0 0 0)`, `rgb(0, 0, 0)`);
@@ -131,8 +139,16 @@
// Test nesting relative colors.
test_computed_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_computed_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_computed_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_computed_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_computed_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_computed_value(`color`, `hsl(from rebeccapurple 0 0% 0%)`, `rgb(0, 0, 0)`);
@@ -204,8 +220,16 @@
// Test nesting relative colors.
test_computed_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_computed_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_computed_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_computed_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_computed_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_computed_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_computed_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_computed_value(`color`, `hwb(from rebeccapurple 0 0% 0%)`, `rgb(255, 0, 0)`);
@@ -342,7 +366,7 @@
// Test nesting relative colors.
test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`);
- // Testing non-sRGB origin colors to see gamut clipping.
+ // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
test_computed_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`);
test_computed_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`);
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt 2022-02-08 18:57:30 UTC (rev 289396)
@@ -5,6 +5,14 @@
PASS e.style['color'] = "rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)" should set the property value
PASS e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value
PASS e.style['color'] = "rgb(from color(display-p3 0 1 0) r g b / alpha)" should set the property value
+PASS e.style['color'] = "rgb(from lab(100% 104.3 -50.9) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from lab(0% 104.3 -50.9) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from lch(100% 116 334) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from lch(0% 116 334) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from oklab(100% 0.365 -0.16) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from oklab(0% 0.365 -0.16) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from oklch(100% 0.399 336.3) r g b)" should set the property value
+PASS e.style['color'] = "rgb(from oklch(0% 0.399 336.3) r g b)" should set the property value
PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value
PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value
PASS e.style['color'] = "rgb(from rebeccapurple 0 g b / alpha)" should set the property value
@@ -74,6 +82,14 @@
PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)" should set the property value
PASS e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value
PASS e.style['color'] = "hsl(from color(display-p3 0 1 0) h s l / alpha)" should set the property value
+PASS e.style['color'] = "hsl(from lab(100% 104.3 -50.9) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from lab(0% 104.3 -50.9) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from lch(100% 116 334) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from lch(0% 116 334) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from oklab(100% 0.365 -0.16) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from oklab(0% 0.365 -0.16) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from oklch(100% 0.399 336.3) h s l)" should set the property value
+PASS e.style['color'] = "hsl(from oklch(0% 0.399 336.3) h s l)" should set the property value
PASS e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value
PASS e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value
PASS e.style['color'] = "hsl(from rebeccapurple 0 0% 0% / 0)" should set the property value
@@ -128,6 +144,14 @@
PASS e.style['color'] = "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)" should set the property value
PASS e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value
PASS e.style['color'] = "hwb(from color(display-p3 0 1 0) h w b / alpha)" should set the property value
+PASS e.style['color'] = "hwb(from lab(100% 104.3 -50.9) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from lab(0% 104.3 -50.9) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from lch(100% 116 334) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from lch(0% 116 334) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from oklab(100% 0.365 -0.16) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from oklab(0% 0.365 -0.16) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from oklch(100% 0.399 336.3) h w b)" should set the property value
+PASS e.style['color'] = "hwb(from oklch(0% 0.399 336.3) h w b)" should set the property value
PASS e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value
PASS e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value
PASS e.style['color'] = "hwb(from rebeccapurple 0 0% 0% / 0)" should set the property value
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html (289395 => 289396)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html 2022-02-08 18:57:30 UTC (rev 289396)
@@ -32,8 +32,16 @@
// Test nesting relative colors.
test_valid_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_valid_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_valid_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_valid_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_valid_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_valid_value(`color`, `rgb(from rebeccapurple 0 0 0)`, `rgb(0, 0, 0)`);
@@ -130,8 +138,16 @@
// Test nesting relative colors.
test_valid_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_valid_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_valid_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_valid_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_valid_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_valid_value(`color`, `hsl(from rebeccapurple 0 0% 0%)`, `rgb(0, 0, 0)`);
@@ -203,8 +219,16 @@
// Test nesting relative colors.
test_valid_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`);
- // Testing non-sRGB origin colors to see gamut clipping.
- test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`);
+ // Testing non-sRGB origin colors to see gamut mapping.
+ test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
+ test_valid_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
+ test_valid_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
+ test_valid_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
+ test_valid_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
+ test_valid_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
+ test_valid_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
// Testing replacement with 0.
test_valid_value(`color`, `hwb(from rebeccapurple 0 0% 0%)`, `rgb(255, 0, 0)`);
@@ -341,7 +365,7 @@
// Test nesting relative colors.
test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`);
- // Testing non-sRGB origin colors to see gamut clipping.
+ // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
test_valid_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`);
test_valid_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`);
Modified: trunk/LayoutTests/platform/gtk/TestExpectations (289395 => 289396)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1838,8 +1838,11 @@
webkit.org/b/230277 imported/w3c/web-platform-tests/css/css-transforms/3dtransform-and-filter-no-perspective-001.html [ ImageOnlyFailure ]
+webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/color-mix-non-srgb-001.html [ Failure ]
webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html [ Failure ]
webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html [ Failure ]
+webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html [ Failure ]
+webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html [ Failure ]
webkit.org/b/234782 imported/w3c/web-platform-tests/css/css-writing-modes/text-shadow-orientation-upright-001.html [ ImageOnlyFailure ]
Modified: trunk/Source/WebCore/ChangeLog (289395 => 289396)
--- trunk/Source/WebCore/ChangeLog 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Source/WebCore/ChangeLog 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1,3 +1,72 @@
+2022-02-08 Sam Weinig <wei...@apple.com>
+
+ Conversion to a color space with a smaller gamut should perform gamut mapping
+ https://bugs.webkit.org/show_bug.cgi?id=236200
+
+ Reviewed by Darin Adler.
+
+ CSS Color now defines that gamut mapping should happen when converting to an RGB color space
+ with bounded gamut that is smaller than the origin color's color space. Specifically, it
+ specifies the use of a new "CSS gamut mapping algorithm" https://drafts.csswg.org/css-color/#css-gamut-mapping
+ which implements a relative colorimetric intent mapping with colors inside the destination
+ gamut unchanged.
+
+ The previous behavior we implemented was to clip out of gamut colors to the gamut (e.g.
+ color(srgb 1.4 -0.2 .5) would become color(srgb 1 0 .5)) which can lead to very odd results.
+
+ To keep things simple, the gamut mapping has been incorporated directly into the main color
+ conversion pipeline, replacing the call to makeFromComponentsClampingExceptAlpha in toBounded()
+ with one implements the new algorithm. To accomadate this, the pipeline was modified so that
+ the matrix conversions now only happen to/from extended-linear and XYZ color types, rather than
+ the old behavior which allowed shortcuting from bounded-linear, which was ok because the clip
+ would result in the same value. Since conversion from bounded-linear to extended-linear is free
+ (just a type change, no conversion), the only additional cost here is the gamut mapping.
+
+ The implementation of the CSS gamut mapping algorithm itself is a naive iterative bisection
+ implementation based on the psuedo-code from the spec. As an optimization in the future, we should
+ consider implementing an analytic solution, which will be more complicated, but likely faster.
+
+ Currently, the only place where the effect of this new gamut mapping behavior will be visible is
+ via functions that explicitly convert to a bounded color space, specifically the CSS color-mix()
+ function and relative color syntax. Ultimately, we should also be using this to map CSS colors
+ to the output color space of the screen / HTML canvas, but finding the right place to do that
+ is not a part of this initial change.
+
+ * platform/graphics/ColorConversion.cpp:
+ (WebCore::ColorConversion<Lab<float>, XYZA<float, WhitePoint::D50>>::convert):
+ (WebCore::ColorConversion<OKLab<float>, XYZA<float, WhitePoint::D65>>::convert):
+ Add call to makeFromComponentsClampingExceptAlpha at the end of conversion to Lab/OKLab
+ as the conversion functions can produce lightness values just ever so less than 0.
+ In practice, only the lightness value is bounded, so it is the only thing that actually
+ gets clamped thanks to the constexpr nature of clampedComponent().
+
+ * platform/graphics/ColorConversion.h:
+ (WebCore::computeDeltaEOK):
+ Add implementation of the deltaEOK algorithm.
+
+ (WebCore::ClipGamutMapping::mapToBoundedGamut):
+ Add implementation of the degenerate gamut mapping algorithm.
+
+ (WebCore::CSSGamutMapping::mapToBoundedGamut):
+ Add implementation of the CSS gamut mapping algorithm.
+
+ (WebCore::ColorConversion::convert):
+ Add a new step to the main pipeline that explicitly handles bounds conversions to/from
+ extended-linear so that the matrix conversions can rely on always working in extended space.
+
+ (WebCore::ColorConversion::toBounded):
+ Replace call to clamp with call out to gamut mapping algorithm.
+
+ (WebCore::ColorConversion::handleMatrixConversion):
+ Replace makeFromComponentsClampingExceptAlpha with makeFromComponents now that all conversions
+ are in the extended space and clamping is no-op.
+
+ * platform/graphics/ColorTypes.h:
+ (WebCore::inGamut):
+ (WebCore::colorIfInGamut):
+ (WebCore::clipToGamut):
+ Add some helpers to check/convert/clip to the bounded gamut of RGB types.
+
2022-02-07 Yusuke Suzuki <ysuz...@apple.com>
[WebCore] JSValueInWrappedObject is not correct for concurrent GC
Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.cpp (289395 => 289396)
--- trunk/Source/WebCore/platform/graphics/ColorConversion.cpp 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.cpp 2022-02-08 18:57:30 UTC (rev 289396)
@@ -44,7 +44,7 @@
float hue = rad2deg(atan2(b, a));
float chroma = std::hypot(a, b);
- return { lightness, chroma, hue >= 0 ? hue : hue + 360, alpha };
+ return { lightness, chroma, hue >= 0.0f ? hue : hue + 360.0f, alpha };
}
template<typename LabLike, typename LCHLike>
@@ -272,7 +272,7 @@
float a = 500.0f * (f0 - f1);
float b = 200.0f * (f1 - f2);
- return { lightness, a, b, alpha };
+ return makeFromComponentsClampingExceptAlpha<Lab<float>>(lightness, a, b, alpha);
}
// MARK: LCH conversions.
@@ -358,7 +358,7 @@
auto [lightness, a, b] = NonLinearLMSToOKLab.transformedColorComponents(nonLinearLMS);
// 4. Transform lightness from unit lightness to percentage lightness.
- return { lightness * 100.0f, a, b, alpha };
+ return makeFromComponentsClampingExceptAlpha<OKLab<float>>(lightness * 100.0f, a, b, alpha);
}
// MARK: OKLCH conversions.
Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.h (289395 => 289396)
--- trunk/Source/WebCore/platform/graphics/ColorConversion.h 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.h 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
#pragma once
#include "ColorTypes.h"
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -139,7 +140,90 @@
}
};
+// MARK: DeltaE color difference algorithms.
+template<typename ColorType1, typename ColorType2> inline constexpr float computeDeltaEOK(ColorType1 color1, ColorType2 color2)
+{
+ // https://drafts.csswg.org/css-color/#color-difference-OK
+
+ auto [L1, a1, b1, alpha1] = convertColor<OKLab<float>>(color1).resolved();
+ auto [L2, a2, b2, alpha2] = convertColor<OKLab<float>>(color2).resolved();
+
+ auto deltaL = (L1 / 100.0f) - (L2 / 100.0f);
+ auto deltaA = a1 - a2;
+ auto deltaB = b1 - b2;
+
+ return std::hypot(deltaL, deltaA, deltaB);
+}
+
+// MARK: Gamut mapping algorithms.
+
+struct ClipGamutMapping {
+ template<typename ColorType> static auto mapToBoundedGamut(const ColorType& color) -> typename ColorType::BoundedCounterpart
+ {
+ return clipToGamut<typename ColorType::BoundedCounterpart>(color);
+ }
+};
+
+struct CSSGamutMapping {
+ // This implements the CSS gamut mapping algorithm (https://drafts.csswg.org/css-color/#css-gamut-mapping) for RGB
+ // colors that are out of gamut for a particular RGB color space. It implements a relative colorimetric intent mapping
+ // for colors that are outside the destionation gamut and leaves colors inside the destination gamut unchanged.
+
+ // A simple optimization over the psuedocode in the specification has been made to avoid unnecessary work in the
+ // main bisection loop by checking the gamut using the extended linear color space of the RGB family regardless of
+ // of whether the final type is gamma encoded or not. This avoids unnecessary gamma encoding for non final loops.
+
+ // FIXME: This is a naive iterative solution that works for any bounded RGB color space. This can be optimized by
+ // using an analytical solution that computes the exact intersection.
+
+ static constexpr float JND = 0.02f;
+
+ template<typename ColorType> static auto mapToBoundedGamut(const ColorType& color) -> typename ColorType::BoundedCounterpart
+ {
+ using BoundedColorType = typename ColorType::BoundedCounterpart;
+ using ExtendedLinearColorType = ExtendedLinearEncoded<typename BoundedColorType::ComponentType, typename BoundedColorType::Descriptor>;
+ using BoundedLinearColorType = BoundedLinearEncoded<typename BoundedColorType::ComponentType, typename BoundedColorType::Descriptor>;
+
+ auto resolvedColor = color.resolved();
+
+ if (auto result = colorIfInGamut<BoundedColorType>(resolvedColor))
+ return *result;
+
+ auto colorInOKLCHColorSpace = convertColor<OKLCHA<float>>(resolvedColor).resolved();
+
+ if (WTF::areEssentiallyEqual(colorInOKLCHColorSpace.lightness, 100.0f) || colorInOKLCHColorSpace.lightness > 100.0f)
+ return { 1.0, 1.0, 1.0, resolvedColor.alpha };
+ else if (WTF::areEssentiallyEqual(colorInOKLCHColorSpace.lightness, 0.0f))
+ return { 0.0f, 0.0f, 0.0f, resolvedColor.alpha };
+
+ float min = 0.0f;
+ float max = colorInOKLCHColorSpace.chroma;
+
+ while (true) {
+ auto chroma = (min + max) / 2.0f;
+
+ auto current = colorInOKLCHColorSpace;
+ current.chroma = chroma;
+
+ auto currentInExtendedLinearColorSpace = convertColor<ExtendedLinearColorType>(current).resolved();
+
+ if (inGamut<BoundedLinearColorType>(currentInExtendedLinearColorSpace)) {
+ min = chroma;
+ continue;
+ }
+
+ auto currentClippedToBoundedLinearColorSpace = clipToGamut<BoundedLinearColorType>(currentInExtendedLinearColorSpace);
+
+ auto deltaE = computeDeltaEOK(currentClippedToBoundedLinearColorSpace, current);
+ if (deltaE < JND)
+ return convertColor<BoundedColorType>(currentClippedToBoundedLinearColorSpace);
+
+ max = chroma;
+ }
+ }
+};
+
// Main conversion.
// ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
@@ -152,12 +236,16 @@
// │ │ │ │ │ │ │ │
// │ │ │ │ │ │ │ │ │ │
// │ ProPhotoRGB───────────────────┐ │ SRGB──────────────────────────┐ DisplayP3─────────────────────┐ A98RGB────────────────────────┐ Rec2020───────────────────────┐ │
-// │ │ │┌────────┐ ┌────────────────┐│ │ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │ │
-// │ ││ Linear │ │ LinearExtended ││ │ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ │
-// │ │ │└────────┘ └────────────────┘│ │ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │ │
-// │ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ │
+// │ │ │ ┌────────────────┐│ │ │ ┌────────────────┐│ │ ┌────────────────┐│ │ ┌────────────────┐│ │ ┌────────────────┐│ │ │
+// │ │ ┌─────▶︎ LinearExtended ││ │ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││ │
+// │ │ │ │ └────────▲───────┘│ │ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │ │
+// │ ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─ │
+// │ │┌────────┐ │ │ │ │┌────────┐ │ │ │┌────────┐ │ │ │┌────────┐ │ │ │┌────────┐ │ │ │
+// │ ││ Linear │ │ │ │ ││ Linear │ │ │ ││ Linear │ │ │ ││ Linear │ │ │ ││ Linear │ │ │ │
+// │ │└────▲───┘ │ │ │ │└────▲───┘ │ │ │└────▲───┘ │ │ │└────▲───┘ │ │ │└────▲───┘ │ │ │
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
// ┌───────────┐ │┌────────┐ ┌────────────────┐│ │ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ ┌───────────┐
-// │ Lab │ ││ Gamma │ │ GammaExtended ││ │ ││ Gamma │ │ GammaExtended ││ ││ Gamma │ │ GammaExtended ││ ││ Gamma │ │ GammaExtended ││ ││ Gamma │ │ GammaExtended ││ │ OKLab │
+// │ Lab │ ││ Gamma │─│ GammaExtended ││ │ ││ Gamma │─│ GammaExtended ││ ││ Gamma │─│ GammaExtended ││ ││ Gamma │─│ GammaExtended ││ ││ Gamma │─│ GammaExtended ││ │ OKLab │
// └─────▲─────┘ │└────────┘ └────────────────┘│ │ │└────▲───┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ └─────▲─────┘
// │ └─────────────────────────────┘ │ └─────┼───────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘ │
// │ │ ┌──┴──────────┐ │
@@ -195,7 +283,13 @@
else if constexpr (IsRGBGammaEncodedType<Output>)
return convertColor<Output>(convertColor<typename Output::LinearCounterpart>(color));
- // 5. At this point, Input and Output are each either Linear-RGB types (of different familes) or XYZA
+ // 5. Handle any bounds conversions for the Input and Output.
+ else if constexpr (IsRGBBoundedType<Input>)
+ return convertColor<Output>(convertColor<typename Input::ExtendedCounterpart>(color));
+ else if constexpr (IsRGBBoundedType<Output>)
+ return convertColor<Output>(convertColor<typename Output::ExtendedCounterpart>(color));
+
+ // 6. At this point, Input and Output are each either ExtendedLinear-RGB types (of different familes) or XYZA
// and therefore all additional conversion can happen via matrix transformation.
else
return handleMatrixConversion(color);
@@ -243,7 +337,7 @@
template<typename ColorType> static inline constexpr auto toBounded(const ColorType& color) -> typename ColorType::BoundedCounterpart
{
- return makeFromComponentsClampingExceptAlpha<typename ColorType::BoundedCounterpart>(asColorComponents(color.resolved()));
+ return CSSGamutMapping::mapToBoundedGamut(color);
}
static inline constexpr Output handleRGBFamilyConversion(const Input& color)
@@ -251,12 +345,17 @@
static_assert(IsSameRGBTypeFamily<Output, Input>);
// RGB Family────────────────────┐
+ // │ ┌────────────────┐│
+ // │ ┌─────▶︎ LinearExtended ││
+ // │ │ └────────▲───────┘│
+ // │ │ │ │
+ // │┌────────┐ │ │
+ // ││ Linear │ │ │
+ // │└────▲───┘ │ │
+ // │ │ │ │
// │┌────────┐ ┌────────────────┐│
- // ││ Linear │ │ LinearExtended ││
+ // ││ Gamma │─│ GammaExtended ││
// │└────────┘ └────────────────┘│
- // │┌────────┐ ┌────────────────┐│
- // ││ Gamma │ │ GammaExtended ││
- // │└────────┘ └────────────────┘│
// └─────────────────────────────┘
// This handles conversions between any two of these within the same family, so SRGBLinear -> SRGB, but not
@@ -285,8 +384,8 @@
static inline constexpr Output handleMatrixConversion(const Input& color)
{
- static_assert(IsRGBLinearEncodedType<Input> || IsXYZA<Input>);
- static_assert(IsRGBLinearEncodedType<Output> || IsXYZA<Output>);
+ static_assert((IsRGBLinearEncodedType<Input> && IsRGBExtendedType<Input>) || IsXYZA<Input>);
+ static_assert((IsRGBLinearEncodedType<Output> && IsRGBExtendedType<Output>) || IsXYZA<Output>);
// ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
// Matrix Conversions ┌───────────┐│┌───────────┐
@@ -298,12 +397,12 @@
// │ │ │ │ │ │
// │ │ │ │ │ │ │ │
// ProPhotoRGB───────────────────┐ │ SRGB──────────────────────────┐ DisplayP3─────────────────────┐ A98RGB────────────────────────┐ Rec2020───────────────────────┐
- // │ │┌────────┐ ┌────────────────┐│ │ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │
- // ││ Linear │ │ LinearExtended ││ │ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││
- // │ │└────────┘ └────────────────┘│ │ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │
- // ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─
+ // │ │ ┌────────────────┐│ │ │ ┌────────────────┐│ │ ┌────────────────┐│ │ ┌────────────────┐│ │ ┌────────────────┐│ │
+ // │ ┌─────▶︎ LinearExtended ││ │ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││ │ ┌─────▶︎ LinearExtended ││
+ // │ │ │ └────────▲───────┘│ │ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │ │ └────────▲───────┘│ │
+ // ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─
- // This handles conversions between linear color types that can be converted using pre-defined
+ // This handles conversions between extended linear color types that can be converted using pre-defined
// 3x3 matrices.
// FIXME: Pre-compute (using constexpr) the concatenation of the matrices prior to applying them
@@ -312,7 +411,7 @@
// have sufficient testing coverage to notice any adverse effects.
auto applyMatrices = [](const Input& color, auto... matrices) {
- return makeFromComponentsClampingExceptAlpha<Output>(applyMatricesToColorComponents(asColorComponents(color.resolved()), matrices...));
+ return makeFromComponents<Output>(applyMatricesToColorComponents(asColorComponents(color.resolved()), matrices...));
};
if constexpr (Input::whitePoint == Output::whitePoint) {
Modified: trunk/Source/WebCore/platform/graphics/ColorTypes.h (289395 => 289396)
--- trunk/Source/WebCore/platform/graphics/ColorTypes.h 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Source/WebCore/platform/graphics/ColorTypes.h 2022-02-08 18:57:30 UTC (rev 289396)
@@ -29,6 +29,7 @@
#include "ColorMatrix.h"
#include "ColorModels.h"
#include "ColorTransferFunctions.h"
+#include <optional>
namespace WebCore {
@@ -311,6 +312,47 @@
template<typename ColorType1, typename ColorType2> inline constexpr bool IsSameRGBTypeFamilyValue<ColorType1, ColorType2, true> = std::is_same_v<typename ColorType1::Descriptor, typename ColorType2::Descriptor>;
template<typename ColorType1, typename ColorType2> inline constexpr bool IsSameRGBTypeFamily = IsSameRGBTypeFamilyValue<ColorType1, ColorType2, IsRGBType<ColorType1> && IsRGBType<ColorType2>>;
+template<typename BoundedColorType> constexpr bool inGamut(typename BoundedColorType::ComponentType component)
+{
+ static_assert(IsRGBBoundedType<BoundedColorType>);
+
+ return component >= 0.0f && component <= 1.0f;
+}
+
+template<typename BoundedColorType> constexpr bool inGamut(ColorComponents<typename BoundedColorType::ComponentType, 4> components)
+{
+ static_assert(IsRGBBoundedType<BoundedColorType>);
+
+ return inGamut<BoundedColorType>(components[0]) && inGamut<BoundedColorType>(components[1]) && inGamut<BoundedColorType>(components[2]);
+}
+
+template<typename BoundedColorType, typename ColorType> constexpr bool inGamut(ColorType color)
+{
+ static_assert(IsRGBBoundedType<BoundedColorType>);
+ static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
+
+ return inGamut<BoundedColorType>(asColorComponents(color.resolved()));
+}
+
+template<typename BoundedColorType, typename ColorType> constexpr std::optional<BoundedColorType> colorIfInGamut(ColorType color)
+{
+ static_assert(IsRGBBoundedType<BoundedColorType>);
+ static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
+
+ auto components = asColorComponents(color.resolved());
+ if (!inGamut<BoundedColorType>(components))
+ return std::nullopt;
+ return makeFromComponents<BoundedColorType>(components);
+}
+
+template<typename BoundedColorType, typename ColorType> constexpr BoundedColorType clipToGamut(ColorType color)
+{
+ static_assert(IsRGBBoundedType<BoundedColorType>);
+ static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
+
+ return makeFromComponentsClampingExceptAlpha<BoundedColorType>(asColorComponents(color.resolved()));
+}
+
struct SRGBADescriptor {
template<typename T, TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
static constexpr auto whitePoint = WhitePoint::D65;
Modified: trunk/Tools/ChangeLog (289395 => 289396)
--- trunk/Tools/ChangeLog 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Tools/ChangeLog 2022-02-08 18:57:30 UTC (rev 289396)
@@ -1,3 +1,15 @@
+2022-02-08 Sam Weinig <wei...@apple.com>
+
+ Conversion to a color space with a smaller gamut should perform gamut mapping
+ https://bugs.webkit.org/show_bug.cgi?id=236200
+
+ Reviewed by Darin Adler.
+
+ * TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
+ (TestWebKitAPI::TEST):
+ Update color conversion tests to account for gamut mapping and add a new test
+ that bypasses gamut mapping by converting to extended sRGB.
+
2022-02-01 Jonathan Bedard <jbed...@apple.com>
[git-webkit] Autostash when pulling
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp (289395 => 289396)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp 2022-02-08 18:55:54 UTC (rev 289395)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp 2022-02-08 18:57:30 UTC (rev 289396)
@@ -372,6 +372,16 @@
Color p3Color { DisplayP3<float> { 1.0, 0.5, 0.25, 0.75 } };
auto sRGBAColor = p3Color.toColorTypeLossy<SRGBA<float>>().resolved();
EXPECT_FLOAT_EQ(sRGBAColor.red, 1.0f);
+ EXPECT_FLOAT_EQ(sRGBAColor.green, 0.50120097f);
+ EXPECT_FLOAT_EQ(sRGBAColor.blue, 0.26161569f);
+ EXPECT_FLOAT_EQ(sRGBAColor.alpha, 0.75f);
+}
+
+TEST(Color, P3ConversionToExtendedSRGB)
+{
+ Color p3Color { DisplayP3<float> { 1.0, 0.5, 0.25, 0.75 } };
+ auto sRGBAColor = p3Color.toColorTypeLossy<ExtendedSRGBA<float>>().resolved();
+ EXPECT_FLOAT_EQ(sRGBAColor.red, 1.0740442f);
EXPECT_FLOAT_EQ(sRGBAColor.green, 0.46253282f);
EXPECT_FLOAT_EQ(sRGBAColor.blue, 0.14912748f);
EXPECT_FLOAT_EQ(sRGBAColor.alpha, 0.75f);