Diff
Modified: trunk/LayoutTests/ChangeLog (274946 => 274947)
--- trunk/LayoutTests/ChangeLog 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/LayoutTests/ChangeLog 2021-03-24 17:34:50 UTC (rev 274947)
@@ -1,3 +1,14 @@
+2021-03-24 Sam Weinig <wei...@apple.com>
+
+ Update CSS Color 5 color-mix() implementation to match the latest draft spec
+ https://bugs.webkit.org/show_bug.cgi?id=223665
+
+ Reviewed by Simon Fraser.
+
+ * fast/css/parsing-color-mix-expected.txt:
+ * fast/css/parsing-color-mix.html:
+ Update test and results for vastly simplified color-mix().
+
2021-03-24 Chris Lord <cl...@igalia.com>
[GLIB] imported/w3c/web-platform-tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.w.html is flaky failing
Modified: trunk/LayoutTests/fast/css/parsing-color-mix-expected.txt (274946 => 274947)
--- trunk/LayoutTests/fast/css/parsing-color-mix-expected.txt 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/LayoutTests/fast/css/parsing-color-mix-expected.txt 2021-03-24 17:34:50 UTC (rev 274947)
@@ -4,200 +4,76 @@
color-mix(hsl, ...)
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))") is "rgb(84, 92, 61)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))") is "rgb(112, 106, 67)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)") is "rgb(61, 73, 54)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)") is "rgb(112, 106, 67)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 50%, hsl(30deg 30% 40%) 150%)") is "rgb(112, 106, 67)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)") is "rgb(112, 106, 67)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))") is "rgb(133, 102, 71)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%))") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) hue 50%)") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) hue 50%)") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 100%, hsl(30deg 30% 40%))") is "rgb(46, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%))") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100%, hsl(30deg 30% 40%))") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100% lightness 100%, hsl(30deg 30% 40%))") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100% lightness 100% alpha 100%, hsl(30deg 30% 40%))") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0%)") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0% lightness 0%)") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0% lightness 0% alpha 0%)") is "rgb(53, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75%, hsl(30deg 30% 40%))") is "rgb(55, 59, 43)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75% lightness 15%, hsl(30deg 30% 40%))") is "rgb(101, 108, 80)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75% lightness 15% alpha 10%, hsl(30deg 30% 40%))") is "rgb(101, 108, 80)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 60%, hsl(30deg 30% 40%))") is "rgb(52, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) hue 40%)") is "rgb(52, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 60%, hsl(30deg 30% 40%) hue 40%)") is "rgb(52, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 60% hue 40%, hsl(30deg 30% 40%))") is "rgb(55, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 40%, hsl(30deg 30% 40%))") is "rgb(55, 56, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue, hsl(30deg 30% 40%))") is "rgb(56, 51, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 0%, hsl(30deg 30% 40%))") is "rgb(56, 51, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) -10%, hsl(30deg 30% 40%))") is "rgb(133, 102, 71)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))") is "rgb(133, 102, 71)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue -10%, hsl(30deg 30% 40%))") is "rgb(56, 51, 46)"
-PASS computedStyle("background-color", "color-mix(hsl, hsl(120deg 10% 20%) hue 0%, hsl(30deg 30% 40%))") is "rgb(56, 51, 46)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))") is "rgb(84, 92, 61)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))") is "rgb(112, 106, 67)"
+PASS computedStyle("background-color", "color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))") is "rgb(112, 106, 67)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))") is "rgb(61, 73, 54)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)") is "rgb(61, 73, 54)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)") is "rgb(112, 106, 67)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) 50%, hsl(30deg 30% 40%) 150%)") is "rgb(112, 106, 67)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)") is "rgb(112, 106, 67)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))") is "rgb(133, 102, 71)"
+PASS computedStyle("background-color", "color-mix(in hsl, hsl(120deg 10% 20%) -10%, hsl(30deg 30% 40%))") is "rgb(142, 97, 72)"
color-mix(hwb, ...)
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))") is "rgb(147, 179, 52)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))") is "rgb(166, 153, 64)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)") is "rgb(96, 191, 39)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)") is "rgb(166, 153, 64)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 50%, hwb(30deg 30% 40%) 150%)") is "rgb(166, 153, 64)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)") is "rgb(166, 153, 64)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))") is "rgb(153, 115, 77)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%))") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) hue 50%)") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) hue 50%)") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 100%, hwb(30deg 30% 40%))") is "rgb(26, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%))") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100%, hwb(30deg 30% 40%))") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100% blackness 100%, hwb(30deg 30% 40%))") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100% blackness 100% alpha 100%, hwb(30deg 30% 40%))") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0%)") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0% blackness 0%)") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0% blackness 0% alpha 0%)") is "rgb(160, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75%, hwb(30deg 30% 40%))") is "rgb(163, 204, 39)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75% blackness 15%, hwb(30deg 30% 40%))") is "rgb(130, 161, 39)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75% blackness 15% alpha 10%, hwb(30deg 30% 40%))") is "rgb(130, 161, 39)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 60%, hwb(30deg 30% 40%))") is "rgb(133, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) hue 40%)") is "rgb(133, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 60%, hwb(30deg 30% 40%) hue 40%)") is "rgb(133, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 75% 25%) whiteness 100%, hwb(120deg 25% 75%) blackness 100%)") is "rgb(128, 128, 128)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 60% hue 40%, hwb(30deg 30% 40%))") is "rgb(186, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 40%, hwb(30deg 30% 40%))") is "rgb(186, 204, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue, hwb(30deg 30% 40%))") is "rgb(204, 115, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 0%, hwb(30deg 30% 40%))") is "rgb(204, 115, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) -10%, hwb(30deg 30% 40%))") is "rgb(153, 115, 77)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))") is "rgb(153, 115, 77)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue -10%, hwb(30deg 30% 40%))") is "rgb(204, 115, 26)"
-PASS computedStyle("background-color", "color-mix(hwb, hwb(120deg 10% 20%) hue 0%, hwb(30deg 30% 40%))") is "rgb(204, 115, 26)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))") is "rgb(147, 179, 52)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))") is "rgb(166, 153, 64)"
+PASS computedStyle("background-color", "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))") is "rgb(166, 153, 64)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))") is "rgb(96, 191, 39)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)") is "rgb(96, 191, 39)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)") is "rgb(166, 153, 64)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) 50%, hwb(30deg 30% 40%) 150%)") is "rgb(166, 153, 64)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)") is "rgb(166, 153, 64)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))") is "rgb(153, 115, 77)"
+PASS computedStyle("background-color", "color-mix(in hwb, hwb(120deg 10% 20%) -10%, hwb(30deg 30% 40%))") is "rgb(148, 105, 82)"
color-mix(lch, ...)
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))") is "lch(30% 40 50 / 0.6)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))") is "lch(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)") is "lch(20% 30 40 / 0.5)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)") is "lch(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 50%, lch(50% 60 70deg / .8) 150%)") is "lch(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)") is "lch(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))") is "lch(50% 60 70 / 0.8)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8))") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) lightness 50%)") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) lightness 50%)") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 100%, lch(50% 60 70deg / .8))") is "lch(10% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8))") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100%, lch(50% 60 70deg / .8))") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100% hue 100%, lch(50% 60 70deg / .8))") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100% hue 100% alpha 100%, lch(50% 60 70deg / .8))") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0%)") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0% hue 0%)") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0% hue 0% alpha 0%)") is "lch(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75%, lch(50% 60 70deg / .8))") is "lch(30% 30 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75% hue 15%, lch(50% 60 70deg / .8))") is "lch(30% 30 64 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75% hue 15% alpha 10%, lch(50% 60 70deg / .8))") is "lch(30% 30 64 / 0.76)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 60%, lch(50% 60 70deg / .8))") is "lch(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) lightness 40%)") is "lch(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 60%, lch(50% 60 70deg / .8) lightness 40%)") is "lch(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 60% lightness 40%, lch(50% 60 70deg / .8))") is "lch(34% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 40%, lch(50% 60 70deg / .8))") is "lch(34% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness, lch(50% 60 70deg / .8))") is "lch(50% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 0%, lch(50% 60 70deg / .8))") is "lch(50% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) -10%, lch(50% 60 70deg / .8))") is "lch(50% 60 70 / 0.8)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))") is "lch(50% 60 70 / 0.8)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness -10%, lch(50% 60 70deg / .8))") is "lch(50% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lch, lch(10% 20 30deg / .4) lightness 0%, lch(50% 60 70deg / .8))") is "lch(50% 20 30 / 0.4)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))") is "lch(30% 40 50 / 0.6)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))") is "lch(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))") is "lch(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))") is "lch(20% 30 40 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)") is "lch(20% 30 40 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)") is "lch(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) 50%, lch(50% 60 70deg / .8) 150%)") is "lch(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)") is "lch(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))") is "lch(50% 60 70 / 0.8)"
+PASS computedStyle("background-color", "color-mix(in lch, lch(10% 20 30deg / .4) -10%, lch(50% 60 70deg / .8))") is "lch(54% 64 74 / 0.84000003)"
color-mix(lab, ...)
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))") is "lab(30% 40 50 / 0.6)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))") is "lab(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)") is "lab(20% 30 40 / 0.5)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)") is "lab(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) 50%, lab(50% 60 70 / .8) 150%)") is "lab(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)") is "lab(40% 50 60 / 0.7)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))") is "lab(50% 60 70 / 0.8)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8))") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) lightness 50%)") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) lightness 50%)") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 100%, lab(50% 60 70 / .8))") is "lab(10% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8))") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100%, lab(50% 60 70 / .8))") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100% b 100%, lab(50% 60 70 / .8))") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100% b 100% alpha 100%, lab(50% 60 70 / .8))") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0%)") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0% b 0%)") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0% b 0% alpha 0%)") is "lab(30% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75%, lab(50% 60 70 / .8))") is "lab(30% 30 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75% b 15%, lab(50% 60 70 / .8))") is "lab(30% 30 64 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75% b 15% alpha 10%, lab(50% 60 70 / .8))") is "lab(30% 30 64 / 0.76)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 60%, lab(50% 60 70 / .8))") is "lab(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) lightness 40%)") is "lab(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 60%, lab(50% 60 70 / .8) lightness 40%)") is "lab(26% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 60% lightness 40%, lab(50% 60 70 / .8))") is "lab(34% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness, lab(50% 60 70 / .8))") is "lab(50% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness 0%, lab(50% 60 70 / .8))") is "lab(50% 20 30 / 0.4)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) -10%, lab(50% 60 70 / .8))") is "lab(50% 60 70 / 0.8)"
-PASS computedStyle("background-color", "color-mix(lab, lab(10% 20 30 / .4) lightness -10%, lab(50% 60 70 / .8))") is "lab(50% 20 30 / 0.4)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))") is "lab(30% 40 50 / 0.6)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))") is "lab(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))") is "lab(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))") is "lab(20% 30 40 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)") is "lab(20% 30 40 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)") is "lab(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) 50%, lab(50% 60 70 / .8) 150%)") is "lab(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)") is "lab(40% 50 60 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))") is "lab(50% 60 70 / 0.8)"
+PASS computedStyle("background-color", "color-mix(in lab, lab(10% 20 30 / .4) -10%, lab(50% 60 70 / .8))") is "lab(54% 64 74 / 0.84000003)"
color-mix(srgb, ...)
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.4 0.5 / 0.6)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)") is "color(srgb 0.2 0.3 0.4 / 0.5)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) 50%, color(srgb .5 .6 .7 / .8) 150%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.6 0.7 / 0.8)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) red 50%)") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) red 50%)") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 100%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.1 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100% blue 100%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100% blue 100% alpha 100%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0%)") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0% blue 0%)") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0% blue 0% alpha 0%)") is "color(srgb 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.3 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75% blue 15%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.3 0.64 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75% blue 15% alpha 10%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.3 0.64 / 0.76)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) red 40%)") is "color(srgb 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60%, color(srgb .5 .6 .7 / .8) red 40%)") is "color(srgb 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60% red 40%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.34 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red 0%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) -10%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.6 0.7 / 0.8)"
-PASS computedStyle("background-color", "color-mix(srgb, color(srgb .1 .2 .3 / .4) red -10%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.2 0.3 / 0.4)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))") is "color(srgb 0.3 0.4 0.5 / 0.6)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))") is "color(srgb 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))") is "color(srgb 0.2 0.3 0.4 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)") is "color(srgb 0.2 0.3 0.4 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 50%, color(srgb .5 .6 .7 / .8) 150%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)") is "color(srgb 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.5 0.6 0.7 / 0.8)"
+PASS computedStyle("background-color", "color-mix(in srgb, color(srgb .1 .2 .3 / .4) -10%, color(srgb .5 .6 .7 / .8))") is "color(srgb 0.54 0.64000005 0.74 / 0.84000003)"
color-mix(xyz, ...)
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.4 0.5 / 0.6)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)") is "color(xyz 0.2 0.3 0.4 / 0.5)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) 50%, color(xyz .5 .6 .7 / .8) 150%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.6 0.7 / 0.8)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) x 50%)") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) x 50%)") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 100%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.1 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100% z 100%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100% z 100% alpha 100%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0%)") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0% z 0%)") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0% z 0% alpha 0%)") is "color(xyz 0.3 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.3 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75% z 15%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.3 0.64 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75% z 15% alpha 10%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.3 0.64 / 0.76)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) x 40%)") is "color(xyz 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60%, color(xyz .5 .6 .7 / .8) x 40%)") is "color(xyz 0.26 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60% x 40%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.34 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x 0%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.2 0.3 / 0.4)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) -10%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.6 0.7 / 0.8)"
-PASS computedStyle("background-color", "color-mix(xyz, color(xyz .1 .2 .3 / .4) x -10%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.2 0.3 / 0.4)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))") is "color(xyz 0.3 0.4 0.5 / 0.6)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))") is "color(xyz 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)") is "color(xyz 0.2 0.3 0.4 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))") is "color(xyz 0.2 0.3 0.4 / 0.5)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 50%, color(xyz .5 .6 .7 / .8) 150%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)") is "color(xyz 0.4 0.5 0.6 / 0.7)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.5 0.6 0.7 / 0.8)"
+PASS computedStyle("background-color", "color-mix(in xyz, color(xyz .1 .2 .3 / .4) -10%, color(xyz .5 .6 .7 / .8))") is "color(xyz 0.54 0.64000005 0.74 / 0.84000003)"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/css/parsing-color-mix.html (274946 => 274947)
--- trunk/LayoutTests/fast/css/parsing-color-mix.html 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/LayoutTests/fast/css/parsing-color-mix.html 2021-03-24 17:34:50 UTC (rev 274947)
@@ -28,301 +28,102 @@
debug('color-mix(hsl, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))`, `rgb(84, 92, 61)`); // hsl(75deg 20% 30%)
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))`, `rgb(84, 92, 61)`); // hsl(75deg 20% 30%)
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))`, `rgb(112, 106, 67)`);
+ testComputed(`color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))`, `rgb(112, 106, 67)`);
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))`, `rgb(61, 73, 54)`);
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)`, `rgb(61, 73, 54)`);
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)`, `rgb(112, 106, 67)`);
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) 50%, hsl(30deg 30% 40%) 150%)`, `rgb(112, 106, 67)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)`, `rgb(112, 106, 67)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))`, `rgb(133, 102, 71)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))`, `rgb(112, 106, 67)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)`, `rgb(61, 73, 54)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)`, `rgb(112, 106, 67)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 50%, hsl(30deg 30% 40%) 150%)`, `rgb(112, 106, 67)`); // Scale down > 100% sum.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)`, `rgb(112, 106, 67)`); // Scale up < 100% sum.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))`, `rgb(133, 102, 71)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in hsl, hsl(120deg 10% 20%) -10%, hsl(30deg 30% 40%))`, `rgb(142, 97, 72)`);
- // Test per-channel adjusters.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%))`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) hue 50%)`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) hue 50%)`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 100%, hsl(30deg 30% 40%))`, `rgb(46, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%))`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100%, hsl(30deg 30% 40%))`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100% lightness 100%, hsl(30deg 30% 40%))`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 100% lightness 100% alpha 100%, hsl(30deg 30% 40%))`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0%)`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0% lightness 0%)`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50%, hsl(30deg 30% 40%) saturation 0% lightness 0% alpha 0%)`, `rgb(53, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75%, hsl(30deg 30% 40%))`, `rgb(55, 59, 43)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75% lightness 15%, hsl(30deg 30% 40%))`, `rgb(101, 108, 80)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 50% saturation 75% lightness 15% alpha 10%, hsl(30deg 30% 40%))`, `rgb(101, 108, 80)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 60%, hsl(30deg 30% 40%))`, `rgb(52, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) hue 40%)`, `rgb(52, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 60%, hsl(30deg 30% 40%) hue 40%)`, `rgb(52, 56, 46)`);
- // FIXME: Test hue mixes with modifiers.
-
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 60% hue 40%, hsl(30deg 30% 40%))`, `rgb(55, 56, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 40%, hsl(30deg 30% 40%))`, `rgb(55, 56, 46)`);
-
- // What should happen if you provide an adjuster without a paihue percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue, hsl(30deg 30% 40%))`, `rgb(56, 51, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 0%, hsl(30deg 30% 40%))`, `rgb(56, 51, 46)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) -10%, hsl(30deg 30% 40%))`, `rgb(133, 102, 71)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))`, `rgb(133, 102, 71)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue -10%, hsl(30deg 30% 40%))`, `rgb(56, 51, 46)`);
- testComputed(`color-mix(hsl, hsl(120deg 10% 20%) hue 0%, hsl(30deg 30% 40%))`, `rgb(56, 51, 46)`);
-
-
debug('');
debug('color-mix(hwb, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`); // hwb(75deg 20% 30%)
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`); // hwb(75deg 20% 30%)
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
+ testComputed(`color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))`, `rgb(96, 191, 39)`);
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)`, `rgb(96, 191, 39)`);
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)`, `rgb(166, 153, 64)`);
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) 50%, hwb(30deg 30% 40%) 150%)`, `rgb(166, 153, 64)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)`, `rgb(166, 153, 64)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))`, `rgb(153, 115, 77)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)`, `rgb(96, 191, 39)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)`, `rgb(166, 153, 64)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 50%, hwb(30deg 30% 40%) 150%)`, `rgb(166, 153, 64)`); // Scale down > 100% sum.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)`, `rgb(166, 153, 64)`); // Scale up < 100% sum.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))`, `rgb(153, 115, 77)`);
-
- // Test per-channel adjusters.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%))`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) hue 50%)`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) hue 50%)`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 100%, hwb(30deg 30% 40%))`, `rgb(26, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%))`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100%, hwb(30deg 30% 40%))`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100% blackness 100%, hwb(30deg 30% 40%))`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 100% blackness 100% alpha 100%, hwb(30deg 30% 40%))`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0%)`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0% blackness 0%)`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50%, hwb(30deg 30% 40%) whiteness 0% blackness 0% alpha 0%)`, `rgb(160, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75%, hwb(30deg 30% 40%))`, `rgb(163, 204, 39)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75% blackness 15%, hwb(30deg 30% 40%))`, `rgb(130, 161, 39)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 50% whiteness 75% blackness 15% alpha 10%, hwb(30deg 30% 40%))`, `rgb(130, 161, 39)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 60%, hwb(30deg 30% 40%))`, `rgb(133, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) hue 40%)`, `rgb(133, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 60%, hwb(30deg 30% 40%) hue 40%)`, `rgb(133, 204, 26)`);
-
- // Test mix that creates whiteness + blackness > 100%.
- testComputed(`color-mix(hwb, hwb(120deg 75% 25%) whiteness 100%, hwb(120deg 25% 75%) blackness 100%)`, `rgb(128, 128, 128)`);
-
- // FIXME: Test hue mixes with modifiers.
-
-
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 60% hue 40%, hwb(30deg 30% 40%))`, `rgb(186, 204, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 40%, hwb(30deg 30% 40%))`, `rgb(186, 204, 26)`);
-
- // What should happen if you provide an adjuster without a paihue percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue, hwb(30deg 30% 40%))`, `rgb(204, 115, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 0%, hwb(30deg 30% 40%))`, `rgb(204, 115, 26)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) -10%, hwb(30deg 30% 40%))`, `rgb(153, 115, 77)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))`, `rgb(153, 115, 77)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue -10%, hwb(30deg 30% 40%))`, `rgb(204, 115, 26)`);
- testComputed(`color-mix(hwb, hwb(120deg 10% 20%) hue 0%, hwb(30deg 30% 40%))`, `rgb(204, 115, 26)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in hwb, hwb(120deg 10% 20%) -10%, hwb(30deg 30% 40%))`, `rgb(148, 105, 82)`);
debug('');
debug('color-mix(lch, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))`, `lch(30% 40 50 / 0.6)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))`, `lch(30% 40 50 / 0.6)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))`, `lch(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))`, `lch(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))`, `lch(20% 30 40 / 0.5)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)`, `lch(20% 30 40 / 0.5)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)`, `lch(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) 50%, lch(50% 60 70deg / .8) 150%)`, `lch(40% 50 60 / 0.7)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)`, `lch(40% 50 60 / 0.7)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))`, `lch(50% 60 70 / 0.8)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))`, `lch(40% 50 60 / 0.7)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)`, `lch(20% 30 40 / 0.5)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)`, `lch(40% 50 60 / 0.7)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 50%, lch(50% 60 70deg / .8) 150%)`, `lch(40% 50 60 / 0.7)`); // Scale down > 100% sum.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)`, `lch(40% 50 60 / 0.7)`); // Scale up < 100% sum.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))`, `lch(50% 60 70 / 0.8)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in lch, lch(10% 20 30deg / .4) -10%, lch(50% 60 70deg / .8))`, `lch(54% 64 74 / 0.84000003)`);
- // Test per-channel adjusters.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8))`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) lightness 50%)`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) lightness 50%)`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 100%, lch(50% 60 70deg / .8))`, `lch(10% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8))`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100%, lch(50% 60 70deg / .8))`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100% hue 100%, lch(50% 60 70deg / .8))`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 100% hue 100% alpha 100%, lch(50% 60 70deg / .8))`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0%)`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0% hue 0%)`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50%, lch(50% 60 70deg / .8) chroma 0% hue 0% alpha 0%)`, `lch(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75%, lch(50% 60 70deg / .8))`, `lch(30% 30 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75% hue 15%, lch(50% 60 70deg / .8))`, `lch(30% 30 64 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 50% chroma 75% hue 15% alpha 10%, lch(50% 60 70deg / .8))`, `lch(30% 30 64 / 0.76)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 60%, lch(50% 60 70deg / .8))`, `lch(26% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) lightness 40%)`, `lch(26% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 60%, lch(50% 60 70deg / .8) lightness 40%)`, `lch(26% 20 30 / 0.4)`);
- // FIXME: Test hue mixes with modifiers.
-
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 60% lightness 40%, lch(50% 60 70deg / .8))`, `lch(34% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 40%, lch(50% 60 70deg / .8))`, `lch(34% 20 30 / 0.4)`);
-
- // What should happen if you provide an adjuster without a pailightness percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness, lch(50% 60 70deg / .8))`, `lch(50% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 0%, lch(50% 60 70deg / .8))`, `lch(50% 20 30 / 0.4)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) -10%, lch(50% 60 70deg / .8))`, `lch(50% 60 70 / 0.8)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))`, `lch(50% 60 70 / 0.8)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness -10%, lch(50% 60 70deg / .8))`, `lch(50% 20 30 / 0.4)`);
- testComputed(`color-mix(lch, lch(10% 20 30deg / .4) lightness 0%, lch(50% 60 70deg / .8))`, `lch(50% 20 30 / 0.4)`);
-
-
debug('');
debug('color-mix(lab, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))`, `lab(30% 40 50 / 0.6)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))`, `lab(30% 40 50 / 0.6)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))`, `lab(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))`, `lab(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))`, `lab(20% 30 40 / 0.5)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)`, `lab(20% 30 40 / 0.5)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)`, `lab(40% 50 60 / 0.7)`);
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) 50%, lab(50% 60 70 / .8) 150%)`, `lab(40% 50 60 / 0.7)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)`, `lab(40% 50 60 / 0.7)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))`, `lab(50% 60 70 / 0.8)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))`, `lab(40% 50 60 / 0.7)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)`, `lab(20% 30 40 / 0.5)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)`, `lab(40% 50 60 / 0.7)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) 50%, lab(50% 60 70 / .8) 150%)`, `lab(40% 50 60 / 0.7)`); // Scale down > 100% sum.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)`, `lab(40% 50 60 / 0.7)`); // Scale up < 100% sum.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))`, `lab(50% 60 70 / 0.8)`);
-
- // Test per-channel adjusters.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8))`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) lightness 50%)`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) lightness 50%)`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 100%, lab(50% 60 70 / .8))`, `lab(10% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8))`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100%, lab(50% 60 70 / .8))`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100% b 100%, lab(50% 60 70 / .8))`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 100% b 100% alpha 100%, lab(50% 60 70 / .8))`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0%)`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0% b 0%)`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50%, lab(50% 60 70 / .8) a 0% b 0% alpha 0%)`, `lab(30% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75%, lab(50% 60 70 / .8))`, `lab(30% 30 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75% b 15%, lab(50% 60 70 / .8))`, `lab(30% 30 64 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 50% a 75% b 15% alpha 10%, lab(50% 60 70 / .8))`, `lab(30% 30 64 / 0.76)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 60%, lab(50% 60 70 / .8))`, `lab(26% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) lightness 40%)`, `lab(26% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 60%, lab(50% 60 70 / .8) lightness 40%)`, `lab(26% 20 30 / 0.4)`);
-
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 60% lightness 40%, lab(50% 60 70 / .8))`, `lab(34% 20 30 / 0.4)`);
-
- // What should happen if you provide an adjuster without a pailightness percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness, lab(50% 60 70 / .8))`, `lab(50% 20 30 / 0.4)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness 0%, lab(50% 60 70 / .8))`, `lab(50% 20 30 / 0.4)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) -10%, lab(50% 60 70 / .8))`, `lab(50% 60 70 / 0.8)`);
- testComputed(`color-mix(lab, lab(10% 20 30 / .4) lightness -10%, lab(50% 60 70 / .8))`, `lab(50% 20 30 / 0.4)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in lab, lab(10% 20 30 / .4) -10%, lab(50% 60 70 / .8))`, `lab(54% 64 74 / 0.84000003)`);
debug('');
debug('color-mix(srgb, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.4 0.5 / 0.6)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.4 0.5 / 0.6)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))`, `color(srgb 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))`, `color(srgb 0.2 0.3 0.4 / 0.5)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)`, `color(srgb 0.2 0.3 0.4 / 0.5)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) 50%, color(srgb .5 .6 .7 / .8) 150%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.6 0.7 / 0.8)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.4 0.5 0.6 / 0.7)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)`, `color(srgb 0.2 0.3 0.4 / 0.5)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) 50%, color(srgb .5 .6 .7 / .8) 150%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`); // Scale down > 100% sum.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)`, `color(srgb 0.4 0.5 0.6 / 0.7)`); // Scale up < 100% sum.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.6 0.7 / 0.8)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in srgb, color(srgb .1 .2 .3 / .4) -10%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.54 0.64000005 0.74 / 0.84000003)`);
- // Test per-channel adjusters.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) red 50%)`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) red 50%)`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 100%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.1 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100% blue 100%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 100% blue 100% alpha 100%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0%)`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0% blue 0%)`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50%, color(srgb .5 .6 .7 / .8) green 0% blue 0% alpha 0%)`, `color(srgb 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.3 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75% blue 15%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.3 0.64 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 50% green 75% blue 15% alpha 10%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.3 0.3 0.64 / 0.76)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.26 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) red 40%)`, `color(srgb 0.26 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60%, color(srgb .5 .6 .7 / .8) red 40%)`, `color(srgb 0.26 0.2 0.3 / 0.4)`);
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 60% red 40%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.34 0.2 0.3 / 0.4)`);
-
- // What should happen if you provide an adjuster without a paired percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red 0%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.2 0.3 / 0.4)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) -10%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.6 0.7 / 0.8)`);
- testComputed(`color-mix(srgb, color(srgb .1 .2 .3 / .4) red -10%, color(srgb .5 .6 .7 / .8))`, `color(srgb 0.5 0.2 0.3 / 0.4)`);
-
-
debug('');
debug('color-mix(xyz, ...)');
- // Special case no adjusters or percentage is split 50-50.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.4 0.5 / 0.6)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.4 0.5 / 0.6)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))`, `color(xyz 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)`, `color(xyz 0.2 0.3 0.4 / 0.5)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))`, `color(xyz 0.2 0.3 0.4 / 0.5)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`);
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) 50%, color(xyz .5 .6 .7 / .8) 150%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`); // Scale down > 100% sum.
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`); // Scale up < 100% sum.
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.6 0.7 / 0.8)`);
- // Test precentage without adjusters.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.4 0.5 0.6 / 0.7)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)`, `color(xyz 0.2 0.3 0.4 / 0.5)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) 50%, color(xyz .5 .6 .7 / .8) 150%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`); // Scale down > 100% sum.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)`, `color(xyz 0.4 0.5 0.6 / 0.7)`); // Scale up < 100% sum.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.6 0.7 / 0.8)`);
-
- // Test per-channel adjusters.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) x 50%)`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) x 50%)`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 100%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.1 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100% z 100%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 100% z 100% alpha 100%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0%)`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0% z 0%)`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50%, color(xyz .5 .6 .7 / .8) y 0% z 0% alpha 0%)`, `color(xyz 0.3 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.3 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75% z 15%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.3 0.64 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 50% y 75% z 15% alpha 10%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.3 0.3 0.64 / 0.76)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.26 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) x 40%)`, `color(xyz 0.26 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60%, color(xyz .5 .6 .7 / .8) x 40%)`, `color(xyz 0.26 0.2 0.3 / 0.4)`);
-
- // Open questions.
-
- // What should happen if you provide the same adjuster more than once? Currently, we do last one wins.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 60% x 40%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.34 0.2 0.3 / 0.4)`);
-
- // What should happen if you provide an adjuster without a paix percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.2 0.3 / 0.4)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x 0%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.2 0.3 / 0.4)`);
-
- // What should happen if you provide an adjuster without a negative percent? Currently, we treat that like having 0% for that adjuster.
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) -10%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.6 0.7 / 0.8)`);
- testComputed(`color-mix(xyz, color(xyz .1 .2 .3 / .4) x -10%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.5 0.2 0.3 / 0.4)`);
+ // What should happen if you provide a negative percent? https://github.com/w3c/csswg-drafts/issues/6047
+ testComputed(`color-mix(in xyz, color(xyz .1 .2 .3 / .4) -10%, color(xyz .5 .6 .7 / .8))`, `color(xyz 0.54 0.64000005 0.74 / 0.84000003)`);
</script>
<script src=""
Modified: trunk/Source/WebCore/ChangeLog (274946 => 274947)
--- trunk/Source/WebCore/ChangeLog 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/ChangeLog 2021-03-24 17:34:50 UTC (rev 274947)
@@ -1,3 +1,53 @@
+2021-03-24 Sam Weinig <wei...@apple.com>
+
+ Update CSS Color 5 color-mix() implementation to match the latest draft spec
+ https://bugs.webkit.org/show_bug.cgi?id=223665
+
+ Reviewed by Simon Fraser.
+
+ Update to the latest draft spec, which dramatically reduces the complexity of color-mix()
+ by remove per-component adjusters.
+
+ * css/CSSValueKeywords.in:
+ * css/parser/CSSPropertyParserHelpers.cpp:
+ (WebCore::CSSPropertyParserHelpers::normalizeWhitenessBlackness):
+ (WebCore::CSSPropertyParserHelpers::consumeColorMixColorSpaceAndComma):
+ (WebCore::CSSPropertyParserHelpers::consumeColorMixComponent):
+ (WebCore::CSSPropertyParserHelpers::normalizedMixPercentages):
+ (WebCore::CSSPropertyParserHelpers::makeColorTypeByNormalizingComponentsAfterMix):
+ (WebCore::CSSPropertyParserHelpers::makeColorTypeByNormalizingComponentsAfterMix<HWBA<float>>):
+ (WebCore::CSSPropertyParserHelpers::makeColorTypeByNormalizingComponentsAfterMix<HSLA<float>>):
+ (WebCore::CSSPropertyParserHelpers::fixupHueComponentsPriorToMix):
+ (WebCore::CSSPropertyParserHelpers::mixColorComponentsInColorSpace):
+ (WebCore::CSSPropertyParserHelpers::mixColorComponents):
+ (WebCore::CSSPropertyParserHelpers::parseColorMixFunctionParameters):
+ (WebCore::CSSPropertyParserHelpers::HueColorAdjuster::fixupAnglesForInterpolation): Deleted.
+ (WebCore::CSSPropertyParserHelpers::HueColorAdjuster::HueColorAdjuster): Deleted.
+ (WebCore::CSSPropertyParserHelpers::ColorAdjuster::ColorAdjuster): Deleted.
+ (WebCore::CSSPropertyParserHelpers::consumeAdjuster): Deleted.
+ (WebCore::CSSPropertyParserHelpers::consumeAndUpdateAdjusterAtIndex): Deleted.
+ (WebCore::CSSPropertyParserHelpers::consumeAndUpdateAdjuster): Deleted.
+ (WebCore::CSSPropertyParserHelpers::consumeAdjusters): Deleted.
+ (WebCore::CSSPropertyParserHelpers::consumeMixComponents): Deleted.
+ (WebCore::CSSPropertyParserHelpers::normalizeAdjusterValues): Deleted.
+ (WebCore::CSSPropertyParserHelpers::remainingAdjustment): Deleted.
+ (WebCore::CSSPropertyParserHelpers::mixComponent): Deleted.
+ (WebCore::CSSPropertyParserHelpers::mixComponentAtIndex): Deleted.
+ (WebCore::CSSPropertyParserHelpers::mix): Deleted.
+ (WebCore::CSSPropertyParserHelpers::parseColorMixFunctionParametersUsingAdjusters): Deleted.
+ Update to the new syntax and remove component adjusters. They may come back for color-adjust()
+ in the future.
+
+ * platform/graphics/ColorModels.h:
+ * platform/graphics/ColorTypes.h:
+ (WebCore::clampedComponent):
+ (WebCore::assertInRange):
+ * platform/graphics/ColorUtilities.h:
+ (WebCore::invertedColorWithOverriddenAlpha):
+ Add support in the color models for annotating more about each component, now including
+ the type (angle, number or percentage). This allows algorithms generic algorithms to
+ operate on abstract color type components without specializing for each color type.
+
2021-03-24 Zan Dobersek <zdober...@igalia.com>
[GStreamer] Use imxvideoconvert_g2d element inside the sink when available
Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (274946 => 274947)
--- trunk/Source/WebCore/css/CSSValueKeywords.in 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in 2021-03-24 17:34:50 UTC (rev 274947)
@@ -1443,15 +1443,7 @@
// color-mix()
color-mix
-shorter
-longer
-increasing
-decreasing
-specified
-lightness
-chroma
-whiteness
-blackness
+in
// prefers-default-appearance
prefers
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (274946 => 274947)
--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2021-03-24 17:34:50 UTC (rev 274947)
@@ -1104,17 +1104,19 @@
return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) });
}
+template<typename ComponentType>
struct WhitenessBlackness {
- double whiteness;
- double blackness;
+ ComponentType whiteness;
+ ComponentType blackness;
};
-static WhitenessBlackness normalizeWhitenessBlackness(double whiteness, double blackness)
+
+template<typename ComponentType> static auto normalizeWhitenessBlackness(ComponentType whiteness, ComponentType blackness) -> WhitenessBlackness<ComponentType>
{
// Values outside of these ranges are not invalid, but are clamped to the
// ranges defined here at computed-value time.
- WhitenessBlackness result {
- clampTo(whiteness, 0.0, 100.0),
- clampTo(blackness, 0.0, 100.0)
+ WhitenessBlackness<ComponentType> result {
+ clampTo<ComponentType>(whiteness, 0.0, 100.0),
+ clampTo<ComponentType>(blackness, 0.0, 100.0)
};
// If the sum of these two arguments is greater than 100%, then at
@@ -1551,327 +1553,192 @@
return colorsToCompareAgainst[indexOfColorWithHigestContrastRatio];
}
-struct HueColorAdjuster {
- enum class Type {
- Shorter,
- Longer,
- Increasing,
- Decreasing,
- Specified
- };
-
- static std::pair<double, double> fixupAnglesForInterpolation(double theta1, double theta2, Type type)
- {
- ASSERT(theta1 >= 0.0);
- ASSERT(theta1 <= 360.0);
- ASSERT(theta2 >= 0.0);
- ASSERT(theta2 <= 360.0);
-
- switch (type) {
- case Type::Shorter: {
- auto difference = theta2 - theta1;
- if (difference > 180.0)
- return { theta1 + 360.0, theta2 };
- if (difference < -180.0)
- return { theta1, theta2 + 360.0 };
- return { theta1, theta2 };
- }
- case Type::Longer: {
- auto difference = theta2 - theta1;
- if (difference >= 0.0 && difference < 180.0)
- return { theta1 + 360.0, theta2 };
- if (difference >= -180.0 && difference < 0)
- return { theta1, theta2 + 360.0 };
- return { theta1, theta2 };
- }
- case Type::Increasing: {
- if (theta2 < theta1)
- return { theta1, theta2 + 360.0 };
- return { theta1, theta2 };
- }
- case Type::Decreasing: {
- if (theta1 < theta2)
- return { theta1 + 360.0, theta2 };
- return { theta1, theta2 };
- }
- case Type::Specified:
- return { theta1, theta2 };
- }
-
- RELEASE_ASSERT_NOT_REACHED();
- }
-
- HueColorAdjuster(double value = 0.0, Type type = Type::Shorter)
- : type { type }
- , value { value }
- {
- }
-
- Type type;
- double value;
+enum class ColorMixColorSpace {
+ Srgb,
+ Hsl,
+ Hwb,
+ Xyz,
+ Lab,
+ Lch
};
-template<typename C, CSSValueID ID0, typename Channel0, CSSValueID ID1, typename Channel1, CSSValueID ID2, typename Channel2, CSSValueID ID3, typename Channel3>
-struct ColorAdjuster {
- using ColorType = C;
- static constexpr auto channelCSSValueIDs = std::make_tuple(ID0, ID1, ID2, ID3);
+static Optional<ColorMixColorSpace> consumeColorMixColorSpaceAndComma(CSSParserTokenRange& args)
+{
+ auto consumeIdentAndComma = [](CSSParserTokenRange& args, ColorMixColorSpace colorSpace) -> Optional<ColorMixColorSpace> {
+ consumeIdentRaw(args);
+ if (!consumeCommaIncludingWhitespace(args))
+ return WTF::nullopt;
+ return colorSpace;
+ };
- ColorAdjuster() = default;
- explicit ColorAdjuster(double percentage)
- : channels { percentage, percentage, percentage, percentage }
- {
+ switch (args.peek().id()) {
+ case CSSValueHsl:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Hsl);
+ case CSSValueHwb:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Hwb);
+ case CSSValueLch:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Lch);
+ case CSSValueLab:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Lab);
+ case CSSValueXyz:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Xyz);
+ case CSSValueSRGB:
+ return consumeIdentAndComma(args, ColorMixColorSpace::Srgb);
+ default:
+ return WTF::nullopt;
}
+}
- std::tuple<Optional<Channel0>, Optional<Channel1>, Optional<Channel2>, Optional<Channel3>> channels;
-};
-
-using HSLColorAdjuster = ColorAdjuster<HSLA<float>, CSSValueHue, HueColorAdjuster, CSSValueSaturation, double, CSSValueLightness, double, CSSValueAlpha, double>;
-using HWBColorAdjuster = ColorAdjuster<HWBA<float>, CSSValueHue, HueColorAdjuster, CSSValueWhiteness, double, CSSValueBlackness, double, CSSValueAlpha, double>;
-using LCHColorAdjuster = ColorAdjuster<LCHA<float>, CSSValueLightness, double, CSSValueChroma, HueColorAdjuster, CSSValueHue, double, CSSValueAlpha, double>;
-using LabColorAdjuster = ColorAdjuster<Lab<float>, CSSValueLightness, double, CSSValueA, double, CSSValueB, double, CSSValueAlpha, double>;
-using SRGBColorAdjuster = ColorAdjuster<SRGBA<float>, CSSValueRed, double, CSSValueGreen, double, CSSValueBlue, double, CSSValueAlpha, double>;
-using XYZColorAdjuster = ColorAdjuster<XYZA<float, WhitePoint::D50>, CSSValueX, double, CSSValueY, double, CSSValueZ, double, CSSValueAlpha, double>;
-
-template<typename Adjuster> struct ColorMixComponent {
+struct ColorMixComponent {
Color color;
- Adjuster adjuster;
+ Optional<double> percentage;
};
-template<CSSValueID Ident, typename T> struct AdjusterConsumer;
+static Optional<ColorMixComponent> consumeColorMixComponent(CSSParserTokenRange& args, const CSSParserContext& context)
+{
+ ColorMixComponent result;
-template<CSSValueID Ident> struct AdjusterConsumer<Ident, HueColorAdjuster> {
- static Optional<HueColorAdjuster> consume(CSSParserTokenRange& args)
- {
- if (!consumeIdentRaw<Ident>(args))
- return WTF::nullopt;
+ if (auto percentage = consumePercentRaw(args))
+ result.percentage = percentage;
- HueColorAdjuster result;
- if (auto hueAdjustmentType = consumeHueAdjustmentType(args))
- result.type = *hueAdjustmentType;
+ result.color = consumeOriginColor(args, context);
+ if (!result.color.isValid())
+ return WTF::nullopt;
- // FIXME: Is clamping to 0 for negative percentages the right thing to do?
+ if (!result.percentage) {
if (auto percentage = consumePercentRaw(args))
- result.value = std::max(0.0, *percentage);
-
- // FIXME: Should an adjuster without a percetange be allowed?
- // e.g color-mix(hsl, teal hue, red);
-
- return result;
+ result.percentage = percentage;
}
- static Optional<HueColorAdjuster::Type> consumeHueAdjustmentType(CSSParserTokenRange& args)
- {
- switch (args.peek().id()) {
- case CSSValueShorter:
- consumeIdentRaw(args);
- return HueColorAdjuster::Type::Shorter;
- case CSSValueLonger:
- consumeIdentRaw(args);
- return HueColorAdjuster::Type::Longer;
- case CSSValueIncreasing:
- consumeIdentRaw(args);
- return HueColorAdjuster::Type::Increasing;
- case CSSValueDecreasing:
- consumeIdentRaw(args);
- return HueColorAdjuster::Type::Decreasing;
- case CSSValueSpecified:
- consumeIdentRaw(args);
- return HueColorAdjuster::Type::Specified;
- default:
- return WTF::nullopt;
- }
- }
-};
+ return result;
+}
-template<CSSValueID Ident> struct AdjusterConsumer<Ident, double> {
- static Optional<double> consume(CSSParserTokenRange& args)
- {
- if (!consumeIdentRaw<Ident>(args))
- return WTF::nullopt;
-
- // FIXME: Is clamping to 0 for negative percentages the right thing to do?
- if (auto percentage = consumePercentRaw(args))
- return std::max(0.0, *percentage);
-
- // FIXME: Should an adjuster without a percetange be allowed?
- // e.g color-mix(hsl, teal saturation, red);
-
- return 0;
- }
+struct ColorMixPercentages {
+ double p1;
+ double p2;
};
-template<CSSValueID Ident, typename T> inline decltype(auto) consumeAdjuster(CSSParserTokenRange& args)
+static ColorMixPercentages normalizedMixPercentages(const ColorMixComponent& mixComponents1, const ColorMixComponent& mixComponents2)
{
- return AdjusterConsumer<Ident, T>::consume(args);
-}
+ // The percentages are normalized as follows:
-template<std::size_t I, typename Adjuster> static bool consumeAndUpdateAdjusterAtIndex(CSSParserTokenRange& args, Adjuster& adjuster)
-{
- using AdjusterType = std::decay_t<decltype(std::get<I>(adjuster.channels).value())>;
- static constexpr CSSValueID Ident = std::get<I>(Adjuster::channelCSSValueIDs);
+ // 1. Let p1 be the first percentage and p2 the second one.
- if (auto adjustment = consumeAdjuster<Ident, AdjusterType>(args)) {
- std::get<I>(adjuster.channels) = *adjustment;
- return true;
- }
- return false;
-}
+ // 2. If both percentages are omitted, they each default to 50% (an equal mix of the two colors).
+ if (!mixComponents1.percentage && !mixComponents2.percentage)
+ return { 50.0, 50.0 };
+
+ ColorMixPercentages result;
-template<typename Adjuster> static bool consumeAndUpdateAdjuster(CSSParserTokenRange& args, Adjuster& adjuster)
-{
- if (consumeAndUpdateAdjusterAtIndex<0>(args, adjuster))
- return true;
- if (consumeAndUpdateAdjusterAtIndex<1>(args, adjuster))
- return true;
- if (consumeAndUpdateAdjusterAtIndex<2>(args, adjuster))
- return true;
- if (consumeAndUpdateAdjusterAtIndex<3>(args, adjuster))
- return true;
- return false;
-}
-
-template<typename Adjuster> static Adjuster consumeAdjusters(CSSParserTokenRange& args)
-{
- Adjuster adjuster;
- while (consumeAndUpdateAdjuster(args, adjuster)) {
- // Keep consuming until there are no more adjusters.
+ if (!mixComponents2.percentage) {
+ // 3. Otherwise, if p2 is omitted, it becomes 100% - p1
+ result.p1 = *mixComponents1.percentage;
+ result.p2 = 100.0 - result.p1;
+ } else if (!mixComponents1.percentage) {
+ // 4. Otherwise, if p1 is omitted, it becomes 100% - p2
+ result.p2 = *mixComponents2.percentage;
+ result.p1 = 100.0 - result.p2;
+ } else {
+ result.p1 = *mixComponents1.percentage;
+ result.p2 = *mixComponents2.percentage;
}
-
- return adjuster;
-}
-template<typename Adjuster> static Optional<ColorMixComponent<Adjuster>> consumeMixComponents(CSSParserTokenRange& args, const CSSParserContext& context)
-{
- auto originColor = consumeOriginColor(args, context);
- if (!originColor.isValid())
- return WTF::nullopt;
+ auto sum = result.p1 + result.p2;
- // FIXME: Is clamping to 0 for negative percentages the right thing to do?
- if (auto percentage = consumePercentRaw(args))
- return { { WTFMove(originColor), Adjuster { std::max(0.0, *percentage) } } };
+ // 5. If the percentages sum to zero do something, tbd. (FIXME: We just use 50 / 50 for this case for now).
+ if (sum == 0)
+ return { 50.0, 50.0 };
- return { { WTFMove(originColor), consumeAdjusters<Adjuster>(args) } };
-}
-
-static std::pair<HueColorAdjuster, HueColorAdjuster> normalizeAdjusterValues(HueColorAdjuster adjuster1, HueColorAdjuster adjuster2)
-{
- if (auto sum = adjuster1.value + adjuster2.value; sum != 100.0) {
- adjuster1.value *= 100.0 / sum;
- adjuster2.value *= 100.0 / sum;
+ if (sum != 100.0) {
+ // 6. Otherwise, if both are provided but do not add up to 100%, they are scaled accordingly so that they
+ // add up to 100%. This means that p1 becomes p1 / (p1 + p2) and p2 becomes p2 / (p1 + p2).
+ result.p1 *= 100.0 / sum;
+ result.p2 *= 100.0 / sum;
}
- return { adjuster1, adjuster2 };
+ return result;
}
-static std::pair<double, double> normalizeAdjusterValues(double adjuster1, double adjuster2)
+// Normalization is special cased for HWBA, which needs to normalize the whiteness and blackness components and convert to sRGB
+// and HSLA, which just needs to be converted to sRGB. All other color types can go through this non-specialized case.
+
+template<typename ColorType> inline Color makeColorTypeByNormalizingComponentsAfterMix(const ColorComponents<float>& colorComponents)
{
- if (auto sum = adjuster1 + adjuster2; sum != 100.0) {
- adjuster1 *= 100.0 / sum;
- adjuster2 *= 100.0 / sum;
- }
-
- return { adjuster1, adjuster2 };
+ return makeFromComponents<ColorType>(colorComponents);
}
-static HueColorAdjuster remainingAdjustment(HueColorAdjuster adjuster)
+template<> inline Color makeColorTypeByNormalizingComponentsAfterMix<HWBA<float>>(const ColorComponents<float>& colorComponents)
{
- return { 100.0 - adjuster.value, adjuster.type };
-}
+ auto [hue, whiteness, blackness, alpha] = colorComponents;
+ auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(whiteness, blackness);
-static double remainingAdjustment(double adjuster)
-{
- return 100.0 - adjuster;
+ return convertColor<SRGBA<uint8_t>>(HWBA<float> { hue, normalizedWhitness, normalizedBlackness, alpha });
}
-template<typename AdjusterType> static auto normalizeAdjusterValues(Optional<AdjusterType> adjuster1, Optional<AdjusterType> adjuster2) -> std::pair<AdjusterType, AdjusterType>
+template<> inline Color makeColorTypeByNormalizingComponentsAfterMix<HSLA<float>>(const ColorComponents<float>& colorComponents)
{
- if (adjuster1 && adjuster2)
- return normalizeAdjusterValues(*adjuster1, *adjuster2);
- if (!adjuster1 && adjuster2)
- return { remainingAdjustment(*adjuster2), *adjuster2 };
- if (adjuster1 && !adjuster2)
- return { *adjuster1, remainingAdjustment(*adjuster1) };
- // When neigher mix component provides an adjuster, the result is the non-modified
- // channel from from the first color.
- ASSERT(!adjuster1 && !adjuster2);
- return { 100.0, 0.0 };
+ return convertColor<SRGBA<uint8_t>>(makeFromComponents<HSLA<float>>(colorComponents));
}
-static double mixComponent(float component1, HueColorAdjuster adjustment1, float component2, HueColorAdjuster adjustment2)
+template<size_t I, typename ComponentType> static void fixupHueComponentsPriorToMix(ColorComponents<ComponentType>& colorComponents1, ColorComponents<ComponentType>& colorComponents2)
{
- // FIXME: The spec does not indicate what to do if two different hue types are specified. We always use the first one for now,
- // though we probably should take into account whether it was actually specified or is the default value. That normalization
- // should happen in normalizeAdjusterValues().
+ auto normalizeAnglesUsingShorterAlgorithm = [] (auto theta1, auto theta2) -> std::pair<ComponentType, ComponentType> {
+ // https://drafts.csswg.org/css-color-4/#hue-shorter
+ auto difference = theta2 - theta1;
+ if (difference > 180.0)
+ return { theta1 + 360.0, theta2 };
+ if (difference < -180.0)
+ return { theta1, theta2 + 360.0 };
+ return { theta1, theta2 };
+ };
- auto [fixedUpComponent1, fixedUpComponent2] = HueColorAdjuster::fixupAnglesForInterpolation(component1, component2, adjustment1.type);
- auto result = (fixedUpComponent1 * (adjustment1.value / 100.0)) + (fixedUpComponent2 * (adjustment2.value / 100.0));
- // FIXME: Check if this full normalization is needed.
- return normalizeHue(result);
+ // As no other interpolation type was specified, all angles should be normalized to use the "shorter" algorithm.
+ auto [theta1, theta2] = normalizeAnglesUsingShorterAlgorithm(colorComponents1[I], colorComponents2[I]);
+ colorComponents1[I] = theta1;
+ colorComponents2[I] = theta2;
}
-static double mixComponent(float component1, double adjustment1, float component2, double adjustment2)
+template<typename ColorType> static Color mixColorComponentsInColorSpace(ColorMixPercentages mixPercentages, const Color& color1, const Color& color2)
{
- return (component1 * (adjustment1 / 100.0)) + (component2 * (adjustment2 / 100.0));
-}
+ auto colorComponents1 = asColorComponents(color1.template toColorTypeLossy<ColorType>());
+ auto colorComponents2 = asColorComponents(color2.template toColorTypeLossy<ColorType>());
-template<std::size_t I, typename Adjuster> static double mixComponentAtIndex(const ColorComponents<float>& color1, const Adjuster& adjuster1, const ColorComponents<float>& color2, const Adjuster& adjuster2)
-{
- auto [normalizedAdjuster1Value, normalizedAdjuster2Value] = normalizeAdjusterValues(std::get<I>(adjuster1.channels), std::get<I>(adjuster2.channels));
- return mixComponent(color1[I], normalizedAdjuster1Value, color2[I], normalizedAdjuster2Value);
-}
+ // Perform fixups on any hue/angle components.
+ constexpr auto componentInfo = ColorType::Model::componentInfo;
+ if constexpr (componentInfo[0].type == ColorComponentType::Angle)
+ fixupHueComponentsPriorToMix<0>(colorComponents1, colorComponents2);
+ if constexpr (componentInfo[1].type == ColorComponentType::Angle)
+ fixupHueComponentsPriorToMix<1>(colorComponents1, colorComponents2);
+ if constexpr (componentInfo[2].type == ColorComponentType::Angle)
+ fixupHueComponentsPriorToMix<2>(colorComponents1, colorComponents2);
-template<typename ColorType> inline ColorType makeColorTypeByNormalizingComponentsAfterMix(double channel0, double channel1, double channel2, double channel3)
-{
- return { static_cast<float>(channel0), static_cast<float>(channel1), static_cast<float>(channel2), static_cast<float>(channel3) };
-}
+ auto colorComponentsMixed = mapColorComponents([&] (auto componentFromColor1, auto componentFromColor2) -> float {
+ return (componentFromColor1 * mixPercentages.p1 / 100.0) + (componentFromColor2 * mixPercentages.p2 / 100.0);
+ }, colorComponents1, colorComponents2);
-template<> inline HWBA<float> makeColorTypeByNormalizingComponentsAfterMix<HWBA<float>>(double hue, double whiteness, double blackness, double alpha)
-{
- auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(whiteness, blackness);
- return { static_cast<float>(hue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(alpha) };
+ return makeColorTypeByNormalizingComponentsAfterMix<ColorType>(colorComponentsMixed);
}
-template<typename Adjuster> static typename Adjuster::ColorType mix(const ColorMixComponent<Adjuster>& mixComponents1, const ColorMixComponent<Adjuster>& mixComponents2)
+static Color mixColorComponents(ColorMixColorSpace colorSpace, const ColorMixComponent& mixComponents1, const ColorMixComponent& mixComponents2)
{
- using ColorType = typename Adjuster::ColorType;
+ auto mixPercentages = normalizedMixPercentages(mixComponents1, mixComponents2);
- auto color1 = asColorComponents(mixComponents1.color.template toColorTypeLossy<ColorType>());
- auto color2 = asColorComponents(mixComponents2.color.template toColorTypeLossy<ColorType>());
-
- auto adjuster1 = mixComponents1.adjuster;
- auto adjuster2 = mixComponents2.adjuster;
-
- if (!std::get<0>(adjuster1.channels) && !std::get<1>(adjuster1.channels) && !std::get<2>(adjuster1.channels) && !std::get<3>(adjuster1.channels) && !std::get<0>(adjuster2.channels) && !std::get<1>(adjuster2.channels) && !std::get<2>(adjuster2.channels) && !std::get<3>(adjuster2.channels)) {
- // No adjusters being specified at all is special cased to mean mix 50-50.
- adjuster1 = Adjuster { 50.0 };
- adjuster2 = Adjuster { 50.0 };
+ switch (colorSpace) {
+ case ColorMixColorSpace::Hsl:
+ return mixColorComponentsInColorSpace<HSLA<float>>(mixPercentages, mixComponents1.color, mixComponents2.color);
+ case ColorMixColorSpace::Hwb:
+ return mixColorComponentsInColorSpace<HWBA<float>>(mixPercentages, mixComponents1.color, mixComponents2.color);
+ case ColorMixColorSpace::Lch:
+ return mixColorComponentsInColorSpace<LCHA<float>>(mixPercentages, mixComponents1.color, mixComponents2.color);
+ case ColorMixColorSpace::Lab:
+ return mixColorComponentsInColorSpace<Lab<float>>(mixPercentages, mixComponents1.color, mixComponents2.color);
+ case ColorMixColorSpace::Xyz:
+ return mixColorComponentsInColorSpace<XYZA<float, WhitePoint::D50>>(mixPercentages, mixComponents1.color, mixComponents2.color);
+ case ColorMixColorSpace::Srgb:
+ return mixColorComponentsInColorSpace<SRGBA<float>>(mixPercentages, mixComponents1.color, mixComponents2.color);
}
-
- auto channel0 = mixComponentAtIndex<0>(color1, adjuster1, color2, adjuster2);
- auto channel1 = mixComponentAtIndex<1>(color1, adjuster1, color2, adjuster2);
- auto channel2 = mixComponentAtIndex<2>(color1, adjuster1, color2, adjuster2);
- auto channel3 = mixComponentAtIndex<3>(color1, adjuster1, color2, adjuster2);
-
- return makeColorTypeByNormalizingComponentsAfterMix<ColorType>(channel0, channel1, channel2, channel3);
}
-template<typename Adjuster> static Optional<typename Adjuster::ColorType> parseColorMixFunctionParametersUsingAdjusters(CSSParserTokenRange& args, const CSSParserContext& context)
-{
- auto mixComponents1 = consumeMixComponents<Adjuster>(args, context);
- if (!mixComponents1)
- return WTF::nullopt;
-
- // FIXME: This comma is not in the grammar, but is in all the examples.
- if (!consumeCommaIncludingWhitespace(args))
- return WTF::nullopt;
-
- auto mixComponents2 = consumeMixComponents<Adjuster>(args, context);
- if (!mixComponents2)
- return WTF::nullopt;
-
- return mix(*mixComponents1, *mixComponents2);
-}
-
static Color parseColorMixFunctionParameters(CSSParserTokenRange& range, const CSSParserContext& context)
{
ASSERT(range.peek().functionId() == CSSValueColorMix);
@@ -1881,50 +1748,28 @@
auto args = consumeFunction(range);
- auto consumeIdentAndComma = [](CSSParserTokenRange& args) {
- consumeIdentRaw(args);
- // FIXME: This comma is not in the grammar, but is in all the examples.
- return consumeCommaIncludingWhitespace(args);
- };
+ if (!consumeIdentRaw<CSSValueIn>(args))
+ return { };
+
+ auto colorSpace = consumeColorMixColorSpaceAndComma(args);
+ if (!colorSpace)
+ return { };
- switch (args.peek().id()) {
- case CSSValueHsl: {
- if (!consumeIdentAndComma(args))
- return { };
- auto hsl = parseColorMixFunctionParametersUsingAdjusters<HSLColorAdjuster>(args, context);
- if (!hsl)
- return { };
- return convertColor<SRGBA<uint8_t>>(*hsl);
- }
- case CSSValueHwb: {
- if (!consumeIdentAndComma(args))
- return { };
- auto hwb = parseColorMixFunctionParametersUsingAdjusters<HWBColorAdjuster>(args, context);
- if (!hwb)
- return { };
- return convertColor<SRGBA<uint8_t>>(*hwb);
- }
- case CSSValueLch:
- if (!consumeIdentAndComma(args))
- return { };
- return parseColorMixFunctionParametersUsingAdjusters<LCHColorAdjuster>(args, context);
- case CSSValueLab:
- if (!consumeIdentAndComma(args))
- return { };
- return parseColorMixFunctionParametersUsingAdjusters<LabColorAdjuster>(args, context);
- case CSSValueXyz:
- if (!consumeIdentAndComma(args))
- return { };
- return parseColorMixFunctionParametersUsingAdjusters<XYZColorAdjuster>(args, context);
- case CSSValueSRGB:
- if (!consumeIdentAndComma(args))
- return { };
- return parseColorMixFunctionParametersUsingAdjusters<SRGBColorAdjuster>(args, context);
- default:
- // Default to using LCH if no color space is provided as per the spec.
- // FIXME: This behavior is unnecessarily confusing, we should remove the default from the spec.
- return parseColorMixFunctionParametersUsingAdjusters<LCHColorAdjuster>(args, context);
- }
+ auto mixComponent1 = consumeColorMixComponent(args, context);
+ if (!mixComponent1)
+ return { };
+
+ if (!consumeCommaIncludingWhitespace(args))
+ return { };
+
+ auto mixComponent2 = consumeColorMixComponent(args, context);
+ if (!mixComponent2)
+ return { };
+
+ if (!args.atEnd())
+ return { };
+
+ return mixColorComponents(*colorSpace, *mixComponent1, *mixComponent2);
}
static Optional<SRGBA<uint8_t>> parseHexColor(CSSParserTokenRange& range, bool acceptQuirkyColors)
Modified: trunk/Source/WebCore/platform/graphics/ColorModels.h (274946 => 274947)
--- trunk/Source/WebCore/platform/graphics/ColorModels.h 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/platform/graphics/ColorModels.h 2021-03-24 17:34:50 UTC (rev 274947)
@@ -31,7 +31,7 @@
namespace WebCore {
template<typename> struct AlphaTraits;
-template<typename> struct ColorComponentRange;
+template<typename> struct ColorComponentInfo;
template<typename> struct ExtendedRGBModel;
template<typename> struct HSLModel;
template<typename> struct HWBModel;
@@ -51,79 +51,86 @@
static constexpr uint8_t opaque = 255;
};
-template<typename T> struct ColorComponentRange {
+enum class ColorComponentType {
+ Angle,
+ Number,
+ Percentage
+};
+
+template<typename T> struct ColorComponentInfo {
T min;
T max;
+ ColorComponentType type;
};
template<> struct ExtendedRGBModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number }
} };
static constexpr bool isInvertible = false;
};
template<> struct HSLModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { 0, 360 },
- { 0, 100 },
- { 0, 100 }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { 0, 360, ColorComponentType::Angle },
+ { 0, 100, ColorComponentType::Percentage },
+ { 0, 100, ColorComponentType::Percentage }
} };
static constexpr bool isInvertible = false;
};
template<> struct HWBModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { 0, 360 },
- { 0, 100 },
- { 0, 100 }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { 0, 360, ColorComponentType::Angle },
+ { 0, 100, ColorComponentType::Percentage },
+ { 0, 100, ColorComponentType::Percentage }
} };
static constexpr bool isInvertible = false;
};
template<> struct LabModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { 0, std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { 0, std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number }
} };
static constexpr bool isInvertible = false;
};
template<> struct LCHModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { 0, std::numeric_limits<float>::infinity() },
- { 0, std::numeric_limits<float>::infinity() },
- { 0, 360 }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { 0, std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { 0, std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { 0, 360, ColorComponentType::Angle }
} };
static constexpr bool isInvertible = false;
};
template<> struct RGBModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { 0, 1 },
- { 0, 1 },
- { 0, 1 }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { 0, 1, ColorComponentType::Number },
+ { 0, 1, ColorComponentType::Number },
+ { 0, 1, ColorComponentType::Number }
} };
static constexpr bool isInvertible = true;
};
template<> struct RGBModel<uint8_t> {
- static constexpr std::array<ColorComponentRange<uint8_t>, 3> ranges { {
- { 0, 255 },
- { 0, 255 },
- { 0, 255 }
+ static constexpr std::array<ColorComponentInfo<uint8_t>, 3> componentInfo { {
+ { 0, 255, ColorComponentType::Number },
+ { 0, 255, ColorComponentType::Number },
+ { 0, 255, ColorComponentType::Number }
} };
static constexpr bool isInvertible = true;
};
template<> struct XYZModel<float> {
- static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
- { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
+ static constexpr std::array<ColorComponentInfo<float>, 3> componentInfo { {
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number },
+ { -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), ColorComponentType::Number }
} };
static constexpr bool isInvertible = false;
};
Modified: trunk/Source/WebCore/platform/graphics/ColorTypes.h (274946 => 274947)
--- trunk/Source/WebCore/platform/graphics/ColorTypes.h 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/platform/graphics/ColorTypes.h 2021-03-24 17:34:50 UTC (rev 274947)
@@ -55,24 +55,24 @@
{
static_assert(std::is_integral_v<T>);
- constexpr auto range = ColorType::Model::ranges[Index];
- return std::clamp<T>(c, range.min, range.max);
+ constexpr auto componentInfo = ColorType::Model::componentInfo[Index];
+ return std::clamp<T>(c, componentInfo.min, componentInfo.max);
}
template<typename ColorType, unsigned Index> constexpr float clampedComponent(float c)
{
- constexpr auto range = ColorType::Model::ranges[Index];
+ constexpr auto componentInfo = ColorType::Model::componentInfo[Index];
- if constexpr (range.min == -std::numeric_limits<float>::infinity() && range.max == std::numeric_limits<float>::infinity())
+ if constexpr (componentInfo.min == -std::numeric_limits<float>::infinity() && componentInfo.max == std::numeric_limits<float>::infinity())
return c;
- if constexpr (range.min == -std::numeric_limits<float>::infinity())
- return std::min(c, range.max);
+ if constexpr (componentInfo.min == -std::numeric_limits<float>::infinity())
+ return std::min(c, componentInfo.max);
- if constexpr (range.max == std::numeric_limits<float>::infinity())
- return std::max(c, range.min);
+ if constexpr (componentInfo.max == std::numeric_limits<float>::infinity())
+ return std::max(c, componentInfo.min);
- return std::clamp(c, range.min, range.max);
+ return std::clamp(c, componentInfo.min, componentInfo.max);
}
template<typename ColorType, unsigned Index, typename T> constexpr T clampedComponent(const ColorComponents<T>& c)
@@ -127,8 +127,8 @@
if constexpr (std::is_same_v<typename T::ComponentType, float>) {
auto components = asColorComponents(color);
for (unsigned i = 0; i < 3; ++i) {
- ASSERT_WITH_MESSAGE(components[i] >= T::Model::ranges[i].min, "Component at index %d is %f and is less than the allowed minimum %f", i, components[i], T::Model::ranges[i].min);
- ASSERT_WITH_MESSAGE(components[i] <= T::Model::ranges[i].max, "Component at index %d is %f and is greater than the allowed maximum %f", i, components[i], T::Model::ranges[i].max);
+ ASSERT_WITH_MESSAGE(components[i] >= T::Model::componentInfo[i].min, "Component at index %d is %f and is less than the allowed minimum %f", i, components[i], T::Model::componentInfo[i].min);
+ ASSERT_WITH_MESSAGE(components[i] <= T::Model::componentInfo[i].max, "Component at index %d is %f and is greater than the allowed maximum %f", i, components[i], T::Model::componentInfo[i].max);
}
ASSERT_WITH_MESSAGE(color.alpha >= AlphaTraits<typename T::ComponentType>::transparent, "Alpha is %f and is less than the allowed minimum (transparent) %f", color.alpha, AlphaTraits<typename T::ComponentType>::transparent);
ASSERT_WITH_MESSAGE(color.alpha <= AlphaTraits<typename T::ComponentType>::opaque, "Alpha is %f and is greater than the allowed maximum (opaque) %f", color.alpha, AlphaTraits<typename T::ComponentType>::opaque);
Modified: trunk/Source/WebCore/platform/graphics/ColorUtilities.h (274946 => 274947)
--- trunk/Source/WebCore/platform/graphics/ColorUtilities.h 2021-03-24 17:31:28 UTC (rev 274946)
+++ trunk/Source/WebCore/platform/graphics/ColorUtilities.h 2021-03-24 17:34:50 UTC (rev 274947)
@@ -125,7 +125,7 @@
auto copy = components;
for (unsigned i = 0; i < 3; ++i)
- copy[i] = ColorType::Model::ranges[i].max - components[i];
+ copy[i] = ColorType::Model::componentInfo[i].max - components[i];
copy[3] = convertByteAlphaTo<typename ColorType::ComponentType>(overrideAlpha);
return makeFromComponents<ColorType>(copy);
@@ -139,7 +139,7 @@
auto copy = components;
for (unsigned i = 0; i < 3; ++i)
- copy[i] = ColorType::Model::ranges[i].max - components[i];
+ copy[i] = ColorType::Model::componentInfo[i].max - components[i];
copy[3] = convertFloatAlphaTo<typename ColorType::ComponentType>(overrideAlpha);
return makeFromComponents<ColorType>(copy);
@@ -164,8 +164,8 @@
constexpr bool isBlack(const ColorType& color)
{
auto [c1, c2, c3, alpha] = color;
- constexpr auto ranges = ColorType::Model::ranges;
- return c1 == ranges[0].min && c2 == ranges[1].min && c3 == ranges[2].min && alpha == AlphaTraits<typename ColorType::ComponentType>::opaque;
+ constexpr auto componentInfo = ColorType::Model::componentInfo;
+ return c1 == componentInfo[0].min && c2 == componentInfo[1].min && c3 == componentInfo[2].min && alpha == AlphaTraits<typename ColorType::ComponentType>::opaque;
}
template<WhitePoint W> constexpr bool isWhite(const XYZA<float, W>& color)
@@ -187,8 +187,8 @@
constexpr bool isWhite(const ColorType& color)
{
auto [c1, c2, c3, alpha] = color;
- constexpr auto ranges = ColorType::Model::ranges;
- return c1 == ranges[0].max && c2 == ranges[1].max && c3 == ranges[2].max && alpha == AlphaTraits<typename ColorType::ComponentType>::opaque;
+ constexpr auto componentInfo = ColorType::Model::componentInfo;
+ return c1 == componentInfo[0].max && c2 == componentInfo[1].max && c3 == componentInfo[2].max && alpha == AlphaTraits<typename ColorType::ComponentType>::opaque;
}
constexpr uint16_t fastMultiplyBy255(uint16_t value)