Title: [274947] trunk
Revision
274947
Author
wei...@apple.com
Date
2021-03-24 10:34:50 -0700 (Wed, 24 Mar 2021)

Log Message

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.

Source/WebCore:

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.

LayoutTests:

* fast/css/parsing-color-mix-expected.txt:
* fast/css/parsing-color-mix.html:
Update test and results for vastly simplified color-mix().

Modified Paths

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)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to