Changeset 289396 in webkit


Ignore:
Timestamp:
Feb 8, 2022 10:57:30 AM (5 months ago)
Author:
weinig@apple.com
Message:

Conversion to a color space with a smaller gamut should perform gamut mapping
https://bugs.webkit.org/show_bug.cgi?id=236200

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Update tests to include more examples that force gamut mapping and update the results
of a few existing ones to account for the new algorithm.

  • web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt:
  • web-platform-tests/css/css-color/parsing/color-mix-computed.html:
  • web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt:
  • web-platform-tests/css/css-color/parsing/color-mix-valid.html:
  • web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt:
  • web-platform-tests/css/css-color/parsing/relative-color-computed.html:
  • web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt:
  • web-platform-tests/css/css-color/parsing/relative-color-valid.html:

Source/WebCore:

CSS Color now defines that gamut mapping should happen when converting to an RGB color space
with bounded gamut that is smaller than the origin color's color space. Specifically, it
specifies the use of a new "CSS gamut mapping algorithm" https://drafts.csswg.org/css-color/#css-gamut-mapping
which implements a relative colorimetric intent mapping with colors inside the destination
gamut unchanged.

The previous behavior we implemented was to clip out of gamut colors to the gamut (e.g.
color(srgb 1.4 -0.2 .5) would become color(srgb 1 0 .5)) which can lead to very odd results.

To keep things simple, the gamut mapping has been incorporated directly into the main color
conversion pipeline, replacing the call to makeFromComponentsClampingExceptAlpha in toBounded()
with one implements the new algorithm. To accomadate this, the pipeline was modified so that
the matrix conversions now only happen to/from extended-linear and XYZ color types, rather than
the old behavior which allowed shortcuting from bounded-linear, which was ok because the clip
would result in the same value. Since conversion from bounded-linear to extended-linear is free
(just a type change, no conversion), the only additional cost here is the gamut mapping.

The implementation of the CSS gamut mapping algorithm itself is a naive iterative bisection
implementation based on the psuedo-code from the spec. As an optimization in the future, we should
consider implementing an analytic solution, which will be more complicated, but likely faster.

Currently, the only place where the effect of this new gamut mapping behavior will be visible is
via functions that explicitly convert to a bounded color space, specifically the CSS color-mix()
function and relative color syntax. Ultimately, we should also be using this to map CSS colors
to the output color space of the screen / HTML canvas, but finding the right place to do that
is not a part of this initial change.

  • platform/graphics/ColorConversion.cpp:

(WebCore::ColorConversion<Lab<float>, XYZA<float, WhitePoint::D50>>::convert):
(WebCore::ColorConversion<OKLab<float>, XYZA<float, WhitePoint::D65>>::convert):
Add call to makeFromComponentsClampingExceptAlpha at the end of conversion to Lab/OKLab
as the conversion functions can produce lightness values just ever so less than 0.
In practice, only the lightness value is bounded, so it is the only thing that actually
gets clamped thanks to the constexpr nature of clampedComponent().

  • platform/graphics/ColorConversion.h:

(WebCore::computeDeltaEOK):
Add implementation of the deltaEOK algorithm.

(WebCore::ClipGamutMapping::mapToBoundedGamut):
Add implementation of the degenerate gamut mapping algorithm.

(WebCore::CSSGamutMapping::mapToBoundedGamut):
Add implementation of the CSS gamut mapping algorithm.

(WebCore::ColorConversion::convert):
Add a new step to the main pipeline that explicitly handles bounds conversions to/from
extended-linear so that the matrix conversions can rely on always working in extended space.

(WebCore::ColorConversion::toBounded):
Replace call to clamp with call out to gamut mapping algorithm.

(WebCore::ColorConversion::handleMatrixConversion):
Replace makeFromComponentsClampingExceptAlpha with makeFromComponents now that all conversions
are in the extended space and clamping is no-op.

  • platform/graphics/ColorTypes.h:

(WebCore::inGamut):
(WebCore::colorIfInGamut):
(WebCore::clipToGamut):
Add some helpers to check/convert/clip to the bounded gamut of RGB types.

Tools:

  • TestWebKitAPI/Tests/WebCore/ColorTests.cpp:

(TestWebKitAPI::TEST):
Update color conversion tests to account for gamut mapping and add a new test
that bypasses gamut mapping by converting to extended sRGB.

LayoutTests:

  • platform/gtk/TestExpectations:

