Changeset 288427 in webkit


Ignore:
Timestamp:
Jan 23, 2022 4:57:12 PM (6 months ago)
Author:
weinig@apple.com
Message:

Support interpolating colors with missing/none components via color-mix()
https://bugs.webkit.org/show_bug.cgi?id=235496

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Update color-mix() tests to include test cases that use 'none' components.

  • 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:

Source/WebCore:

Adds support for interpolating colors that have a missing/none component. Currently,
the only way for a color to have a missing/none component is for it to be specified
explicitly by the user (e.g. hsl(none 20% 40%)), but the interpolation implementation
is agnostic to how the color was created so will work once there is automatic creation
of missing/none components on conversion for powerless components.

This change only enables the new interpolation behavior for color-mix(), by replacing
a call of colorType.resolved() with colorType.unresolved(), support for other interpolation
use cases will follow.

  • css/parser/CSSPropertyParserHelpers.cpp:

(WebCore::CSSPropertyParserHelpers::mixColorComponentsUsingColorInterpolationMethod):
Replace resolved() with unrersolved() to allow NaN values through to interpolation.

  • platform/graphics/ColorInterpolation.cpp:

(WebCore::fixupHueComponentsPriorToInterpolation):
(WebCore::interpolateColors):
Move non-templated version of interpolateColors to the implementation file as it generates
a lot of code and there is little reason to believe it would be useful to inline it.

  • platform/graphics/ColorInterpolation.h:

(WebCore::interpolateComponent):
(WebCore::interpolateComponentAccountingForNaN):
(WebCore::interpolateHue):
(WebCore::interpolateAlphaPremulitplied):
(WebCore::interpolateComponentUsingPremultipliedAlpha):
(WebCore::interpolateAlphaUnpremulitplied):
(WebCore::interpolateComponentUsingUnpremultipliedAlpha):
(WebCore::interpolateColorComponents):
(WebCore::preInterpolationNormalizationForComponent): Deleted.
(WebCore::preInterpolationNormalization): Deleted.
(WebCore::postInterpolationNormalizationForComponent): Deleted.
(WebCore::postInterpolationNormalization): Deleted.
(WebCore::interpolateColors): Deleted.
Replace existing interpolation implementation which separated each component into pre/interpolate/post
steps, with one that does all three steps at once and now also supports missing components. Removing
the steps made the overall algorithm is easier to understand a couples premulitplication and unpremultiplication
much closer together.

  • platform/graphics/ColorTypes.h:

(WebCore::constexprIsNaN):
Update comment to include missing word.

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r288420 r288427  
     12022-01-23  Sam Weinig  <weinig@apple.com>
     2
     3        Support interpolating colors with missing/none components via color-mix()
     4        https://bugs.webkit.org/show_bug.cgi?id=235496
     5
     6        Reviewed by Darin Adler.
     7
     8        Update color-mix() tests to include test cases that use 'none' components.
     9
     10        * web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt:
     11        * web-platform-tests/css/css-color/parsing/color-mix-computed.html:
     12        * web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt:
     13        * web-platform-tests/css/css-color/parsing/color-mix-valid.html:
     14
    1152022-01-23  Ziran Sun  <zsun@igalia.com>
    216
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed-expected.txt

    r287838 r288427  
    5454PASS Property color value 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))'
    5555PASS Property color value 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))'
     56PASS Property color value 'color-mix(in hsl, hsl(none none none), hsl(none none none))'
     57PASS Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))'
     58PASS Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))'
     59PASS Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))'
     60PASS Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))'
     61PASS Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))'
     62PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))'
     63PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))'
     64PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))'
    5665PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))'
    5766PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))'
     
    108117PASS Property color value 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))'
    109118PASS Property color value 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))'
     119PASS Property color value 'color-mix(in hwb, hwb(none none none), hwb(none none none))'
     120PASS Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))'
     121PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))'
     122PASS Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))'
     123PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))'
     124PASS Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))'
     125PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))'
     126PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))'
     127PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))'
    110128PASS Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))'
    111129PASS Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))'
     
    162180PASS Property color value 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))'
    163181PASS Property color value 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))'
     182PASS Property color value 'color-mix(in lch, lch(none none none), lch(none none none))'
     183PASS Property color value 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))'
     184PASS Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))'
     185PASS Property color value 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))'
     186PASS Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))'
     187PASS Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))'
     188PASS Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))'
     189PASS Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))'
     190PASS Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))'
    164191PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))'
    165192PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))'
     
    216243PASS Property color value 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))'
    217244PASS Property color value 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))'
     245PASS Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))'
     246PASS Property color value 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))'
     247PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))'
     248PASS Property color value 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))'
     249PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))'
     250PASS Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))'
     251PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))'
     252PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))'
     253PASS Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))'
    218254PASS Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))'
    219255PASS Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))'
     
    234270PASS Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)'
    235271PASS Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))'
     272PASS Property color value 'color-mix(in lab, lab(none none none), lab(none none none))'
     273PASS Property color value 'color-mix(in lab, lab(none none none), lab(50% 60 70))'
     274PASS Property color value 'color-mix(in lab, lab(10% 20 30), lab(none none none))'
     275PASS Property color value 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))'
     276PASS Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))'
     277PASS Property color value 'color-mix(in lab, lab(none 20 30), lab(50% none 70))'
     278PASS Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))'
     279PASS Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))'
     280PASS Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))'
    236281PASS Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))'
    237282PASS Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))'
     
    252297PASS Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)'
    253298PASS Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))'
     299PASS Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))'
     300PASS Property color value 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))'
     301PASS Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))'
     302PASS Property color value 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))'
     303PASS Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))'
     304PASS Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))'
     305PASS Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))'
     306PASS Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))'
     307PASS Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))'
    254308PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))'
    255309PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))'
     
    273327PASS Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))'
    274328PASS Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))'
     329PASS Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))'
     330PASS Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))'
     331PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))'
     332PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))'
     333PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))'
     334PASS Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))'
     335PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))'
     336PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))'
     337PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))'
    275338PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))'
    276339PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))'
     
    294357PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))'
    295358PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))'
     359PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))'
     360PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))'
     361PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))'
     362PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))'
     363PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))'
     364PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))'
     365PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))'
     366PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))'
     367PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))'
    296368PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))'
    297369PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))'
     
    315387PASS Property color value 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))'
    316388PASS Property color value 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))'
     389PASS Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))'
     390PASS Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))'
     391PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))'
     392PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))'
     393PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))'
     394PASS Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))'
     395PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))'
     396PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))'
     397PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))'
    317398PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))'
    318399PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))'
     
    336417PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))'
    337418PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))'
     419PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))'
     420PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))'
     421PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))'
     422PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))'
     423PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))'
     424PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))'
     425PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))'
     426PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))'
     427PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))'
    338428PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))'
    339429PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))'
     
    357447PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))'
    358448PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))'
     449PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))'
     450PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))'
     451PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))'
     452PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))'
     453PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))'
     454PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))'
     455PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))'
     456PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))'
     457PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))'
    359458
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-computed.html

    r287838 r288427  
    8787    test_computed_value(`color`, `color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`));
    8888
     89    test_computed_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(none none none))`, canonicalize(`hsl(none none none)`));
     90    test_computed_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))`, canonicalize(`hsl(30deg 40% 80%)`));
     91    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))`, canonicalize(`hsl(120deg 20% 40%)`));
     92    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))`, canonicalize(`hsl(75deg 30% 60%)`));
     93    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))`, canonicalize(`hsl(75deg 20% 40%)`));
     94    test_computed_value(`color`, `color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))`, canonicalize(`hsl(30deg 20% 60%)`));
     95
     96    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))`, canonicalize(`hsl(60deg 40% 40%)`));
     97    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`));
     98    test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
     99
     100
    89101    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
    90102    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
     
    148160    test_computed_value(`color`, `color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`));
    149161    test_computed_value(`color`, `color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`));
     162
     163    test_computed_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(none none none))`, canonicalize(`hwb(none none none)`));
     164    test_computed_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))`, canonicalize(`hwb(30deg 30% 40%)`));
     165    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))`, canonicalize(`hwb(120deg 10% 20%)`));
     166    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 40%)`));
     167    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))`, canonicalize(`hwb(75deg 20% 20%)`));
     168    test_computed_value(`color`, `color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))`, canonicalize(`hwb(30deg 10% 30%)`));
     169    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 30%)`));
     170    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)`));
     171    test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
    150172
    151173    for (const colorSpace of [ "lch", "oklch" ]) {
     
    211233        test_computed_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 20deg), ${colorSpace}(100% 0 320deg))`, `${colorSpace}(100% 0 170)`);
    212234        test_computed_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 320deg), ${colorSpace}(100% 0 20deg))`, `${colorSpace}(100% 0 170)`);
     235
     236        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`);
     237        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(50% 60 70)`);
     238        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`);
     239        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 70)`);
     240        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`);
     241        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30deg), ${colorSpace}(50% none 70deg))`, `${colorSpace}(50% 20 50)`);
     242        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`);
     243        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`);
     244        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / none))`, `${colorSpace}(30% 40 50 / none)`);
    213245    }
    214246
     
    233265        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 12.5%, ${colorSpace}(50% 60 70 / .8) 37.5%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication.
    234266        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 0%, ${colorSpace}(50% 60 70 / .8))`, `${colorSpace}(50% 60 70 / 0.8)`);
     267
     268        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`);
     269        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70))`, `${colorSpace}(50% 60 70)`);
     270        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`);
     271        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 70)`);
     272        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`);
     273        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30), ${colorSpace}(50% none 70))`, `${colorSpace}(50% 20 50)`);
     274        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 50)`);
     275        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`);
     276        test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / none))`, `${colorSpace}(30% 40 50 / none)`);
    235277    }
    236278
     
    261303        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4), color(${colorSpace} -4 -6 -8))`, `color(${resultColorSpace} -3 -4.5 -6)`);
    262304        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4 / -5), color(${colorSpace} -4 -6 -8 / -10))`, `color(${resultColorSpace} 0 0 0 / 0)`);
     305
     306        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} none none none))`, `color(${resultColorSpace} none none none)`);
     307        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.5 0.6 0.7)`);
     308        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} none none none))`, `color(${resultColorSpace} 0.1 0.2 0.3)`);
     309        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.7)`);
     310        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} .5 .6 none))`, `color(${resultColorSpace} 0.3 0.4 0.3)`);
     311        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none .2 .3), color(${colorSpace} .5 none .7))`, `color(${resultColorSpace} 0.5 0.2 0.5)`);
     312        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.5)`);
     313        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / 0.5))`, `color(${resultColorSpace} 0.3 0.4 0.5 / 0.5)`);
     314        test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / none))`, `color(${resultColorSpace} 0.3 0.4 0.5 / none)`);
    263315    }
    264316</script>
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid-expected.txt

    r287838 r288427  
    5454PASS e.style['color'] = "color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value
    5555PASS e.style['color'] = "color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value
     56PASS e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(none none none))" should set the property value
     57PASS e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))" should set the property value
     58PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))" should set the property value
     59PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))" should set the property value
     60PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))" should set the property value
     61PASS e.style['color'] = "color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))" should set the property value
     62PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value
     63PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value
     64PASS e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value
    5665PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value
    5766PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value
     
    108117PASS e.style['color'] = "color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value
    109118PASS e.style['color'] = "color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value
     119PASS e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(none none none))" should set the property value
     120PASS e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))" should set the property value
     121PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))" should set the property value
     122PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))" should set the property value
     123PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))" should set the property value
     124PASS e.style['color'] = "color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))" should set the property value
     125PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value
     126PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value
     127PASS e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value
    110128PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value
    111129PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value
     
    162180PASS e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value
    163181PASS e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value
     182PASS e.style['color'] = "color-mix(in lch, lch(none none none), lch(none none none))" should set the property value
     183PASS e.style['color'] = "color-mix(in lch, lch(none none none), lch(50% 60 70deg))" should set the property value
     184PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(none none none))" should set the property value
     185PASS e.style['color'] = "color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))" should set the property value
     186PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))" should set the property value
     187PASS e.style['color'] = "color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))" should set the property value
     188PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))" should set the property value
     189PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))" should set the property value
     190PASS e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))" should set the property value
    164191PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value
    165192PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))" should set the property value
     
    216243PASS e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value
    217244PASS e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value
     245PASS e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(none none none))" should set the property value
     246PASS e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))" should set the property value
     247PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))" should set the property value
     248PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))" should set the property value
     249PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))" should set the property value
     250PASS e.style['color'] = "color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))" should set the property value
     251PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))" should set the property value
     252PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))" should set the property value
     253PASS e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))" should set the property value
    218254PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70))" should set the property value
    219255PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))" should set the property value
     
    234270PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)" should set the property value
    235271PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))" should set the property value
     272PASS e.style['color'] = "color-mix(in lab, lab(none none none), lab(none none none))" should set the property value
     273PASS e.style['color'] = "color-mix(in lab, lab(none none none), lab(50% 60 70))" should set the property value
     274PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(none none none))" should set the property value
     275PASS e.style['color'] = "color-mix(in lab, lab(10% 20 none), lab(50% 60 70))" should set the property value
     276PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 none))" should set the property value
     277PASS e.style['color'] = "color-mix(in lab, lab(none 20 30), lab(50% none 70))" should set the property value
     278PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))" should set the property value
     279PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))" should set the property value
     280PASS e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))" should set the property value
    236281PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))" should set the property value
    237282PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))" should set the property value
     
    252297PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)" should set the property value
    253298PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))" should set the property value
     299PASS e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(none none none))" should set the property value
     300PASS e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(50% 60 70))" should set the property value
     301PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(none none none))" should set the property value
     302PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))" should set the property value
     303PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))" should set the property value
     304PASS e.style['color'] = "color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))" should set the property value
     305PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))" should set the property value
     306PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))" should set the property value
     307PASS e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))" should set the property value
    254308PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value
    255309PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))" should set the property value
     
    273327PASS e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))" should set the property value
    274328PASS e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))" should set the property value
     329PASS e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb none none none))" should set the property value
     330PASS e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))" should set the property value
     331PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))" should set the property value
     332PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))" should set the property value
     333PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))" should set the property value
     334PASS e.style['color'] = "color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))" should set the property value
     335PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))" should set the property value
     336PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))" should set the property value
     337PASS e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))" should set the property value
    275338PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value
    276339PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))" should set the property value
     
    294357PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))" should set the property value
    295358PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))" should set the property value
     359PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))" should set the property value
     360PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))" should set the property value
     361PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))" should set the property value
     362PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))" should set the property value
     363PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))" should set the property value
     364PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))" should set the property value
     365PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))" should set the property value
     366PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))" should set the property value
     367PASS e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))" should set the property value
    296368PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value
    297369PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))" should set the property value
     
    315387PASS e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))" should set the property value
    316388PASS e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))" should set the property value
     389PASS e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz none none none))" should set the property value
     390PASS e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))" should set the property value
     391PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))" should set the property value
     392PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))" should set the property value
     393PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))" should set the property value
     394PASS e.style['color'] = "color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))" should set the property value
     395PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))" should set the property value
     396PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))" should set the property value
     397PASS e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))" should set the property value
    317398PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value
    318399PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))" should set the property value
     
    336417PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))" should set the property value
    337418PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))" should set the property value
     419PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))" should set the property value
     420PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))" should set the property value
     421PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))" should set the property value
     422PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))" should set the property value
     423PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))" should set the property value
     424PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))" should set the property value
     425PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))" should set the property value
     426PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))" should set the property value
     427PASS e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))" should set the property value
    338428PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value
    339429PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))" should set the property value
     
    357447PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))" should set the property value
    358448PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))" should set the property value
     449PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))" should set the property value
     450PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))" should set the property value
     451PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))" should set the property value
     452PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))" should set the property value
     453PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))" should set the property value
     454PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))" should set the property value
     455PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))" should set the property value
     456PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))" should set the property value
     457PASS e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))" should set the property value
    359458
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-color/parsing/color-mix-valid.html

    r287838 r288427  
    8787    test_valid_value(`color`, `color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`));
    8888
     89    test_valid_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(none none none))`, canonicalize(`hsl(none none none)`));
     90    test_valid_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))`, canonicalize(`hsl(30deg 40% 80%)`));
     91    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))`, canonicalize(`hsl(120deg 20% 40%)`));
     92    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))`, canonicalize(`hsl(75deg 30% 60%)`));
     93    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))`, canonicalize(`hsl(75deg 20% 40%)`));
     94    test_valid_value(`color`, `color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))`, canonicalize(`hsl(30deg 20% 60%)`));
     95
     96    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))`, canonicalize(`hsl(60deg 40% 40%)`));
     97    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`));
     98    test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`));
     99
     100
    89101    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`);
    90102    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`);
     
    148160    test_valid_value(`color`, `color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`));
    149161    test_valid_value(`color`, `color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`));
     162
     163    test_valid_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(none none none))`, canonicalize(`hwb(none none none)`));
     164    test_valid_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))`, canonicalize(`hwb(30deg 30% 40%)`));
     165    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))`, canonicalize(`hwb(120deg 10% 20%)`));
     166    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 40%)`));
     167    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))`, canonicalize(`hwb(75deg 20% 20%)`));
     168    test_valid_value(`color`, `color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))`, canonicalize(`hwb(30deg 10% 30%)`));
     169    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 30%)`));
     170    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)`));
     171    test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`));
    150172
    151173    for (const colorSpace of [ "lch", "oklch" ]) {
     
    211233        test_valid_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 20deg), ${colorSpace}(100% 0 320deg))`, `${colorSpace}(100% 0 170)`);
    212234        test_valid_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 320deg), ${colorSpace}(100% 0 20deg))`, `${colorSpace}(100% 0 170)`);
     235
     236        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`);
     237        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(50% 60 70)`);
     238        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`);
     239        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 70)`);
     240        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`);
     241        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30deg), ${colorSpace}(50% none 70deg))`, `${colorSpace}(50% 20 50)`);
     242        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`);
     243        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`);
     244        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / none))`, `${colorSpace}(30% 40 50 / none)`);
    213245    }
    214246
     
    233265        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 12.5%, ${colorSpace}(50% 60 70 / .8) 37.5%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication.
    234266        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 0%, ${colorSpace}(50% 60 70 / .8))`, `${colorSpace}(50% 60 70 / 0.8)`);
     267
     268        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`);
     269        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70))`, `${colorSpace}(50% 60 70)`);
     270        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`);
     271        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 70)`);
     272        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`);
     273        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30), ${colorSpace}(50% none 70))`, `${colorSpace}(50% 20 50)`);
     274        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 50)`);
     275        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`);
     276        test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / none))`, `${colorSpace}(30% 40 50 / none)`);
    235277    }
    236278
     
    261303        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4), color(${colorSpace} -4 -6 -8))`, `color(${resultColorSpace} -3 -4.5 -6)`);
    262304        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4 / -5), color(${colorSpace} -4 -6 -8 / -10))`, `color(${resultColorSpace} 0 0 0 / 0)`);
     305
     306        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} none none none))`, `color(${resultColorSpace} none none none)`);
     307        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.5 0.6 0.7)`);
     308        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} none none none))`, `color(${resultColorSpace} 0.1 0.2 0.3)`);
     309        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.7)`);
     310        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} .5 .6 none))`, `color(${resultColorSpace} 0.3 0.4 0.3)`);
     311        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none .2 .3), color(${colorSpace} .5 none .7))`, `color(${resultColorSpace} 0.5 0.2 0.5)`);
     312        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.5)`);
     313        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / 0.5))`, `color(${resultColorSpace} 0.3 0.4 0.5 / 0.5)`);
     314        test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / none))`, `color(${resultColorSpace} 0.3 0.4 0.5 / none)`);
    263315    }
    264316</script>
  • trunk/Source/WebCore/ChangeLog

    r288426 r288427  
     12022-01-23  Sam Weinig  <weinig@apple.com>
     2
     3        Support interpolating colors with missing/none components via color-mix()
     4        https://bugs.webkit.org/show_bug.cgi?id=235496
     5
     6        Reviewed by Darin Adler.
     7
     8        Adds support for interpolating colors that have a missing/none component. Currently,
     9        the only way for a color to have a missing/none component is for it to be specified
     10        explicitly by the user (e.g. hsl(none 20% 40%)), but the interpolation implementation
     11        is agnostic to how the color was created so will work once there is automatic creation
     12        of missing/none components on conversion for powerless components.
     13
     14        This change only enables the new interpolation behavior for color-mix(), by replacing
     15        a call of colorType.resolved() with colorType.unresolved(), support for other interpolation
     16        use cases will follow.
     17
     18        * css/parser/CSSPropertyParserHelpers.cpp:
     19        (WebCore::CSSPropertyParserHelpers::mixColorComponentsUsingColorInterpolationMethod):
     20        Replace resolved() with unrersolved() to allow NaN values through to interpolation.
     21
     22        * platform/graphics/ColorInterpolation.cpp:
     23        (WebCore::fixupHueComponentsPriorToInterpolation):
     24        (WebCore::interpolateColors):
     25        Move non-templated version of interpolateColors to the implementation file as it generates
     26        a lot of code and there is little reason to believe it would be useful to inline it.
     27
     28        * platform/graphics/ColorInterpolation.h:
     29        (WebCore::interpolateComponent):
     30        (WebCore::interpolateComponentAccountingForNaN):
     31        (WebCore::interpolateHue):
     32        (WebCore::interpolateAlphaPremulitplied):
     33        (WebCore::interpolateComponentUsingPremultipliedAlpha):
     34        (WebCore::interpolateAlphaUnpremulitplied):
     35        (WebCore::interpolateComponentUsingUnpremultipliedAlpha):
     36        (WebCore::interpolateColorComponents):
     37        (WebCore::preInterpolationNormalizationForComponent): Deleted.
     38        (WebCore::preInterpolationNormalization): Deleted.
     39        (WebCore::postInterpolationNormalizationForComponent): Deleted.
     40        (WebCore::postInterpolationNormalization): Deleted.
     41        (WebCore::interpolateColors): Deleted.
     42        Replace existing interpolation implementation which separated each component into pre/interpolate/post
     43        steps, with one that does all three steps at once and now also supports missing components. Removing
     44        the steps made the overall algorithm is easier to understand a couples premulitplication and unpremultiplication
     45        much closer together.
     46
     47        * platform/graphics/ColorTypes.h:
     48        (WebCore::constexprIsNaN):
     49        Update comment to include missing word.
     50
    1512022-01-23  Darin Adler  <darin@apple.com>
    252
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r288143 r288427  
    28382838
    28392839    // 2. Colors are then interpolated in the specified color space, as described in CSS Color 4 § 13 Interpolation. [...]
    2840     auto mixedColor = interpolateColorComponents<AlphaPremultiplication::Premultiplied>(interpolationMethod, convertedColor1, mixPercentages.p1 / 100.0, convertedColor2, mixPercentages.p2 / 100.0).resolved();
     2840    auto mixedColor = interpolateColorComponents<AlphaPremultiplication::Premultiplied>(interpolationMethod, convertedColor1, mixPercentages.p1 / 100.0, convertedColor2, mixPercentages.p2 / 100.0).unresolved();
    28412841
    28422842    // 3. If an alpha multiplier was produced during percentage normalization, the alpha component of the interpolated result
    28432843    //    is multiplied by the alpha multiplier.
    2844     if (mixPercentages.alphaMultiplier)
     2844    if (mixPercentages.alphaMultiplier && !std::isnan(mixedColor.alpha))
    28452845        mixedColor.alpha *= (*mixPercentages.alphaMultiplier / 100.0);
    28462846
  • trunk/Source/WebCore/platform/graphics/ColorInterpolation.cpp

    r288200 r288427  
    11/*
    2  * Copyright (C) 2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#include "config.h"
    2727#include "ColorInterpolation.h"
     28
     29#include "Color.h"
    2830
    2931namespace WebCore {
     
    8587}
    8688
     89Color interpolateColors(ColorInterpolationMethod colorInterpolationMethod, Color color1, double color1Multiplier, Color color2, double color2Multiplier)
     90{
     91    return WTF::switchOn(colorInterpolationMethod.colorSpace,
     92        [&] (auto& colorSpace) {
     93            using ColorType = typename std::remove_reference_t<decltype(colorSpace)>::ColorType;
     94            switch (colorInterpolationMethod.alphaPremultiplication) {
     95            case AlphaPremultiplication::Premultiplied:
     96                return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Premultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
     97            case AlphaPremultiplication::Unpremultiplied:
     98                return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Unpremultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
     99            }
     100            RELEASE_ASSERT_NOT_REACHED();
     101        }
     102    );
    87103}
     104
     105}
  • trunk/Source/WebCore/platform/graphics/ColorInterpolation.h

    r288200 r288427  
    11/*
    2  * Copyright (C) 2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727
    2828#include "AlphaPremultiplication.h"
    29 #include "Color.h"
    3029#include "ColorInterpolationMethod.h"
    3130#include "ColorNormalization.h"
     
    3433namespace WebCore {
    3534
    36 // MARK: - Pre-interpolation normalization/fixup
     35class Color;
    3736
    38 std::pair<float, float> fixupHueComponentsPriorToInterpolation(HueInterpolationMethod, float, float);
     37template<AlphaPremultiplication, typename InterpolationMethodColorSpace>
     38typename InterpolationMethodColorSpace::ColorType interpolateColorComponents(InterpolationMethodColorSpace, typename InterpolationMethodColorSpace::ColorType color1, double color1Multiplier, typename InterpolationMethodColorSpace::ColorType color2, double color2Multiplier);
    3939
    40 template<size_t I, AlphaPremultiplication alphaPremultiplication, typename InterpolationMethodColorSpace>
    41 std::pair<float, float> preInterpolationNormalizationForComponent(InterpolationMethodColorSpace interpolationMethodColorSpace, ColorComponents<float, 4> colorComponents1, ColorComponents<float, 4> colorComponents2)
     40Color interpolateColors(ColorInterpolationMethod, Color color1, double color1Multiplier, Color color2, double color2Multiplier);
     41
     42
     43// MARK: - Pre-interpolation normalization/fixup.
     44
     45std::pair<float, float> fixupHueComponentsPriorToInterpolation(HueInterpolationMethod, float component1, float component2);
     46
     47// MARK: - Premultiplication-agnostic interpolation helpers.
     48
     49inline float interpolateComponetWithoutAccountingForNaN(float componentFromColor1, double color1Multiplier, float componentFromColor2, double color2Multiplier)
     50{
     51    return (componentFromColor1 * color1Multiplier) + (componentFromColor2 * color2Multiplier);
     52}
     53
     54inline float interpolateComponentAccountingForNaN(float componentFromColor1, double color1Multiplier, float componentFromColor2, double color2Multiplier)
     55{
     56    if (std::isnan(componentFromColor1))
     57        return componentFromColor2;
     58    if (std::isnan(componentFromColor2))
     59        return componentFromColor1;
     60
     61    return interpolateComponetWithoutAccountingForNaN(componentFromColor1, color1Multiplier, componentFromColor2, color2Multiplier);
     62}
     63
     64template<typename InterpolationMethodColorSpace>
     65float interpolateHue(InterpolationMethodColorSpace interpolationMethodColorSpace, float componentFromColor1, double color1Multiplier, float componentFromColor2, double color2Multiplier)
     66{
     67    if (std::isnan(componentFromColor1))
     68        return componentFromColor2;
     69    if (std::isnan(componentFromColor2))
     70        return componentFromColor1;
     71
     72    auto [fixedupComponent1, fixedupComponent2] = fixupHueComponentsPriorToInterpolation(interpolationMethodColorSpace.hueInterpolationMethod, componentFromColor1, componentFromColor2);
     73    return interpolateComponetWithoutAccountingForNaN(fixedupComponent1, color1Multiplier, fixedupComponent2, color2Multiplier);
     74}
     75
     76// MARK: - Premultiplied interpolation.
     77
     78struct PremultipliedAlphaState {
     79    float alphaForPremultiplicationOfColor1;
     80    float alphaForPremultiplicationOfColor2;
     81    float alphaForUnpremultiplication;
     82    float resultAlpha;
     83};
     84inline PremultipliedAlphaState interpolateAlphaPremulitplied(float alphaForColor1, double color1Multiplier, float alphaForColor2, double color2Multiplier)
     85{
     86    // If both alpha channels are none/missing, no premultiplication is performed and the resulting color will have a none/missing alpha channel.
     87    // If only one alpha channels is none/missing, the other alpha channel is used premultiplication of both colors and is the resulting color's alpha channel.
     88    // If neither alpha channel is none/missing, each alpha channel is used for the premultiplication of its associated color and the interpolated result of the two alpha channels is the resulting color's alpha channel.
     89
     90    if (std::isnan(alphaForColor1)) {
     91        if (std::isnan(alphaForColor2))
     92            return { 1.0f, 1.0f, 1.0f, std::numeric_limits<float>::quiet_NaN() };
     93        return { alphaForColor2, alphaForColor2, alphaForColor2, alphaForColor2 };
     94    }
     95    if (std::isnan(alphaForColor2))
     96        return { alphaForColor1, alphaForColor1, alphaForColor1, alphaForColor1 };
     97
     98    auto interpolatedAlpha = interpolateComponetWithoutAccountingForNaN(alphaForColor1, color1Multiplier, alphaForColor2, color2Multiplier);
     99    return { alphaForColor1, alphaForColor2, interpolatedAlpha, interpolatedAlpha };
     100}
     101
     102template<size_t I, typename InterpolationMethodColorSpace>
     103float interpolateComponentUsingPremultipliedAlpha(InterpolationMethodColorSpace interpolationMethodColorSpace, ColorComponents<float, 4> colorComponents1, double color1Multiplier, ColorComponents<float, 4> colorComponents2, double color2Multiplier, PremultipliedAlphaState interpolatedAlpha)
    42104{
    43105    using ColorType = typename InterpolationMethodColorSpace::ColorType;
     
    45107
    46108    if constexpr (componentInfo[I].type == ColorComponentType::Angle)
    47         return fixupHueComponentsPriorToInterpolation(interpolationMethodColorSpace.hueInterpolationMethod, colorComponents1[I], colorComponents2[I]);
     109        return interpolateHue(interpolationMethodColorSpace, colorComponents1[I], color1Multiplier, colorComponents2[I], color2Multiplier);
    48110    else {
    49         if constexpr (alphaPremultiplication == AlphaPremultiplication::Premultiplied)
    50             return { colorComponents1[I] * colorComponents1[3], colorComponents2[I] * colorComponents2[3] };
    51         else
    52             return { colorComponents1[I], colorComponents2[I] };
     111        if (std::isnan(colorComponents1[I]))
     112            return colorComponents2[I];
     113        if (std::isnan(colorComponents2[I]))
     114            return colorComponents1[I];
     115
     116        auto premultipliedComponent1 = colorComponents1[I] * interpolatedAlpha.alphaForPremultiplicationOfColor1;
     117        auto premultipliedComponent2 = colorComponents2[I] * interpolatedAlpha.alphaForPremultiplicationOfColor2;
     118
     119        auto premultipliedResult = interpolateComponetWithoutAccountingForNaN(premultipliedComponent1, color1Multiplier, premultipliedComponent2, color2Multiplier);
     120
     121        if (interpolatedAlpha.alphaForUnpremultiplication == 0.0f)
     122            return premultipliedResult;
     123        return premultipliedResult / interpolatedAlpha.alphaForUnpremultiplication;
    53124    }
    54125}
    55126
    56 template<AlphaPremultiplication alphaPremultiplication, typename InterpolationMethodColorSpace>
    57 std::pair<ColorComponents<float, 4>, ColorComponents<float, 4>> preInterpolationNormalization(InterpolationMethodColorSpace interpolationMethodColorSpace, ColorComponents<float, 4> colorComponents1, ColorComponents<float, 4> colorComponents2)
     127// MARK: - Unpremultiplied interpolation.
     128
     129inline float interpolateAlphaUnpremulitplied(float alphaForColor1, double color1Multiplier, float alphaForColor2, double color2Multiplier)
    58130{
    59     auto [colorA0, colorB0] = preInterpolationNormalizationForComponent<0, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents1, colorComponents2);
    60     auto [colorA1, colorB1] = preInterpolationNormalizationForComponent<1, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents1, colorComponents2);
    61     auto [colorA2, colorB2] = preInterpolationNormalizationForComponent<2, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents1, colorComponents2);
    62 
    63     return {
    64         { colorA0, colorA1, colorA2, colorComponents1[3] },
    65         { colorB0, colorB1, colorB2, colorComponents2[3] }
    66     };
     131    return interpolateComponentAccountingForNaN(alphaForColor1, color1Multiplier, alphaForColor2, color2Multiplier);
    67132}
    68133
    69 
    70 // MARK: - Post-interpolation normalization/fixup
    71 
    72 template<size_t I, AlphaPremultiplication alphaPremultiplication, typename InterpolationMethodColorSpace>
    73 float postInterpolationNormalizationForComponent(InterpolationMethodColorSpace, ColorComponents<float, 4> colorComponents)
     134template<size_t I, typename InterpolationMethodColorSpace>
     135float interpolateComponentUsingUnpremultipliedAlpha(InterpolationMethodColorSpace interpolationMethodColorSpace, ColorComponents<float, 4> colorComponents1, double color1Multiplier, ColorComponents<float, 4> colorComponents2, double color2Multiplier)
    74136{
    75137    using ColorType = typename InterpolationMethodColorSpace::ColorType;
    76138    constexpr auto componentInfo = ColorType::Model::componentInfo;
    77139
    78     if constexpr (componentInfo[I].type != ColorComponentType::Angle && alphaPremultiplication == AlphaPremultiplication::Premultiplied) {
    79         if (colorComponents[3] == 0.0f)
    80             return 0;
    81         return colorComponents[I] / colorComponents[3];
    82     } else
    83         return colorComponents[I];
     140    if constexpr (componentInfo[I].type == ColorComponentType::Angle)
     141        return interpolateHue(interpolationMethodColorSpace, colorComponents1[I], color1Multiplier, colorComponents2[I], color2Multiplier);
     142    else
     143        return interpolateComponentAccountingForNaN(colorComponents1[I], color1Multiplier, colorComponents2[I], color2Multiplier);
    84144}
    85145
    86 template<AlphaPremultiplication alphaPremultiplication, typename InterpolationMethodColorSpace>
    87 ColorComponents<float, 4> postInterpolationNormalization(InterpolationMethodColorSpace interpolationMethodColorSpace, ColorComponents<float, 4> colorComponents)
    88 {
    89     return {
    90         postInterpolationNormalizationForComponent<0, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents),
    91         postInterpolationNormalizationForComponent<1, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents),
    92         postInterpolationNormalizationForComponent<2, alphaPremultiplication>(interpolationMethodColorSpace, colorComponents),
    93         colorComponents[3]
    94     };
    95  }
    96 
    97 
    98 // MARK: - Interpolation
     146// MARK: - Interpolation.
    99147
    100148template<AlphaPremultiplication alphaPremultiplication, typename InterpolationMethodColorSpace>
    101149typename InterpolationMethodColorSpace::ColorType interpolateColorComponents(InterpolationMethodColorSpace interpolationMethodColorSpace, typename InterpolationMethodColorSpace::ColorType color1, double color1Multiplier, typename InterpolationMethodColorSpace::ColorType color2, double color2Multiplier)
    102150{
    103     // 1. Apply pre-interpolation transforms (hue fixup for polar color spaces, alpha premultiplication if required).
    104     auto [normalizedColorComponents1, normalizedColorComponents2] = preInterpolationNormalization<alphaPremultiplication>(interpolationMethodColorSpace, asColorComponents(color1.resolved()), asColorComponents(color2.resolved()));
     151    auto colorComponents1 = asColorComponents(color1.unresolved());
     152    auto colorComponents2 = asColorComponents(color2.unresolved());
    105153
    106     // 2. Interpolate using the normalized components.
    107     auto interpolatedColorComponents = mapColorComponents([&] (auto componentFromColor1, auto componentFromColor2) -> float {
    108         return (componentFromColor1 * color1Multiplier) + (componentFromColor2 * color2Multiplier);
    109     }, normalizedColorComponents1, normalizedColorComponents2);
     154    if constexpr (alphaPremultiplication == AlphaPremultiplication::Premultiplied) {
     155        auto interpolatedAlpha = interpolateAlphaPremulitplied(colorComponents1[3], color1Multiplier, colorComponents2[3], color2Multiplier);
     156        auto interpolatedComponent1 = interpolateComponentUsingPremultipliedAlpha<0>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier, interpolatedAlpha);
     157        auto interpolatedComponent2 = interpolateComponentUsingPremultipliedAlpha<1>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier, interpolatedAlpha);
     158        auto interpolatedComponent3 = interpolateComponentUsingPremultipliedAlpha<2>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier, interpolatedAlpha);
    110159
    111     // 3. Apply post-interpolation trasforms (alpha un-premultiplication if required).
    112     auto normalizedInterpolatedColorComponents = postInterpolationNormalization<alphaPremultiplication>(interpolationMethodColorSpace, interpolatedColorComponents);
     160        return makeColorTypeByNormalizingComponents<typename InterpolationMethodColorSpace::ColorType>({ interpolatedComponent1, interpolatedComponent2, interpolatedComponent3, interpolatedAlpha.resultAlpha });
     161    } else {
     162        auto interpolatedAlpha = interpolateAlphaUnpremulitplied(colorComponents1[3], color1Multiplier, colorComponents2[3], color2Multiplier);
     163        auto interpolatedComponent1 = interpolateComponentUsingUnpremultipliedAlpha<0>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier);
     164        auto interpolatedComponent2 = interpolateComponentUsingUnpremultipliedAlpha<1>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier);
     165        auto interpolatedComponent3 = interpolateComponentUsingUnpremultipliedAlpha<2>(interpolationMethodColorSpace, colorComponents1, color1Multiplier, colorComponents2, color2Multiplier);
    113166
    114     // 4. Create color type from components, normalizing any components that may be out of range.
    115     return makeColorTypeByNormalizingComponents<typename InterpolationMethodColorSpace::ColorType>(normalizedInterpolatedColorComponents);
    116 }
    117 
    118 inline Color interpolateColors(ColorInterpolationMethod colorInterpolationMethod, Color color1, double color1Multiplier, Color color2, double color2Multiplier)
    119 {
    120     return WTF::switchOn(colorInterpolationMethod.colorSpace,
    121         [&] (auto& colorSpace) {
    122             using ColorType = typename std::remove_reference_t<decltype(colorSpace)>::ColorType;
    123             switch (colorInterpolationMethod.alphaPremultiplication) {
    124             case AlphaPremultiplication::Premultiplied:
    125                 return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Premultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
    126             case AlphaPremultiplication::Unpremultiplied:
    127                 return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Unpremultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
    128             }
    129             RELEASE_ASSERT_NOT_REACHED();
    130         }
    131     );
     167        return makeColorTypeByNormalizingComponents<typename InterpolationMethodColorSpace::ColorType>({ interpolatedComponent1, interpolatedComponent2, interpolatedComponent3, interpolatedAlpha });
     168    }
    132169}
    133170
  • trunk/Source/WebCore/platform/graphics/ColorTypes.h

    r288388 r288427  
    136136constexpr bool constexprIsNaN(ComponentType value)
    137137{
    138     // FIXME: Replace std::isnan() once std::isnan() is constexpr.
     138    // FIXME: Replace with std::isnan() once std::isnan() is constexpr.
    139139    return value != value;
    140140}
Note: See TracChangeset for help on using the changeset viewer.