Changeset 272344 in webkit


Ignore:
Timestamp:
Feb 3, 2021 3:37:14 PM (18 months ago)
Author:
weinig@apple.com
Message:

Add support for hwb() colors defined in CSS Color 4
https://bugs.webkit.org/show_bug.cgi?id=221352

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Add some new WPT tests for hwb() that will be upstreamed shortly.

  • web-platform-tests/css/css-color/color-resolving-hwb-expected.txt: Added.
  • web-platform-tests/css/css-color/color-resolving-hwb.html: Added.
  • web-platform-tests/css/css-color/hwb-001-expected.html: Added.
  • web-platform-tests/css/css-color/hwb-001.html: Added.
  • web-platform-tests/css/css-color/hwb-002-expected.html: Added.
  • web-platform-tests/css/css-color/hwb-002.html: Added.
  • web-platform-tests/css/css-color/hwb-003-expected.html: Added.
  • web-platform-tests/css/css-color/hwb-003.html: Added.
  • web-platform-tests/css/css-color/hwb-004-expected.html: Added.
  • web-platform-tests/css/css-color/hwb-004.html: Added.
  • web-platform-tests/css/css-color/hwb-005-expected.html: Added.
  • web-platform-tests/css/css-color/hwb-005.html: Added.

Source/WebCore:

Add support for hwb() colors. They are similar to the existing
hsl()/hsla() colors, in that they are a transformation of sRGB
specified using a "hue" component and two additional values.
In the case of hwb(), it is hue, whiteness and blackness.

Tests: imported/w3c/web-platform-tests/css/css-color/color-resolving-hwb.html

imported/w3c/web-platform-tests/css/css-color/hwb-001.html
imported/w3c/web-platform-tests/css/css-color/hwb-002.html
imported/w3c/web-platform-tests/css/css-color/hwb-003.html
imported/w3c/web-platform-tests/css/css-color/hwb-004.html
imported/w3c/web-platform-tests/css/css-color/hwb-005.html

  • css/CSSValueKeywords.in:

Add hwb keyword.

  • css/parser/CSSPropertyParserHelpers.cpp:

(WebCore::CSSPropertyParserHelpers::parseHWBParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunction):
Add parsing support for hwb(). Canonicalizing to 0-1 to match
how HSL/HSLA is canonicalized.

  • platform/graphics/ColorConversion.cpp:

(WebCore::calculateHSLHue):
(WebCore::toHSLA):
(WebCore::toSRGBA):
(WebCore::toHWBA):
(WebCore::toXYZA):
(WebCore::calcHue): Deleted.

  • platform/graphics/ColorConversion.h:

Implement conversions to/from sRGB, refactoring HSL conversion
code to reuse hue calculation which is the same.

  • platform/graphics/ColorModels.h:

Add HWBModel and fix HSLModel which incorrectly expanded allowed ranges
to the parsed form, rather than the form we use internally. We may want
change this in the future, as it is a bit confusing and pretty unnessary.

  • platform/graphics/ColorTypes.h:

(WebCore::HWBA::HWBA):
(WebCore::asColorComponents):
Add HWBA color type.

LayoutTests:

  • tests-options.json:

Mark WPT test as slow, matching the HSL/HSLA test it based on.