Add more tests that are only failing on the GTK bots due to a small floating point issues that needs further investigation.

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r289381 r289396  
     12022-02-08  Sam Weinig  <weinig@apple.com>
     2
     3        Conversion to a color space with a smaller gamut should perform gamut mapping
     4        https://bugs.webkit.org/show_bug.cgi?id=236200
     5
     6        Reviewed by Darin Adler.
     7
     8        * platform/gtk/TestExpectations:
     9        Add more tests that are only failing on the GTK bots due to a small floating point issues that needs further investigation.
     10
    1112022-02-08  Youenn Fablet  <youenn@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r289247 r289396  
     12022-02-08  Sam Weinig  <weinig@apple.com>
     2
     3        Conversion to a color space with a smaller gamut should perform gamut mapping
     4        https://bugs.webkit.org/show_bug.cgi?id=236200
     5
     6        Reviewed by Darin Adler.
     7
     8        Update tests to include more examples that force gamut mapping and update the results
     9        of a few existing ones to account for the new algorithm.
     10
     11        * web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt:
     12        * web-platform-tests/css/css-color/parsing/color-mix-computed.html:
     13        * web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt:
     14        * web-platform-tests/css/css-color/parsing/color-mix-valid.html:
     15        * web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt:
     16        * web-platform-tests/css/css-color/parsing/relative-color-computed.html:
     17        * web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt:
     18        * web-platform-tests/css/css-color/parsing/relative-color-valid.html:
     19
    1202022-02-07  Chris Dumez  <cdumez@apple.com>
    221
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt

    r288427 r289396  
    6363PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))'
    6464PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))'
     65PASS Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)'
     66PASS Property color value 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
     67PASS Property color value 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
     68PASS Property color value 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)'
     69PASS Property color value 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)'
     70PASS Property color value 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
     71PASS Property color value 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
     72PASS Property color value 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
     73PASS Property color value 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
    6574PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))'
    6675PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))'
     
    126135PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))'
    127136PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))'
     137PASS Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)'
     138PASS Property color value 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
     139PASS Property color value 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)'
     140PASS Property color value 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)'
     141PASS Property color value 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)'
     142PASS Property color value 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
     143PASS Property color value 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)'
     144PASS Property color value 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
     145PASS Property color value 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)'
    128146PASS Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))'
    129147PASS Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))'
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html

    r288427 r289396  
    9898    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
    9999
     100    test_computed_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     101    test_computed_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     102    test_computed_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     103    test_computed_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     104    test_computed_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     105    test_computed_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     106    test_computed_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     107    test_computed_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     108    test_computed_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
     109
    100110
    101111    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
     
    170180    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`));
    171181    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
     182
     183    test_computed_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     184    test_computed_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     185    test_computed_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     186    test_computed_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     187    test_computed_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     188    test_computed_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     189    test_computed_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     190    test_computed_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     191    test_computed_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    172192
    173193    for (const colorSpace of [ "lch", "oklch" ]) {
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt

    r288427 r289396  
    6363PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value
    6464PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value
     65PASS e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value
     66PASS e.style['color'] = "color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
     67PASS e.style['color'] = "color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
     68PASS e.style['color'] = "color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
     69PASS e.style['color'] = "color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
     70PASS e.style['color'] = "color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
     71PASS e.style['color'] = "color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
     72PASS e.style['color'] = "color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
     73PASS e.style['color'] = "color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
    6574PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value
    6675PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value
     
    126135PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value
    127136PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value
     137PASS e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value
     138PASS e.style['color'] = "color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
     139PASS e.style['color'] = "color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value
     140PASS e.style['color'] = "color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
     141PASS e.style['color'] = "color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value
     142PASS e.style['color'] = "color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
     143PASS e.style['color'] = "color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value
     144PASS e.style['color'] = "color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
     145PASS e.style['color'] = "color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value
    128146PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value
    129147PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html

    r288427 r289396  
    9898    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
    9999
     100    test_valid_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     101    test_valid_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     102    test_valid_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     103    test_valid_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     104    test_valid_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     105    test_valid_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     106    test_valid_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     107    test_valid_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     108    test_valid_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
     109
    100110
    101111    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
     
    170180    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`));
    171181    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
     182
     183    test_valid_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     184    test_valid_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     185    test_valid_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     186    test_valid_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     187    test_valid_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     188    test_valid_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     189    test_valid_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     190    test_valid_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     191    test_valid_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    172192
    173193    for (const colorSpace of [ "lch", "oklch" ]) {
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed-expected.txt

    r288143 r289396  
    66PASS Property color value 'rgb(from rgb(from rebeccapurple r g b) r g b)'
    77PASS Property color value 'rgb(from color(display-p3 0 1 0) r g b / alpha)'
     8PASS Property color value 'rgb(from lab(100% 104.3 -50.9) r g b)'
     9PASS Property color value 'rgb(from lab(0% 104.3 -50.9) r g b)'
     10PASS Property color value 'rgb(from lch(100% 116 334) r g b)'
     11PASS Property color value 'rgb(from lch(0% 116 334) r g b)'
     12PASS Property color value 'rgb(from oklab(100% 0.365 -0.16) r g b)'
     13PASS Property color value 'rgb(from oklab(0% 0.365 -0.16) r g b)'
     14PASS Property color value 'rgb(from oklch(100% 0.399 336.3) r g b)'
     15PASS Property color value 'rgb(from oklch(0% 0.399 336.3) r g b)'
    816PASS Property color value 'rgb(from rebeccapurple 0 0 0)'
    917PASS Property color value 'rgb(from rebeccapurple 0 0 0 / 0)'
     
    7583PASS Property color value 'hsl(from hsl(from rebeccapurple h s l) h s l)'
    7684PASS Property color value 'hsl(from color(display-p3 0 1 0) h s l / alpha)'
     85PASS Property color value 'hsl(from lab(100% 104.3 -50.9) h s l)'
     86PASS Property color value 'hsl(from lab(0% 104.3 -50.9) h s l)'
     87PASS Property color value 'hsl(from lch(100% 116 334) h s l)'
     88PASS Property color value 'hsl(from lch(0% 116 334) h s l)'
     89PASS Property color value 'hsl(from oklab(100% 0.365 -0.16) h s l)'
     90PASS Property color value 'hsl(from oklab(0% 0.365 -0.16) h s l)'
     91PASS Property color value 'hsl(from oklch(100% 0.399 336.3) h s l)'
     92PASS Property color value 'hsl(from oklch(0% 0.399 336.3) h s l)'
    7793PASS Property color value 'hsl(from rebeccapurple 0 0% 0%)'
    7894PASS Property color value 'hsl(from rebeccapurple 0deg 0% 0%)'
     
    129145PASS Property color value 'hwb(from hwb(from rebeccapurple h w b) h w b)'
    130146PASS Property color value 'hwb(from color(display-p3 0 1 0) h w b / alpha)'
     147PASS Property color value 'hwb(from lab(100% 104.3 -50.9) h w b)'
     148PASS Property color value 'hwb(from lab(0% 104.3 -50.9) h w b)'
     149PASS Property color value 'hwb(from lch(100% 116 334) h w b)'
     150PASS Property color value 'hwb(from lch(0% 116 334) h w b)'
     151PASS Property color value 'hwb(from oklab(100% 0.365 -0.16) h w b)'
     152PASS Property color value 'hwb(from oklab(0% 0.365 -0.16) h w b)'
     153PASS Property color value 'hwb(from oklch(100% 0.399 336.3) h w b)'
     154PASS Property color value 'hwb(from oklch(0% 0.399 336.3) h w b)'
    131155PASS Property color value 'hwb(from rebeccapurple 0 0% 0%)'
    132156PASS Property color value 'hwb(from rebeccapurple 0deg 0% 0%)'
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html

    r289194 r289396  
    3434    test_computed_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`);
    3535
    36     // Testing non-sRGB origin colors to see gamut clipping.
    37     test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`);
     36    // Testing non-sRGB origin colors to see gamut mapping.
     37    test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     38    test_computed_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     39    test_computed_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     40    test_computed_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     41    test_computed_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     42    test_computed_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     43    test_computed_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     44    test_computed_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     45    test_computed_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    3846
    3947    // Testing replacement with 0.
     
    132140    test_computed_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`);
    133141
    134     // Testing non-sRGB origin colors to see gamut clipping.
    135     test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`);
     142    // Testing non-sRGB origin colors to see gamut mapping.
     143    test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     144    test_computed_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     145    test_computed_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     146    test_computed_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     147    test_computed_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     148    test_computed_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     149    test_computed_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     150    test_computed_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     151    test_computed_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    136152
    137153    // Testing replacement with 0.
     
    205221    test_computed_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`);
    206222
    207     // Testing non-sRGB origin colors to see gamut clipping.
    208     test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`);
     223    // Testing non-sRGB origin colors to see gamut mapping.
     224    test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     225    test_computed_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     226    test_computed_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     227    test_computed_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     228    test_computed_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     229    test_computed_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     230    test_computed_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     231    test_computed_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     232    test_computed_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    209233
    210234    // Testing replacement with 0.
     
    343367        test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`);
    344368
    345         // Testing non-sRGB origin colors to see gamut clipping.
     369        // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
    346370        test_computed_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`);
    347371        test_computed_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`);
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid-expected.txt

    r288143 r289396  
    66PASS e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value
    77PASS e.style['color'] = "rgb(from color(display-p3 0 1 0) r g b / alpha)" should set the property value
     8PASS e.style['color'] = "rgb(from lab(100% 104.3 -50.9) r g b)" should set the property value
     9PASS e.style['color'] = "rgb(from lab(0% 104.3 -50.9) r g b)" should set the property value
     10PASS e.style['color'] = "rgb(from lch(100% 116 334) r g b)" should set the property value
     11PASS e.style['color'] = "rgb(from lch(0% 116 334) r g b)" should set the property value
     12PASS e.style['color'] = "rgb(from oklab(100% 0.365 -0.16) r g b)" should set the property value
     13PASS e.style['color'] = "rgb(from oklab(0% 0.365 -0.16) r g b)" should set the property value
     14PASS e.style['color'] = "rgb(from oklch(100% 0.399 336.3) r g b)" should set the property value
     15PASS e.style['color'] = "rgb(from oklch(0% 0.399 336.3) r g b)" should set the property value
    816PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value
    917PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value
     
    7583PASS e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value
    7684PASS e.style['color'] = "hsl(from color(display-p3 0 1 0) h s l / alpha)" should set the property value
     85PASS e.style['color'] = "hsl(from lab(100% 104.3 -50.9) h s l)" should set the property value
     86PASS e.style['color'] = "hsl(from lab(0% 104.3 -50.9) h s l)" should set the property value
     87PASS e.style['color'] = "hsl(from lch(100% 116 334) h s l)" should set the property value
     88PASS e.style['color'] = "hsl(from lch(0% 116 334) h s l)" should set the property value
     89PASS e.style['color'] = "hsl(from oklab(100% 0.365 -0.16) h s l)" should set the property value
     90PASS e.style['color'] = "hsl(from oklab(0% 0.365 -0.16) h s l)" should set the property value
     91PASS e.style['color'] = "hsl(from oklch(100% 0.399 336.3) h s l)" should set the property value
     92PASS e.style['color'] = "hsl(from oklch(0% 0.399 336.3) h s l)" should set the property value
    7793PASS e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value
    7894PASS e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value
     
    129145PASS e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value
    130146PASS e.style['color'] = "hwb(from color(display-p3 0 1 0) h w b / alpha)" should set the property value
     147PASS e.style['color'] = "hwb(from lab(100% 104.3 -50.9) h w b)" should set the property value
     148PASS e.style['color'] = "hwb(from lab(0% 104.3 -50.9) h w b)" should set the property value
     149PASS e.style['color'] = "hwb(from lch(100% 116 334) h w b)" should set the property value
     150PASS e.style['color'] = "hwb(from lch(0% 116 334) h w b)" should set the property value
     151PASS e.style['color'] = "hwb(from oklab(100% 0.365 -0.16) h w b)" should set the property value
     152PASS e.style['color'] = "hwb(from oklab(0% 0.365 -0.16) h w b)" should set the property value
     153PASS e.style['color'] = "hwb(from oklch(100% 0.399 336.3) h w b)" should set the property value
     154PASS e.style['color'] = "hwb(from oklch(0% 0.399 336.3) h w b)" should set the property value
    131155PASS e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value
    132156PASS e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html

    r289194 r289396  
    3333    test_valid_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`);
    3434
    35     // Testing non-sRGB origin colors to see gamut clipping.
    36     test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`);
     35    // Testing non-sRGB origin colors to see gamut mapping.
     36    test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     37    test_valid_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     38    test_valid_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     39    test_valid_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     40    test_valid_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     41    test_valid_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     42    test_valid_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     43    test_valid_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     44    test_valid_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    3745
    3846    // Testing replacement with 0.
     
    131139    test_valid_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`);
    132140
    133     // Testing non-sRGB origin colors to see gamut clipping.
    134     test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`);
     141    // Testing non-sRGB origin colors to see gamut mapping.
     142    test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     143    test_valid_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     144    test_valid_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     145    test_valid_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     146    test_valid_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     147    test_valid_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     148    test_valid_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     149    test_valid_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     150    test_valid_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    135151
    136152    // Testing replacement with 0.
     
    204220    test_valid_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`);
    205221
    206     // Testing non-sRGB origin colors to see gamut clipping.
    207     test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`);
     222    // Testing non-sRGB origin colors to see gamut mapping.
     223    test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0).
     224    test_valid_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     225    test_valid_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     226    test_valid_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255).
     227    test_valid_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
     228    test_valid_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255).
     229    test_valid_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24).
     230    test_valid_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255).
     231    test_valid_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24).
    208232
    209233    // Testing replacement with 0.
     
    342366        test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`);
    343367
    344         // Testing non-sRGB origin colors to see gamut clipping.
     368        // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
    345369        test_valid_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`);
    346370        test_valid_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`);
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r289381 r289396  
    18391839webkit.org/b/230277 imported/w3c/web-platform-tests/css/css-transforms/3dtransform-and-filter-no-perspective-001.html [ ImageOnlyFailure ]
    18401840
     1841webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/color-mix-non-srgb-001.html [ Failure ]
    18411842webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-computed.html  [ Failure ]
    18421843webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/relative-color-valid.html [ Failure ]
     1844webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html [ Failure ]
     1845webkit.org/b/234726 imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html [ Failure ]
    18431846
    18441847webkit.org/b/234782 imported/w3c/web-platform-tests/css/css-writing-modes/text-shadow-orientation-upright-001.html [ ImageOnlyFailure ]
  • trunk/Source/WebCore/ChangeLog

    r289383 r289396  
     12022-02-08  Sam Weinig  <weinig@apple.com>
     2
     3        Conversion to a color space with a smaller gamut should perform gamut mapping
     4        https://bugs.webkit.org/show_bug.cgi?id=236200
     5
     6        Reviewed by Darin Adler.
     7
     8        CSS Color now defines that gamut mapping should happen when converting to an RGB color space
     9        with bounded gamut that is smaller than the origin color's color space. Specifically, it
     10        specifies the use of a new "CSS gamut mapping algorithm" https://drafts.csswg.org/css-color/#css-gamut-mapping
     11        which implements a relative colorimetric intent mapping with colors inside the destination
     12        gamut unchanged.
     13
     14        The previous behavior we implemented was to clip out of gamut colors to the gamut (e.g.
     15        color(srgb 1.4 -0.2 .5) would become color(srgb 1 0 .5)) which can lead to very odd results.
     16
     17        To keep things simple, the gamut mapping has been incorporated directly into the main color
     18        conversion pipeline, replacing the call to makeFromComponentsClampingExceptAlpha in toBounded()
     19        with one implements the new algorithm. To accomadate this, the pipeline was modified so that
     20        the matrix conversions now only happen to/from extended-linear and XYZ color types, rather than
     21        the old behavior which allowed shortcuting from bounded-linear, which was ok because the clip
     22        would result in the same value. Since conversion from bounded-linear to extended-linear is free
     23        (just a type change, no conversion), the only additional cost here is the gamut mapping.
     24
     25        The implementation of the CSS gamut mapping algorithm itself is a naive iterative bisection
     26        implementation based on the psuedo-code from the spec. As an optimization in the future, we should
     27        consider implementing an analytic solution, which will be more complicated, but likely faster.
     28
     29        Currently, the only place where the effect of this new gamut mapping behavior will be visible is
     30        via functions that explicitly convert to a bounded color space, specifically the CSS color-mix()
     31        function and relative color syntax. Ultimately, we should also be using this to map CSS colors
     32        to the output color space of the screen / HTML canvas, but finding the right place to do that
     33        is not a part of this initial change.
     34
     35        * platform/graphics/ColorConversion.cpp:
     36        (WebCore::ColorConversion<Lab<float>, XYZA<float, WhitePoint::D50>>::convert):
     37        (WebCore::ColorConversion<OKLab<float>, XYZA<float, WhitePoint::D65>>::convert):
     38        Add call to makeFromComponentsClampingExceptAlpha at the end of conversion to Lab/OKLab
     39        as the conversion functions can produce lightness values just ever so less than 0.
     40        In practice, only the lightness value is bounded, so it is the only thing that actually
     41        gets clamped thanks to the constexpr nature of clampedComponent().
     42
     43        * platform/graphics/ColorConversion.h:
     44        (WebCore::computeDeltaEOK):
     45        Add implementation of the deltaEOK algorithm.
     46
     47        (WebCore::ClipGamutMapping::mapToBoundedGamut):
     48        Add implementation of the degenerate gamut mapping algorithm.
     49
     50        (WebCore::CSSGamutMapping::mapToBoundedGamut):
     51        Add implementation of the CSS gamut mapping algorithm.
     52
     53        (WebCore::ColorConversion::convert):
     54        Add a new step to the main pipeline that explicitly handles bounds conversions to/from
     55        extended-linear so that the matrix conversions can rely on always working in extended space.
     56
     57        (WebCore::ColorConversion::toBounded):
     58        Replace call to clamp with call out to gamut mapping algorithm.
     59
     60        (WebCore::ColorConversion::handleMatrixConversion):
     61        Replace makeFromComponentsClampingExceptAlpha with makeFromComponents now that all conversions
     62        are in the extended space and clamping is no-op.
     63
     64        * platform/graphics/ColorTypes.h:
     65        (WebCore::inGamut):
     66        (WebCore::colorIfInGamut):
     67        (WebCore::clipToGamut):
     68        Add some helpers to check/convert/clip to the bounded gamut of RGB types.
     69
    1702022-02-07  Yusuke Suzuki  <ysuzuki@apple.com>
    271
  • trunk/Source/WebCore/platform/graphics/ColorConversion.cpp

    r287552 r289396  
    4545    float chroma = std::hypot(a, b);
    4646
    47     return { lightness, chroma, hue >= 0 ? hue : hue + 360, alpha };
     47    return { lightness, chroma, hue >= 0.0f ? hue : hue + 360.0f, alpha };
    4848}
    4949
     
    273273    float b = 200.0f * (f1 - f2);
    274274
    275     return { lightness, a, b, alpha };
     275    return makeFromComponentsClampingExceptAlpha<Lab<float>>(lightness, a, b, alpha);
    276276}
    277277
     
    359359
    360360    // 4. Transform lightness from unit lightness to percentage lightness.
    361     return { lightness * 100.0f, a, b, alpha };
     361    return makeFromComponentsClampingExceptAlpha<OKLab<float>>(lightness * 100.0f, a, b, alpha);
    362362}
    363363
  • trunk/Source/WebCore/platform/graphics/ColorConversion.h

    r287552 r289396  
    11/*
    2  * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727
    2828#include "ColorTypes.h"
     29#include <wtf/MathExtras.h>
    2930
    3031namespace WebCore {
     
    140141};
    141142
     143// MARK: DeltaE color difference algorithms.
     144
     145template<typename ColorType1, typename ColorType2> inline constexpr float computeDeltaEOK(ColorType1 color1, ColorType2 color2)
     146{
     147    // https://drafts.csswg.org/css-color/#color-difference-OK
     148
     149    auto [L1, a1, b1, alpha1] = convertColor<OKLab<float>>(color1).resolved();
     150    auto [L2, a2, b2, alpha2] = convertColor<OKLab<float>>(color2).resolved();
     151
     152    auto deltaL = (L1 / 100.0f) - (L2 / 100.0f);
     153    auto deltaA = a1 - a2;
     154    auto deltaB = b1 - b2;
     155
     156    return std::hypot(deltaL, deltaA, deltaB);
     157}
     158
     159// MARK: Gamut mapping algorithms.
     160
     161struct ClipGamutMapping {
     162    template<typename ColorType> static auto mapToBoundedGamut(const ColorType& color) -> typename ColorType::BoundedCounterpart
     163    {
     164        return clipToGamut<typename ColorType::BoundedCounterpart>(color);
     165    }
     166};
     167
     168struct CSSGamutMapping {
     169    // This implements the CSS gamut mapping algorithm (https://drafts.csswg.org/css-color/#css-gamut-mapping) for RGB
     170    // colors that are out of gamut for a particular RGB color space. It implements a relative colorimetric intent mapping
     171    // for colors that are outside the destionation gamut and leaves colors inside the destination gamut unchanged.
     172
     173    // A simple optimization over the psuedocode in the specification has been made to avoid unnecessary work in the
     174    // main bisection loop by checking the gamut using the extended linear color space of the RGB family regardless of
     175    // of whether the final type is gamma encoded or not. This avoids unnecessary gamma encoding for non final loops.
     176
     177    // FIXME: This is a naive iterative solution that works for any bounded RGB color space. This can be optimized by
     178    // using an analytical solution that computes the exact intersection.
     179
     180    static constexpr float JND = 0.02f;
     181
     182    template<typename ColorType> static auto mapToBoundedGamut(const ColorType& color) -> typename ColorType::BoundedCounterpart
     183    {
     184        using BoundedColorType = typename ColorType::BoundedCounterpart;
     185        using ExtendedLinearColorType = ExtendedLinearEncoded<typename BoundedColorType::ComponentType, typename BoundedColorType::Descriptor>;
     186        using BoundedLinearColorType = BoundedLinearEncoded<typename BoundedColorType::ComponentType, typename BoundedColorType::Descriptor>;
     187
     188        auto resolvedColor = color.resolved();
     189
     190        if (auto result = colorIfInGamut<BoundedColorType>(resolvedColor))
     191            return *result;
     192
     193        auto colorInOKLCHColorSpace = convertColor<OKLCHA<float>>(resolvedColor).resolved();
     194
     195        if (WTF::areEssentiallyEqual(colorInOKLCHColorSpace.lightness, 100.0f) || colorInOKLCHColorSpace.lightness > 100.0f)
     196            return { 1.0, 1.0, 1.0, resolvedColor.alpha };
     197        else if (WTF::areEssentiallyEqual(colorInOKLCHColorSpace.lightness, 0.0f))
     198            return { 0.0f, 0.0f, 0.0f, resolvedColor.alpha };
     199
     200        float min = 0.0f;
     201        float max = colorInOKLCHColorSpace.chroma;
     202
     203        while (true) {
     204            auto chroma = (min + max) / 2.0f;
     205
     206            auto current = colorInOKLCHColorSpace;
     207            current.chroma = chroma;
     208
     209            auto currentInExtendedLinearColorSpace = convertColor<ExtendedLinearColorType>(current).resolved();
     210
     211            if (inGamut<BoundedLinearColorType>(currentInExtendedLinearColorSpace)) {
     212                min = chroma;
     213                continue;
     214            }
     215
     216            auto currentClippedToBoundedLinearColorSpace = clipToGamut<BoundedLinearColorType>(currentInExtendedLinearColorSpace);
     217
     218            auto deltaE = computeDeltaEOK(currentClippedToBoundedLinearColorSpace, current);
     219            if (deltaE < JND)
     220                return convertColor<BoundedColorType>(currentClippedToBoundedLinearColorSpace);
     221
     222            max = chroma;
     223        }
     224    }
     225};
    142226
    143227// Main conversion.
     
    153237//       │        │                │                  │                  │                               │                               │                               │                │        │
    154238//       │          ProPhotoRGB───────────────────┐   │   SRGB──────────────────────────┐ DisplayP3─────────────────────┐ A98RGB────────────────────────┐ Rec2020───────────────────────┐          │
    155 //       │        │ │┌────────┐ ┌────────────────┐│   │   │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │        │
    156 //       │          ││ Linear │ │ LinearExtended ││   │   ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││          │
    157 //       │        │ │└────────┘ └────────────────┘│   │   │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │        │
    158 //       │         ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─         │
     239//       │        │ │           ┌────────────────┐│   │   │           ┌────────────────┐│ │           ┌────────────────┐│ │           ┌────────────────┐│ │           ┌────────────────┐│ │        │
     240//       │          │     ┌─────▶︎ LinearExtended ││   │   │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││          │
     241//       │        │ │     │     └────────▲───────┘│   │   │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │        │
     242//       │         ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─         │
     243//       │          │┌────────┐          │        │   │   │┌────────┐          │        │ │┌────────┐          │        │ │┌────────┐          │        │ │┌────────┐          │        │          │
     244//       │          ││ Linear │          │        │   │   ││ Linear │          │        │ ││ Linear │          │        │ ││ Linear │          │        │ ││ Linear │          │        │          │
     245//       │          │└────▲───┘          │        │   │   │└────▲───┘          │        │ │└────▲───┘          │        │ │└────▲───┘          │        │ │└────▲───┘          │        │          │
     246//       │          │     │              │        │   │   │     │              │        │ │     │              │        │ │     │              │        │ │     │              │        │          │
    159247// ┌───────────┐    │┌────────┐ ┌────────────────┐│   │   │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│    ┌───────────┐
    160 // │    Lab    │    ││ Gamma  │ │ GammaExtended  ││   │   ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││    │   OKLab   │
     248// │    Lab    │    ││ Gamma  │─│ GammaExtended  ││   │   ││ Gamma  │─│ GammaExtended  ││ ││ Gamma  │─│ GammaExtended  ││ ││ Gamma  │─│ GammaExtended  ││ ││ Gamma  │─│ GammaExtended  ││    │   OKLab   │
    161249// └─────▲─────┘    │└────────┘ └────────────────┘│   │   │└────▲───┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│    └─────▲─────┘
    162250//       │          └─────────────────────────────┘   │   └─────┼───────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘          │
     
    196284            return convertColor<Output>(convertColor<typename Output::LinearCounterpart>(color));
    197285
    198         // 5. At this point, Input and Output are each either Linear-RGB types (of different familes) or XYZA
     286        // 5. Handle any bounds conversions for the Input and Output.
     287        else if constexpr (IsRGBBoundedType<Input>)
     288            return convertColor<Output>(convertColor<typename Input::ExtendedCounterpart>(color));
     289        else if constexpr (IsRGBBoundedType<Output>)
     290            return convertColor<Output>(convertColor<typename Output::ExtendedCounterpart>(color));
     291
     292        // 6. At this point, Input and Output are each either ExtendedLinear-RGB types (of different familes) or XYZA
    199293        //    and therefore all additional conversion can happen via matrix transformation.
    200294        else
     
    244338    template<typename ColorType> static inline constexpr auto toBounded(const ColorType& color) -> typename ColorType::BoundedCounterpart
    245339    {
    246         return makeFromComponentsClampingExceptAlpha<typename ColorType::BoundedCounterpart>(asColorComponents(color.resolved()));
     340        return CSSGamutMapping::mapToBoundedGamut(color);
    247341    }
    248342
     
    252346
    253347        //  RGB Family────────────────────┐
     348        //  │           ┌────────────────┐│
     349        //  │     ┌─────▶︎ LinearExtended ││
     350        //  │     │     └────────▲───────┘│
     351        //  │     │              │        │
     352        //  │┌────────┐          │        │
     353        //  ││ Linear │          │        │
     354        //  │└────▲───┘          │        │
     355        //  │     │              │        │
    254356        //  │┌────────┐ ┌────────────────┐│
    255         //  ││ Linear │ │ LinearExtended ││
    256         //  │└────────┘ └────────────────┘│
    257         //  │┌────────┐ ┌────────────────┐│
    258         //  ││ Gamma  │ │ GammaExtended  ││
     357        //  ││ Gamma  │─│ GammaExtended  ││
    259358        //  │└────────┘ └────────────────┘│
    260359        //  └─────────────────────────────┘
     
    286385    static inline constexpr Output handleMatrixConversion(const Input& color)
    287386    {
    288         static_assert(IsRGBLinearEncodedType<Input> || IsXYZA<Input>);
    289         static_assert(IsRGBLinearEncodedType<Output> || IsXYZA<Output>);
     387        static_assert((IsRGBLinearEncodedType<Input> && IsRGBExtendedType<Input>) || IsXYZA<Input>);
     388        static_assert((IsRGBLinearEncodedType<Output> && IsRGBExtendedType<Output>) || IsXYZA<Output>);
    290389
    291390        //  ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
     
    299398        //  │                │                  │                  │                               │                               │                               │                │
    300399        //    ProPhotoRGB───────────────────┐   │   SRGB──────────────────────────┐ DisplayP3─────────────────────┐ A98RGB────────────────────────┐ Rec2020───────────────────────┐
    301         //  │ │┌────────┐ ┌────────────────┐│   │   │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │┌────────┐ ┌────────────────┐│ │
    302         //    ││ Linear │ │ LinearExtended ││   │   ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││ ││ Linear │ │ LinearExtended ││
    303         //  │ │└────────┘ └────────────────┘│   │   │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │
    304         //   ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─
    305 
    306         // This handles conversions between linear color types that can be converted using pre-defined
     400        //  │ │           ┌────────────────┐│   │   │           ┌────────────────┐│ │           ┌────────────────┐│ │           ┌────────────────┐│ │          ┌────────────────┐│ │
     401        //    │     ┌─────▶︎ LinearExtended ││   │   │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││ │     ┌─────▶︎ LinearExtended ││
     402        //  │ │     │     └────────▲───────┘│   │   │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │     │     └────────▲───────┘│ │
     403        //   ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─ ─│─ ─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─│─ ─ ─│─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─│─
     404
     405        // This handles conversions between extended linear color types that can be converted using pre-defined
    307406        // 3x3 matrices.
    308407       
     
    313412
    314413        auto applyMatrices = [](const Input& color, auto... matrices) {
    315             return makeFromComponentsClampingExceptAlpha<Output>(applyMatricesToColorComponents(asColorComponents(color.resolved()), matrices...));
     414            return makeFromComponents<Output>(applyMatricesToColorComponents(asColorComponents(color.resolved()), matrices...));
    316415        };
    317416
  • trunk/Source/WebCore/platform/graphics/ColorTypes.h

    r289122 r289396  
    3030#include "ColorModels.h"
    3131#include "ColorTransferFunctions.h"
     32#include <optional>
    3233
    3334namespace WebCore {
     
    312313template<typename ColorType1, typename ColorType2> inline constexpr bool IsSameRGBTypeFamily = IsSameRGBTypeFamilyValue<ColorType1, ColorType2, IsRGBType<ColorType1> && IsRGBType<ColorType2>>;
    313314
     315template<typename BoundedColorType> constexpr bool inGamut(typename BoundedColorType::ComponentType component)
     316{
     317    static_assert(IsRGBBoundedType<BoundedColorType>);
     318
     319    return component >= 0.0f && component <= 1.0f;
     320}
     321
     322template<typename BoundedColorType> constexpr bool inGamut(ColorComponents<typename BoundedColorType::ComponentType, 4> components)
     323{
     324    static_assert(IsRGBBoundedType<BoundedColorType>);
     325
     326    return inGamut<BoundedColorType>(components[0]) && inGamut<BoundedColorType>(components[1]) && inGamut<BoundedColorType>(components[2]);
     327}
     328
     329template<typename BoundedColorType, typename ColorType> constexpr bool inGamut(ColorType color)
     330{
     331    static_assert(IsRGBBoundedType<BoundedColorType>);
     332    static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
     333
     334    return inGamut<BoundedColorType>(asColorComponents(color.resolved()));
     335}
     336
     337template<typename BoundedColorType, typename ColorType> constexpr std::optional<BoundedColorType> colorIfInGamut(ColorType color)
     338{
     339    static_assert(IsRGBBoundedType<BoundedColorType>);
     340    static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
     341
     342    auto components = asColorComponents(color.resolved());
     343    if (!inGamut<BoundedColorType>(components))
     344        return std::nullopt;
     345    return makeFromComponents<BoundedColorType>(components);
     346}
     347
     348template<typename BoundedColorType, typename ColorType> constexpr BoundedColorType clipToGamut(ColorType color)
     349{
     350    static_assert(IsRGBBoundedType<BoundedColorType>);
     351    static_assert(std::is_same_v<BoundedColorType, typename ColorType::BoundedCounterpart>);
     352
     353    return makeFromComponentsClampingExceptAlpha<BoundedColorType>(asColorComponents(color.resolved()));
     354}
     355
    314356struct SRGBADescriptor {
    315357    template<typename T, TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
  • trunk/Tools/ChangeLog

    r289386 r289396  
     12022-02-08  Sam Weinig  <weinig@apple.com>
     2
     3        Conversion to a color space with a smaller gamut should perform gamut mapping
     4        https://bugs.webkit.org/show_bug.cgi?id=236200
     5
     6        Reviewed by Darin Adler.
     7
     8        * TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
     9        (TestWebKitAPI::TEST):
     10        Update color conversion tests to account for gamut mapping and add a new test
     11        that bypasses gamut mapping by converting to extended sRGB.
     12
    1132022-02-01  Jonathan Bedard  <jbedard@apple.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp

    r287552 r289396  
    373373    auto sRGBAColor = p3Color.toColorTypeLossy<SRGBA<float>>().resolved();
    374374    EXPECT_FLOAT_EQ(sRGBAColor.red, 1.0f);
     375    EXPECT_FLOAT_EQ(sRGBAColor.green, 0.50120097f);
     376    EXPECT_FLOAT_EQ(sRGBAColor.blue, 0.26161569f);
     377    EXPECT_FLOAT_EQ(sRGBAColor.alpha, 0.75f);
     378}
     379
     380TEST(Color, P3ConversionToExtendedSRGB)
     381{
     382    Color p3Color { DisplayP3<float> { 1.0, 0.5, 0.25, 0.75 } };
     383    auto sRGBAColor = p3Color.toColorTypeLossy<ExtendedSRGBA<float>>().resolved();
     384    EXPECT_FLOAT_EQ(sRGBAColor.red, 1.0740442f);
    375385    EXPECT_FLOAT_EQ(sRGBAColor.green, 0.46253282f);
    376386    EXPECT_FLOAT_EQ(sRGBAColor.blue, 0.14912748f);
Note: See TracChangeset for help on using the changeset viewer.