Location:
trunk
Files:
12 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r272339 r272344  
     12021-02-03  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for hwb() colors defined in CSS Color 4
     4        https://bugs.webkit.org/show_bug.cgi?id=221352
     5
     6        Reviewed by Darin Adler.
     7
     8        * tests-options.json:
     9        Mark WPT test as slow, matching the HSL/HSLA test it based on.
     10
    1112021-02-03  Devin Rousso  <drousso@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r272338 r272344  
     12021-02-03  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for hwb() colors defined in CSS Color 4
     4        https://bugs.webkit.org/show_bug.cgi?id=221352
     5
     6        Reviewed by Darin Adler.
     7
     8        Add some new WPT tests for hwb() that will be upstreamed shortly.
     9
     10        * web-platform-tests/css/css-color/color-resolving-hwb-expected.txt: Added.
     11        * web-platform-tests/css/css-color/color-resolving-hwb.html: Added.
     12        * web-platform-tests/css/css-color/hwb-001-expected.html: Added.
     13        * web-platform-tests/css/css-color/hwb-001.html: Added.
     14        * web-platform-tests/css/css-color/hwb-002-expected.html: Added.
     15        * web-platform-tests/css/css-color/hwb-002.html: Added.
     16        * web-platform-tests/css/css-color/hwb-003-expected.html: Added.
     17        * web-platform-tests/css/css-color/hwb-003.html: Added.
     18        * web-platform-tests/css/css-color/hwb-004-expected.html: Added.
     19        * web-platform-tests/css/css-color/hwb-004.html: Added.
     20        * web-platform-tests/css/css-color/hwb-005-expected.html: Added.
     21        * web-platform-tests/css/css-color/hwb-005.html: Added.
     22
    1232021-02-03  Ziran Sun  <zsun@igalia.com>
    224
  • trunk/LayoutTests/tests-options.json

    r270933 r272344  
    636636        "slow"
    637637    ],
     638    "imported/w3c/web-platform-tests/css/css-color/color-resolving-hwb.html": [
     639        "slow"
     640    ],
    638641    "imported/w3c/web-platform-tests/css/css-fonts/font-display/font-display.html": [
    639642        "slow"
  • trunk/Source/WebCore/ChangeLog

    r272340 r272344  
     12021-02-03  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for hwb() colors defined in CSS Color 4
     4        https://bugs.webkit.org/show_bug.cgi?id=221352
     5
     6        Reviewed by Darin Adler.
     7
     8        Add support for hwb() colors. They are similar to the existing
     9        hsl()/hsla() colors, in that they are a transformation of sRGB
     10        specified using a "hue" component and two additional values.
     11        In the case of hwb(), it is hue, whiteness and blackness.
     12
     13        Tests: imported/w3c/web-platform-tests/css/css-color/color-resolving-hwb.html
     14               imported/w3c/web-platform-tests/css/css-color/hwb-001.html
     15               imported/w3c/web-platform-tests/css/css-color/hwb-002.html
     16               imported/w3c/web-platform-tests/css/css-color/hwb-003.html
     17               imported/w3c/web-platform-tests/css/css-color/hwb-004.html
     18               imported/w3c/web-platform-tests/css/css-color/hwb-005.html
     19
     20        * css/CSSValueKeywords.in:
     21        Add hwb keyword.
     22
     23        * css/parser/CSSPropertyParserHelpers.cpp:
     24        (WebCore::CSSPropertyParserHelpers::parseHWBParameters):
     25        (WebCore::CSSPropertyParserHelpers::parseColorFunction):
     26        Add parsing support for hwb(). Canonicalizing to 0-1 to match
     27        how HSL/HSLA is canonicalized.
     28
     29        * platform/graphics/ColorConversion.cpp:
     30        (WebCore::calculateHSLHue):
     31        (WebCore::toHSLA):
     32        (WebCore::toSRGBA):
     33        (WebCore::toHWBA):
     34        (WebCore::toXYZA):
     35        (WebCore::calcHue): Deleted.
     36        * platform/graphics/ColorConversion.h:
     37        Implement conversions to/from sRGB, refactoring HSL conversion
     38        code to reuse hue calculation which is the same.
     39
     40        * platform/graphics/ColorModels.h:
     41        Add HWBModel and fix HSLModel which incorrectly expanded allowed ranges
     42        to the parsed form, rather than the form we use internally. We may want
     43        change this in the future, as it is a bit confusing and pretty unnessary.
     44
     45        * platform/graphics/ColorTypes.h:
     46        (WebCore::HWBA::HWBA):
     47        (WebCore::asColorComponents):
     48        Add HWBA color type.
     49
    1502021-02-03  Adrian Perez de Castro  <aperez@igalia.com>
    251
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r272311 r272344  
    12621262hsl
    12631263hsla
     1264hwb
    12641265lab
    12651266lch
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r272311 r272344  
    830830}
    831831
     832static Color parseHWBParameters(CSSParserTokenRange& range, CSSParserMode cssParserMode)
     833{
     834    ASSERT(range.peek().functionId() == CSSValueHwb);
     835    CSSParserTokenRange args = consumeFunction(range);
     836
     837    double hueAngleInDegrees;
     838    if (auto angle = consumeAngleRaw(args, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
     839        hueAngleInDegrees = CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
     840    else if (auto number = consumeNumberRaw(args))
     841        hueAngleInDegrees = *number;
     842    else
     843        return { };
     844
     845    auto whiteness = consumePercentRaw(args, ValueRangeAll);
     846    if (!whiteness)
     847        return { };
     848
     849    auto blackness = consumePercentRaw(args, ValueRangeAll);
     850    if (!blackness)
     851        return { };
     852
     853    auto alpha = parseOptionalAlpha(args);
     854    if (!alpha)
     855        return { };
     856
     857    if (!args.atEnd())
     858        return { };
     859
     860    // Normalize hue.
     861
     862    hueAngleInDegrees = std::fmod(hueAngleInDegrees, 360.0);
     863    if (hueAngleInDegrees < 0.0)
     864        hueAngleInDegrees += 360.0;
     865   
     866    // Convert angle to normalized form from 0 - 1.
     867    auto normalizedHue = hueAngleInDegrees / 360.0;
     868
     869    // Normalize whiteness/blackness.
     870
     871    //   Values outside of these ranges are not invalid, but are clamped to the
     872    //   ranges defined here at computed-value time.
     873    auto nomalizedWhiteness = clampTo<double>(*whiteness, 0, 100);
     874    auto nomalizedBlackness = clampTo<double>(*blackness, 0, 100);
     875
     876    //   If the sum of these two arguments is greater than 100%, then at
     877    //   computed-value time they are further normalized to add up to 100%, with
     878    //   the same relative ratio.
     879    if (auto sum = nomalizedWhiteness + nomalizedBlackness; sum >= 100) {
     880        nomalizedWhiteness *= 100.0 / sum;
     881        nomalizedBlackness *= 100.0 / sum;
     882    }
     883
     884    // Convert to normalized form from 0 - 1.
     885    nomalizedWhiteness /= 100.0;
     886    nomalizedBlackness /= 100.0;
     887
     888    return convertTo<SRGBA<uint8_t>>(toSRGBA(HWBA<float> { static_cast<float>(normalizedHue), static_cast<float>(nomalizedWhiteness), static_cast<float>(nomalizedBlackness), static_cast<float>(*alpha) }));
     889}
     890
    832891static Color parseLabParameters(CSSParserTokenRange& range)
    833892{
     
    10661125    case CSSValueHsla:
    10671126        color = parseHSLParameters(colorRange, cssParserMode);
     1127        break;
     1128    case CSSValueHwb:
     1129        color = parseHWBParameters(colorRange, cssParserMode);
    10681130        break;
    10691131    case CSSValueLab:
  • trunk/Source/WebCore/platform/graphics/ColorConversion.cpp

    r272146 r272344  
    306306// MARK: HSL conversions.
    307307
    308 HSLA<float> toHSLA(const SRGBA<float>& color)
    309 {
    310     // http://en.wikipedia.org/wiki/HSL_color_space.
     308struct HSLHueCalculationResult {
     309    float hue;
     310    float min;
     311    float max;
     312    float chroma;
     313};
     314
     315static HSLHueCalculationResult calculateHSLHue(const SRGBA<float>& color)
     316{
    311317    auto [r, g, b, alpha] = color;
    312 
    313318    auto [min, max] = std::minmax({ r, g, b });
    314319    float chroma = max - min;
     
    329334    hue /= 360.0f;
    330335
     336    return { hue, min, max, chroma };
     337}
     338
     339HSLA<float> toHSLA(const SRGBA<float>& color)
     340{
     341    // https://drafts.csswg.org/css-color-4/#hsl-to-rgb
     342    auto [r, g, b, alpha] = color;
     343    auto [hue, min, max, chroma] = calculateHSLHue(color);
     344
    331345    float lightness = 0.5f * (max + min);
    332346    float saturation;
     
    338352        saturation = (chroma / (2.0f - (max + min)));
    339353
    340     return {
    341         hue,
    342         saturation,
    343         lightness,
    344         alpha
    345     };
    346 }
    347 
    348 // Hue is in the range 0-6, other args in 0-1.
    349 static float calcHue(float temp1, float temp2, float hueVal)
    350 {
    351     if (hueVal < 0.0f)
    352         hueVal += 6.0f;
    353     else if (hueVal >= 6.0f)
    354         hueVal -= 6.0f;
    355     if (hueVal < 1.0f)
    356         return temp1 + (temp2 - temp1) * hueVal;
    357     if (hueVal < 3.0f)
    358         return temp2;
    359     if (hueVal < 4.0f)
    360         return temp1 + (temp2 - temp1) * (4.0f - hueVal);
    361     return temp1;
    362 }
    363 
    364 // Explanation of this algorithm can be found in the CSS Color 4 Module
    365 // specification at https://drafts.csswg.org/css-color-4/#hsl-to-rgb with
    366 // further explanation available at http://en.wikipedia.org/wiki/HSL_color_space
     354    return { hue, saturation, lightness, alpha };
     355}
     356
    367357SRGBA<float> toSRGBA(const HSLA<float>& color)
    368358{
     359    // https://drafts.csswg.org/css-color-4/#hsl-to-rgb
    369360    auto [hue, saturation, lightness, alpha] = color;
    370361
    371     // Convert back to RGB.
    372     if (!saturation) {
    373         return {
    374             lightness,
    375             lightness,
    376             lightness,
    377             alpha
    378         };
    379     }
     362    if (!saturation)
     363        return { lightness, lightness, lightness, alpha };
    380364   
    381365    float temp2 = lightness <= 0.5f ? lightness * (1.0f + saturation) : lightness + saturation - lightness * saturation;
    382366    float temp1 = 2.0f * lightness - temp2;
    383367   
    384     hue *= 6.0f; // calcHue() wants hue in the 0-6 range.
     368    // Hue is in the range 0-6, other args in 0-1.
     369    auto hueToRGB = [](float temp1, float temp2, float hue) {
     370        if (hue < 1.0f)
     371            return temp1 + (temp2 - temp1) * hue;
     372        if (hue < 3.0f)
     373            return temp2;
     374        if (hue < 4.0f)
     375            return temp1 + (temp2 - temp1) * (4.0f - hue);
     376        return temp1;
     377    };
     378
     379    // hueToRGB() wants hue in the 0-6 range.
     380    hue *= 6.0f;
     381
     382    auto hueForRed = hue + 2.0f;
     383    auto hueForGreen = hue;
     384    auto hueForBlue = hue - 2.0f;
     385    if (hueForRed > 6.0f)
     386        hueForRed -= 6.0f;
     387    else if (hueForBlue < 0.0f)
     388        hueForBlue += 6.0f;
     389
    385390    return {
    386         calcHue(temp1, temp2, hue + 2.0f),
    387         calcHue(temp1, temp2, hue),
    388         calcHue(temp1, temp2, hue - 2.0f),
     391        hueToRGB(temp1, temp2, hueForRed),
     392        hueToRGB(temp1, temp2, hueForGreen),
     393        hueToRGB(temp1, temp2, hueForBlue),
     394        alpha
     395    };
     396}
     397
     398// MARK: HWB conversions.
     399
     400HWBA<float> toHWBA(const SRGBA<float>& color)
     401{
     402    // https://drafts.csswg.org/css-color-4/#rgb-to-hwb
     403    auto [hue, min, max, chroma] = calculateHSLHue(color);
     404    auto whiteness = min;
     405    auto blackness = 1.0f - max;
     406   
     407    return { hue, whiteness, blackness, color.alpha };
     408}
     409
     410SRGBA<float> toSRGBA(const HWBA<float>& color)
     411{
     412    // https://drafts.csswg.org/css-color-4/#hwb-to-rgb
     413    auto [hue, whiteness, blackness, alpha] = color;
     414
     415    if (whiteness + blackness == 1.0f)
     416        return { whiteness, whiteness, whiteness, alpha };
     417
     418    // This is the hueToRGB function in toSRGBA(const HSLA&) with temp1 == 0
     419    // and temp2 == 1 strength reduced through it.
     420    auto hueToRGB = [](float hue) {
     421        if (hue < 1.0f)
     422            return hue;
     423        if (hue < 3.0f)
     424            return 1.0f;
     425        if (hue < 4.0f)
     426            return 4.0f - hue;
     427        return 0.0f;
     428    };
     429
     430    auto applyWhitenessBlackness = [&](float component) {
     431        return (component * (1.0f - color.whiteness - color.blackness)) + color.whiteness;
     432    };
     433
     434    // hueToRGB() wants hue in the 0-6 range.
     435    hue *= 6.0f;
     436
     437    auto hueForRed = hue + 2.0f;
     438    auto hueForGreen = hue;
     439    auto hueForBlue = hue - 2.0f;
     440    if (hueForRed > 6.0f)
     441        hueForRed -= 6.0f;
     442    else if (hueForBlue < 0.0f)
     443        hueForBlue += 6.0f;
     444
     445    return {
     446        applyWhitenessBlackness(hueToRGB(hueForRed)),
     447        applyWhitenessBlackness(hueToRGB(hueForGreen)),
     448        applyWhitenessBlackness(hueToRGB(hueForBlue)),
    389449        alpha
    390450    };
     
    527587}
    528588
     589// - HWBA combination functions.
     590
     591HWBA<float>::ReferenceXYZ toXYZA(const HWBA<float>& color)
     592{
     593    return toXYZA(toSRGBA(color));
     594}
     595
     596HWBA<float> toHWBA(const HWBA<float>::ReferenceXYZ& color)
     597{
     598    return toHWBA(toSRGBA(color));
     599}
     600
    529601// - LCHA combination functions.
    530602
  • trunk/Source/WebCore/platform/graphics/ColorConversion.h

    r272311 r272344  
    7272WEBCORE_EXPORT SRGBA<float> toSRGBA(const HSLA<float>&);
    7373
     74// HWBA
     75WEBCORE_EXPORT HWBA<float>::ReferenceXYZ toXYZA(const HWBA<float>&);
     76WEBCORE_EXPORT HWBA<float> toHWBA(const HWBA<float>::ReferenceXYZ&);
     77// Additions
     78WEBCORE_EXPORT SRGBA<float> toSRGBA(const HWBA<float>&);
     79
    7480// LCHA
    7581WEBCORE_EXPORT LCHA<float>::ReferenceXYZ toXYZA(const LCHA<float>&);
     
    138144WEBCORE_EXPORT LinearSRGBA<float> toLinearSRGBA(const SRGBA<float>&);
    139145WEBCORE_EXPORT HSLA<float> toHSLA(const SRGBA<float>&);
     146WEBCORE_EXPORT HWBA<float> toHWBA(const SRGBA<float>&);
    140147
    141148
     
    163170constexpr ExtendedSRGBA<float> toExtendedSRGBA(const ExtendedSRGBA<float>& color) { return color; }
    164171constexpr HSLA<float> toHSLA(const HSLA<float>& color) { return color; }
     172constexpr HWBA<float> toHWBA(const HWBA<float>& color) { return color; }
    165173constexpr LCHA<float> toLCHA(const LCHA<float>& color) { return color; }
    166174constexpr Lab<float> toLab(const Lab<float>& color) { return color; }
     
    202210}
    203211
     212template<typename T> HWBA<float> toHWBA(const T& color)
     213{
     214    return toHWBA(performChomaticAdapatation<HWBA<float>>(toXYZA(color)));
     215}
     216
    204217template<typename T> LCHA<float> toLCHA(const T& color)
    205218{
  • trunk/Source/WebCore/platform/graphics/ColorModels.h

    r272311 r272344  
    3535template<typename> struct ExtendedRGBModel;
    3636template<typename> struct HSLModel;
     37template<typename> struct HWBModel;
    3738template<typename> struct LCHModel;
    3839template<typename> struct LabModel;
     
    6768template<> struct HSLModel<float> {
    6869    static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
    69         { 0, 360 },
    70         { 0, 100 },
    71         { 0, 100 }
     70        { 0, 1 },
     71        { 0, 1 },
     72        { 0, 1 }
    7273    } };
    73     static constexpr bool isInvertible = true;
     74    static constexpr bool isInvertible = false;
     75};
     76
     77template<> struct HWBModel<float> {
     78    static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
     79        { 0, 1 },
     80        { 0, 1 },
     81        { 0, 1 }
     82    } };
     83    static constexpr bool isInvertible = false;
    7484};
    7585
  • trunk/Source/WebCore/platform/graphics/ColorTypes.h

    r272311 r272344  
    3737template<typename> struct ExtendedSRGBA;
    3838template<typename> struct HSLA;
     39template<typename> struct HWBA;
    3940template<typename> struct LCHA;
    4041template<typename> struct Lab;
     
    402403}
    403404
     405// MARK: - HWBA Color Type.
     406
     407template<typename T> struct HWBA : ColorWithAlphaHelper<HWBA<T>> {
     408    using ComponentType = T;
     409    using Model = HWBModel<T>;
     410    using ReferenceXYZ = XYZA<T, WhitePoint::D65>;
     411
     412    constexpr HWBA(T hue, T whiteness, T blackness, T alpha = AlphaTraits<T>::opaque)
     413        : hue { hue }
     414        , whiteness { whiteness }
     415        , blackness { blackness }
     416        , alpha { alpha }
     417    {
     418        assertInRange(*this);
     419    }
     420
     421    constexpr HWBA()
     422        : HWBA { 0, 0, 0, 0 }
     423    {
     424    }
     425
     426    T hue;
     427    T whiteness;
     428    T blackness;
     429    T alpha;
     430};
     431
     432template<typename T> constexpr ColorComponents<T> asColorComponents(const HWBA<T>& c)
     433{
     434    return { c.hue, c.whiteness, c.blackness, c.alpha };
     435}
     436
    404437// MARK: - XYZ Color Type.
    405438
Note: See TracChangeset for help on using the changeset viewer.