Changeset 273211 in webkit


Ignore:
Timestamp:
Feb 20, 2021 4:47:59 PM (17 months ago)
Author:
weinig@apple.com
Message:

color(lab ...) should serialize as color(lab ...) not lab() according to latest CSS Color 4 spec
https://bugs.webkit.org/show_bug.cgi?id=222110

Reviewed by Dean Jackson.

Source/WebCore:

To make this work it was necessary to make it so that extended colors, like Lab,
could store an extra bit of data on Color to indicate that it should use the
color() function for serialization when parsed using the color() form.

To do that, Color was reworked to allow extra metadata flags for both inline and
extended colors. Previously, only inline colors could make use of the extra bits.
Now, we take advantage of the fact that we have the high 16 bits available to us
for pointers to also store that metadata for extended colors. Rather than using a
union, we encode the pointer / inline color into a uint64_t, and use the extra bits
for the flags we need. Currently we only use 6, so there is quite a bit more that
could be used here.

Finally, the color serialization code has been updated to check for the new bit,
called UseColorFunctionSerialization, and to serialize using color() notation
if it is set.

We are currently only taking advantage of this for differentiating between lab(...)
and color(lab ...), but in the future we should be able to also optimize color(srgb ...)
values that can be represented fully by SRGBA<uint8_t>.

Since we can now add flags for extended colors, the semantic bit is also now usable
for extended colors, though none currently exist.

  • css/parser/CSSPropertyParserHelpers.cpp:

(WebCore::CSSPropertyParserHelpers::parseColorFunctionForRGBTypes):
(WebCore::CSSPropertyParserHelpers::parseColorFunctionForLabParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunctionForXYZParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):

  • platform/graphics/Color.cpp:

(WebCore::Color::Color):
(WebCore::Color::operator=):
(WebCore::Color::colorWithAlpha const):
(WebCore::Color::semanticColor const):

  • platform/graphics/Color.h:

(WebCore::Color::isHashTableDeletedValue const):
(WebCore::Color::Color):
(WebCore::Color::toAllFlags):
(WebCore::Color::setColor):
(WebCore::Color::setExtendedColor):
(WebCore::operator==):
(WebCore::extendedColorsEqual):
(WebCore::extendedColorsEqualIgnoringSemanticColor):
(WebCore::equalIgnoringSemanticColor):
(WebCore::Color::~Color):
(WebCore::Color::hash const):
(WebCore::Color::isValid const):
(WebCore::Color::isSemantic const):
(WebCore::Color::usesColorFunctionSerialization const):
(WebCore::Color::flags const):
(WebCore::Color::isExtended const):
(WebCore::Color::isInline const):
(WebCore::Color::asExtended const):
(WebCore::Color::asExtendedRef const):
(WebCore::Color::asInline const):
(WebCore::Color::asPackedInline const):
(WebCore::Color::encodedFlags):
(WebCore::Color::encodedInlineColor):
(WebCore::Color::encodedPackedInlineColor):
(WebCore::Color::encodedExtendedColor):
(WebCore::Color::decodedFlags):
(WebCore::Color::decodedInlineColor):
(WebCore::Color::decodedPackedInlineColor):
(WebCore::Color::decodedExtendedColor):
(WebCore::Color::setInvalid):
(WebCore::Color::encode const):
(WebCore::Color::decode):
(WebCore::Color::tagAsSemantic): Deleted.
(WebCore::Color::tagAsValid): Deleted.

  • platform/graphics/ColorBlending.cpp:

(WebCore::blendWithWhite):

  • platform/graphics/ColorSerialization.cpp:

(WebCore::serializationForCSS):
(WebCore::serializationForHTML):
(WebCore::serializationForRenderTreeAsText):
(WebCore::serializationUsingColorFunction):

  • platform/graphics/cg/ColorCG.cpp:

(WebCore::Color::Color):

  • platform/graphics/mac/ColorMac.mm:

(WebCore::semanticColorFromNSColor):

  • rendering/RenderThemeIOS.mm:

(WebCore::systemColorFromCSSValueIDSelector):
(WebCore::systemColorFromCSSValueID):

  • rendering/RenderThemeMac.mm:

(WebCore::RenderThemeMac::systemColor const):

LayoutTests:

  • fast/css/parsing-lab-colors-expected.txt:
  • fast/css/parsing-lab-colors.html:

Update test and results for new serialization of color(lab ...).

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r273209 r273211  
     12021-02-20  Sam Weinig  <weinig@apple.com>
     2
     3        color(lab ...) should serialize as color(lab ...) not lab() according to latest CSS Color 4 spec
     4        https://bugs.webkit.org/show_bug.cgi?id=222110
     5
     6        Reviewed by Dean Jackson.
     7
     8        * fast/css/parsing-lab-colors-expected.txt:
     9        * fast/css/parsing-lab-colors.html:
     10        Update test and results for new serialization of color(lab ...).
     11
    1122021-02-20  Jiewen Tan  <jiewen_tan@apple.com>
    213
  • trunk/LayoutTests/fast/css/parsing-lab-colors-expected.txt

    r273078 r273211  
    1 Test the parsing of lab, lch and gray colors.
     1Test the parsing of lab(...), lch(...) and color(lab ...) colors.
    22
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
     
    4141
    4242color(lab )
    43 PASS computedStyle("background-color", "color(lab 0% 0 0)") is "lab(0% 0 0)"
    44 PASS computedStyle("background-color", "color(lab 0% 0 0 / 1)") is "lab(0% 0 0)"
    45 PASS computedStyle("background-color", "color(lab 0% 0 0 / 0.5)") is "lab(0% 0 0 / 0.5)"
    46 PASS computedStyle("background-color", "color(lab 20% 0 10/0.5)") is "lab(20% 0 10 / 0.5)"
    47 PASS computedStyle("background-color", "color(lab 20% 0 10/50%)") is "lab(20% 0 10 / 0.5)"
    48 PASS computedStyle("background-color", "color(lab 400% 0 10/50%)") is "lab(400% 0 10 / 0.5)"
    49 PASS computedStyle("background-color", "color(lab 50% -160 160)") is "lab(50% -160 160)"
    50 PASS computedStyle("background-color", "color(lab 50% -200 200)") is "lab(50% -200 200)"
    51 PASS computedStyle("background-color", "color(lab 0% 0 0 / -10%)") is "lab(0% 0 0 / 0)"
    52 PASS computedStyle("background-color", "color(lab 0% 0 0 / 110%)") is "lab(0% 0 0)"
    53 PASS computedStyle("background-color", "color(lab 0% 0 0 / 300%)") is "lab(0% 0 0)"
    54 PASS computedStyle("background-color", "color(lab 50% -200)") is "lab(50% -200 0)"
    55 PASS computedStyle("background-color", "color(lab 50%)") is "lab(50% 0 0)"
    56 PASS computedStyle("background-color", "color(lab)") is "lab(0% 0 0)"
    57 PASS computedStyle("background-color", "color(lab 50% -200 / 0.5)") is "lab(50% -200 0 / 0.5)"
    58 PASS computedStyle("background-color", "color(lab 50% / 0.5)") is "lab(50% 0 0 / 0.5)"
    59 PASS computedStyle("background-color", "color(lab / 0.5)") is "lab(0% 0 0 / 0.5)"
    60 PASS computedStyle("background-color", "color(lab -40% 0 0)") is "lab(0% 0 0)"
    61 PASS computedStyle("background-color", "color(lab 50% -20 0)") is "lab(50% -20 0)"
    62 PASS computedStyle("background-color", "color(lab 50% 0 -20)") is "lab(50% 0 -20)"
     43PASS computedStyle("background-color", "color(lab 0% 0 0)") is "color(lab 0% 0 0)"
     44PASS computedStyle("background-color", "color(lab 0% 0 0 / 1)") is "color(lab 0% 0 0)"
     45PASS computedStyle("background-color", "color(lab 0% 0 0 / 0.5)") is "color(lab 0% 0 0 / 0.5)"
     46PASS computedStyle("background-color", "color(lab 20% 0 10/0.5)") is "color(lab 20% 0 10 / 0.5)"
     47PASS computedStyle("background-color", "color(lab 20% 0 10/50%)") is "color(lab 20% 0 10 / 0.5)"
     48PASS computedStyle("background-color", "color(lab 400% 0 10/50%)") is "color(lab 400% 0 10 / 0.5)"
     49PASS computedStyle("background-color", "color(lab 50% -160 160)") is "color(lab 50% -160 160)"
     50PASS computedStyle("background-color", "color(lab 50% -200 200)") is "color(lab 50% -200 200)"
     51PASS computedStyle("background-color", "color(lab 0% 0 0 / -10%)") is "color(lab 0% 0 0 / 0)"
     52PASS computedStyle("background-color", "color(lab 0% 0 0 / 110%)") is "color(lab 0% 0 0)"
     53PASS computedStyle("background-color", "color(lab 0% 0 0 / 300%)") is "color(lab 0% 0 0)"
     54PASS computedStyle("background-color", "color(lab 50% -200)") is "color(lab 50% -200 0)"
     55PASS computedStyle("background-color", "color(lab 50%)") is "color(lab 50% 0 0)"
     56PASS computedStyle("background-color", "color(lab)") is "color(lab 0% 0 0)"
     57PASS computedStyle("background-color", "color(lab 50% -200 / 0.5)") is "color(lab 50% -200 0 / 0.5)"
     58PASS computedStyle("background-color", "color(lab 50% / 0.5)") is "color(lab 50% 0 0 / 0.5)"
     59PASS computedStyle("background-color", "color(lab / 0.5)") is "color(lab 0% 0 0 / 0.5)"
     60PASS computedStyle("background-color", "color(lab -40% 0 0)") is "color(lab 0% 0 0)"
     61PASS computedStyle("background-color", "color(lab 50% -20 0)") is "color(lab 50% -20 0)"
     62PASS computedStyle("background-color", "color(lab 50% 0 -20)") is "color(lab 50% 0 -20)"
    6363
    6464Test invalid values
  • trunk/LayoutTests/fast/css/parsing-lab-colors.html

    r273078 r273211  
    44<body>
    55<script>
    6     description("Test the parsing of lab, lch and gray colors.");
     6    description("Test the parsing of lab(...), lch(...) and color(lab ...) colors.");
    77
    88    function computedStyle(property, value)
     
    7575    debug('');
    7676    debug('color(lab )');
    77     testComputed("background-color", "color(lab 0% 0 0)", "lab(0% 0 0)");
    78     testComputed("background-color", "color(lab 0% 0 0 / 1)", "lab(0% 0 0)");
    79     testComputed("background-color", "color(lab 0% 0 0 / 0.5)", "lab(0% 0 0 / 0.5)");
    80     testComputed("background-color", "color(lab 20% 0 10/0.5)", "lab(20% 0 10 / 0.5)");
    81     testComputed("background-color", "color(lab 20% 0 10/50%)", "lab(20% 0 10 / 0.5)");
    82     testComputed("background-color", "color(lab 400% 0 10/50%)", "lab(400% 0 10 / 0.5)");
    83     testComputed("background-color", "color(lab 50% -160 160)", "lab(50% -160 160)");
    84     testComputed("background-color", "color(lab 50% -200 200)", "lab(50% -200 200)");
    85     testComputed("background-color", "color(lab 0% 0 0 / -10%)", "lab(0% 0 0 / 0)");
    86     testComputed("background-color", "color(lab 0% 0 0 / 110%)", "lab(0% 0 0)");
    87     testComputed("background-color", "color(lab 0% 0 0 / 300%)", "lab(0% 0 0)");
    88     testComputed("background-color", "color(lab 50% -200)", "lab(50% -200 0)");
    89     testComputed("background-color", "color(lab 50%)", "lab(50% 0 0)");
    90     testComputed("background-color", "color(lab)", "lab(0% 0 0)");
    91     testComputed("background-color", "color(lab 50% -200 / 0.5)", "lab(50% -200 0 / 0.5)");
    92     testComputed("background-color", "color(lab 50% / 0.5)", "lab(50% 0 0 / 0.5)");
    93     testComputed("background-color", "color(lab / 0.5)", "lab(0% 0 0 / 0.5)");
    94     testComputed("background-color", "color(lab -40% 0 0)", "lab(0% 0 0)");
    95     testComputed("background-color", "color(lab 50% -20 0)", "lab(50% -20 0)");
    96     testComputed("background-color", "color(lab 50% 0 -20)", "lab(50% 0 -20)");
     77    testComputed("background-color", "color(lab 0% 0 0)", "color(lab 0% 0 0)");
     78    testComputed("background-color", "color(lab 0% 0 0 / 1)", "color(lab 0% 0 0)");
     79    testComputed("background-color", "color(lab 0% 0 0 / 0.5)", "color(lab 0% 0 0 / 0.5)");
     80    testComputed("background-color", "color(lab 20% 0 10/0.5)", "color(lab 20% 0 10 / 0.5)");
     81    testComputed("background-color", "color(lab 20% 0 10/50%)", "color(lab 20% 0 10 / 0.5)");
     82    testComputed("background-color", "color(lab 400% 0 10/50%)", "color(lab 400% 0 10 / 0.5)");
     83    testComputed("background-color", "color(lab 50% -160 160)", "color(lab 50% -160 160)");
     84    testComputed("background-color", "color(lab 50% -200 200)", "color(lab 50% -200 200)");
     85    testComputed("background-color", "color(lab 0% 0 0 / -10%)", "color(lab 0% 0 0 / 0)");
     86    testComputed("background-color", "color(lab 0% 0 0 / 110%)", "color(lab 0% 0 0)");
     87    testComputed("background-color", "color(lab 0% 0 0 / 300%)", "color(lab 0% 0 0)");
     88    testComputed("background-color", "color(lab 50% -200)", "color(lab 50% -200 0)");
     89    testComputed("background-color", "color(lab 50%)", "color(lab 50% 0 0)");
     90    testComputed("background-color", "color(lab)", "color(lab 0% 0 0)");
     91    testComputed("background-color", "color(lab 50% -200 / 0.5)", "color(lab 50% -200 0 / 0.5)");
     92    testComputed("background-color", "color(lab 50% / 0.5)", "color(lab 50% 0 0 / 0.5)");
     93    testComputed("background-color", "color(lab / 0.5)", "color(lab 0% 0 0 / 0.5)");
     94    testComputed("background-color", "color(lab -40% 0 0)", "color(lab 0% 0 0)");
     95    testComputed("background-color", "color(lab 50% -20 0)", "color(lab 50% -20 0)");
     96    testComputed("background-color", "color(lab 50% 0 -20)", "color(lab 50% 0 -20)");
    9797
    9898    debug('');
  • trunk/Source/WebCore/ChangeLog

    r273210 r273211  
     12021-02-20  Sam Weinig  <weinig@apple.com>
     2
     3        color(lab ...) should serialize as color(lab ...) not lab() according to latest CSS Color 4 spec
     4        https://bugs.webkit.org/show_bug.cgi?id=222110
     5
     6        Reviewed by Dean Jackson.
     7
     8        To make this work it was necessary to make it so that extended colors, like Lab,
     9        could store an extra bit of data on Color to indicate that it should use the
     10        color() function for serialization when parsed using the color() form.
     11
     12        To do that, Color was reworked to allow extra metadata flags for both inline and
     13        extended colors. Previously, only inline colors could make use of the extra bits.
     14        Now, we take advantage of the fact that we have the high 16 bits available to us
     15        for pointers to also store that metadata for extended colors. Rather than using a
     16        union, we encode the pointer / inline color into a uint64_t, and use the extra bits
     17        for the flags we need. Currently we only use 6, so there is quite a bit more that
     18        could be used here.
     19
     20        Finally, the color serialization code has been updated to check for the new bit,
     21        called UseColorFunctionSerialization, and to serialize using color() notation
     22        if it is set.
     23
     24        We are currently only taking advantage of this for differentiating between lab(...)
     25        and color(lab ...), but in the future we should be able to also optimize color(srgb ...)
     26        values that can be represented fully by SRGBA<uint8_t>.
     27
     28        Since we can now add flags for extended colors, the semantic bit is also now usable
     29        for extended colors, though none currently exist.
     30
     31        * css/parser/CSSPropertyParserHelpers.cpp:
     32        (WebCore::CSSPropertyParserHelpers::parseColorFunctionForRGBTypes):
     33        (WebCore::CSSPropertyParserHelpers::parseColorFunctionForLabParameters):
     34        (WebCore::CSSPropertyParserHelpers::parseColorFunctionForXYZParameters):
     35        (WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):
     36        * platform/graphics/Color.cpp:
     37        (WebCore::Color::Color):
     38        (WebCore::Color::operator=):
     39        (WebCore::Color::colorWithAlpha const):
     40        (WebCore::Color::semanticColor const):
     41        * platform/graphics/Color.h:
     42        (WebCore::Color::isHashTableDeletedValue const):
     43        (WebCore::Color::Color):
     44        (WebCore::Color::toAllFlags):
     45        (WebCore::Color::setColor):
     46        (WebCore::Color::setExtendedColor):
     47        (WebCore::operator==):
     48        (WebCore::extendedColorsEqual):
     49        (WebCore::extendedColorsEqualIgnoringSemanticColor):
     50        (WebCore::equalIgnoringSemanticColor):
     51        (WebCore::Color::~Color):
     52        (WebCore::Color::hash const):
     53        (WebCore::Color::isValid const):
     54        (WebCore::Color::isSemantic const):
     55        (WebCore::Color::usesColorFunctionSerialization const):
     56        (WebCore::Color::flags const):
     57        (WebCore::Color::isExtended const):
     58        (WebCore::Color::isInline const):
     59        (WebCore::Color::asExtended const):
     60        (WebCore::Color::asExtendedRef const):
     61        (WebCore::Color::asInline const):
     62        (WebCore::Color::asPackedInline const):
     63        (WebCore::Color::encodedFlags):
     64        (WebCore::Color::encodedInlineColor):
     65        (WebCore::Color::encodedPackedInlineColor):
     66        (WebCore::Color::encodedExtendedColor):
     67        (WebCore::Color::decodedFlags):
     68        (WebCore::Color::decodedInlineColor):
     69        (WebCore::Color::decodedPackedInlineColor):
     70        (WebCore::Color::decodedExtendedColor):
     71        (WebCore::Color::setInvalid):
     72        (WebCore::Color::encode const):
     73        (WebCore::Color::decode):
     74        (WebCore::Color::tagAsSemantic): Deleted.
     75        (WebCore::Color::tagAsValid): Deleted.
     76        * platform/graphics/ColorBlending.cpp:
     77        (WebCore::blendWithWhite):
     78        * platform/graphics/ColorSerialization.cpp:
     79        (WebCore::serializationForCSS):
     80        (WebCore::serializationForHTML):
     81        (WebCore::serializationForRenderTreeAsText):
     82        (WebCore::serializationUsingColorFunction):
     83        * platform/graphics/cg/ColorCG.cpp:
     84        (WebCore::Color::Color):
     85        * platform/graphics/mac/ColorMac.mm:
     86        (WebCore::semanticColorFromNSColor):
     87        * rendering/RenderThemeIOS.mm:
     88        (WebCore::systemColorFromCSSValueIDSelector):
     89        (WebCore::systemColorFromCSSValueID):
     90        * rendering/RenderThemeMac.mm:
     91        (WebCore::RenderThemeMac::systemColor const):
     92
    1932021-02-20  Simon Fraser  <simon.fraser@apple.com>
    294
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r273127 r273211  
    13721372        return { };
    13731373
    1374     return ColorType { clampTo<float>(channels[0], 0.0, 1.0), clampTo<float>(channels[1], 0.0, 1.0), clampTo<float>(channels[2], 0.0, 1.0), static_cast<float>(*alpha) };
     1374    return { ColorType { clampTo<float>(channels[0], 0.0, 1.0), clampTo<float>(channels[1], 0.0, 1.0), clampTo<float>(channels[2], 0.0, 1.0), static_cast<float>(*alpha) }, Color::Flags::UseColorFunctionSerialization };
    13751375}
    13761376
     
    14041404    auto normalizedLightness = std::max(0.0, channels[0]);
    14051405
    1406     return Lab<float> { static_cast<float>(normalizedLightness), static_cast<float>(channels[1]), static_cast<float>(channels[2]), static_cast<float>(*alpha) };
     1406    return { Lab<float> { static_cast<float>(normalizedLightness), static_cast<float>(channels[1]), static_cast<float>(channels[2]), static_cast<float>(*alpha) }, Color::Flags::UseColorFunctionSerialization };
    14071407}
    14081408
     
    14341434        return { };
    14351435
    1436     return XYZA<float, WhitePoint::D50> { static_cast<float>(channels[0]), static_cast<float>(channels[1]), static_cast<float>(channels[2]), static_cast<float>(*alpha) };
     1436    return { XYZA<float, WhitePoint::D50> { static_cast<float>(channels[0]), static_cast<float>(channels[1]), static_cast<float>(channels[2]), static_cast<float>(*alpha) }, Color::Flags::UseColorFunctionSerialization };
    14371437}
    14381438
     
    14771477        return { };
    14781478
     1479    ASSERT(color.usesColorFunctionSerialization());
    14791480    return color;
    14801481}
  • trunk/Source/WebCore/platform/graphics/Color.cpp

    r272731 r273211  
    11/*
    2  * Copyright (C) 2003-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2003-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3838
    3939Color::Color(const Color& other)
    40     : m_colorData(other.m_colorData)
     40    : m_colorAndFlags(other.m_colorAndFlags)
    4141{
    4242    if (isExtended())
    43         m_colorData.extendedColor->ref();
     43        asExtended().ref();
    4444}
    4545
     
    5555
    5656    if (isExtended())
    57         m_colorData.extendedColor->deref();
     57        asExtended().deref();
    5858
    59     m_colorData = other.m_colorData;
     59    m_colorAndFlags = other.m_colorAndFlags;
    6060
    6161    if (isExtended())
    62         m_colorData.extendedColor->ref();
     62        asExtended().ref();
     63
    6364    return *this;
    6465}
     
    7071
    7172    if (isExtended())
    72         m_colorData.extendedColor->deref();
     73        asExtended().deref();
    7374
    74     m_colorData = other.m_colorData;
    75     other.m_colorData.inlineColorAndFlags = invalidInlineColor;
     75    m_colorAndFlags = other.m_colorAndFlags;
     76    other.m_colorAndFlags = invalidColorAndFlags;
    7677
    7778    return *this;
     
    124125Color Color::colorWithAlpha(float alpha) const
    125126{
    126     return callOnUnderlyingType(WTF::makeVisitor(
    127         [&] (const SRGBA<uint8_t>& underlyingColor) -> Color {
    128             Color result = colorWithOverridenAlpha(underlyingColor, alpha);
     127    return callOnUnderlyingType([&] (const auto& underlyingColor) -> Color {
     128        auto result = colorWithOverriddenAlpha(underlyingColor, alpha);
    129129
    130             // FIXME: Why is preserving the semantic bit desired and/or correct here?
    131             if (isSemantic())
    132                 result.tagAsSemantic();
    133             return result;
    134         },
    135         [&] (const auto& underlyingColor) -> Color {
    136             return colorWithOverridenAlpha(underlyingColor, alpha);
    137         }
    138     ));
     130        // FIXME: Why is preserving the semantic bit desired and/or correct here?
     131        if (isSemantic())
     132            return { result, Flags::Semantic };
     133
     134        return { result };
     135    });
    139136}
    140137
     
    148145        // of alternatives.
    149146        if constexpr (ColorType::Model::isInvertible)
    150             return invertedColorWithOverridenAlpha(underlyingColor, alpha);
     147            return invertedcolorWithOverriddenAlpha(underlyingColor, alpha);
    151148        else
    152             return invertedColorWithOverridenAlpha(convertColor<SRGBA<float>>(underlyingColor), alpha);
     149            return invertedcolorWithOverriddenAlpha(convertColor<SRGBA<float>>(underlyingColor), alpha);
    153150    });
    154151}
     
    158155    if (isSemantic())
    159156        return *this;
    160 
    161     return { toSRGBALossy<uint8_t>(), Semantic };
     157   
     158    if (isExtended())
     159        return { asExtendedRef(), Flags::Semantic };
     160    return { asInline(), Flags::Semantic };
    162161}
    163162
  • trunk/Source/WebCore/platform/graphics/Color.h

    r272436 r273211  
    11/*
    2  * Copyright (C) 2003-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2003-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232#include <wtf/HashFunctions.h>
    3333#include <wtf/Hasher.h>
     34#include <wtf/OptionSet.h>
    3435#include <wtf/Optional.h>
     36#include <wtf/StdLibExtras.h>
    3537
    3638#if USE(CG)
     
    5759//    - 4x 8-bit (0-255) sRGBA, stored inline, no allocation
    5860//    - 4x float color components + color space, stored in a reference counted sub-object
    59 //
    60 // Additionally, the inline 8-bit sRGBA can have an optional "semantic" bit set on it,
    61 // which indicates the color originated from a CSS semantic color name.
    62 // FIXME: If we keep the "semantic" bit on Color, we should extend support to all colors,
    63 // not just inline ones, by using the unused pointer bits.
    6461
    6562class Color {
    6663    WTF_MAKE_FAST_ALLOCATED;
    6764public:
     65    enum class Flags {
     66        Semantic                        = 1 << 0,
     67        UseColorFunctionSerialization   = 1 << 1,
     68    };
     69
    6870    Color() = default;
    6971
    70     Color(SRGBA<uint8_t>);
    71     Color(Optional<SRGBA<uint8_t>>);
    72 
    73     enum SemanticTag { Semantic };
    74     Color(SRGBA<uint8_t>, SemanticTag);
    75     Color(Optional<SRGBA<uint8_t>>, SemanticTag);
    76 
    77     Color(ColorComponents<float>, ColorSpace);
    78 
     72    Color(SRGBA<uint8_t>, OptionSet<Flags> = { });
     73    Color(Optional<SRGBA<uint8_t>>, OptionSet<Flags> = { });
     74
     75    Color(ColorComponents<float>, ColorSpace, OptionSet<Flags> = { });
    7976    template<typename ColorType, typename std::enable_if_t<IsColorTypeWithComponentType<ColorType, float>>* = nullptr>
    80     Color(const ColorType&);
     77    Color(const ColorType&, OptionSet<Flags> = { });
    8178
    8279    explicit Color(WTF::HashTableEmptyValueType);
    8380    explicit Color(WTF::HashTableDeletedValueType);
    84     bool isHashTableDeletedValue() const { return m_colorData.inlineColorAndFlags == deletedHashValue; }
     81    bool isHashTableDeletedValue() const;
    8582
    8683    WEBCORE_EXPORT Color(const Color&);
     
    9491    unsigned hash() const;
    9592
    96     bool isValid() const { return isExtended() || (m_colorData.inlineColorAndFlags & validInlineColorBit); }
    97     bool isSemantic() const { return isInline() && (m_colorData.inlineColorAndFlags & isSemanticInlineColorBit); }
     93    bool isValid() const;
     94    bool isSemantic() const;
     95    bool usesColorFunctionSerialization() const;
    9896
    9997    bool isOpaque() const { return isExtended() ? asExtended().alpha() == 1.0 : asInline().alpha == 255; }
     
    141139#if USE(CG)
    142140    WEBCORE_EXPORT Color(CGColorRef);
    143     WEBCORE_EXPORT Color(CGColorRef, SemanticTag);
     141    WEBCORE_EXPORT Color(CGColorRef, OptionSet<Flags>);
    144142#endif
    145143
     
    165163    static constexpr auto orange = SRGBA<uint8_t> { 255, 128, 0 };
    166164
    167     bool isExtended() const { return !(m_colorData.inlineColorAndFlags & invalidInlineColor); }
    168     bool isInline() const { return !isExtended(); }
     165    bool isExtended() const;
     166    bool isInline() const;
    169167
    170168    const ExtendedColor& asExtended() const;
     
    175173    friend bool equalIgnoringSemanticColor(const Color& a, const Color& b);
    176174    friend bool extendedColorsEqual(const Color&, const Color&);
     175    friend bool extendedColorsEqualIgnoringSemanticColor(const Color&, const Color&);
    177176
    178177    static bool isBlackColor(const Color&);
     
    183182
    184183private:
    185     Color(Ref<ExtendedColor>&&);
    186 
    187     void setColor(SRGBA<uint8_t>);
    188     void setExtendedColor(Ref<ExtendedColor>&&);
    189 
    190     void tagAsSemantic() { m_colorData.inlineColorAndFlags |= isSemanticInlineColorBit; }
    191     void tagAsValid() { m_colorData.inlineColorAndFlags |= validInlineColor; }
    192 
    193     // 0x_______00 is an ExtendedColor pointer.
    194     // 0x_______01 is an invalid inline color.
    195     // 0x_______11 is a valid inline color.
    196     static const uint64_t extendedColor = 0x0;
    197     static const uint64_t invalidInlineColor = 0x1;
    198     static const uint64_t validInlineColorBit = 0x2;
    199     static const uint64_t validInlineColor = 0x3;
    200     static const uint64_t isSemanticInlineColorBit = 0x4;
    201 
    202     static const uint64_t deletedHashValue = 0xFFFFFFFFFFFFFFFD;
    203     static const uint64_t emptyHashValue = 0xFFFFFFFFFFFFFFFB;
    204 
    205     union {
    206         uint64_t inlineColorAndFlags { invalidInlineColor };
    207         ExtendedColor* extendedColor;
    208     } m_colorData;
     184    Color(Ref<ExtendedColor>&&, OptionSet<Flags> = { });
     185
     186    enum class FlagsIncludingPrivate : uint16_t {
     187        Semantic                        = static_cast<uint16_t>(Flags::Semantic),
     188        UseColorFunctionSerialization   = static_cast<uint16_t>(Flags::UseColorFunctionSerialization),
     189        Valid                           = 1 << 2,
     190        Extended                        = 1 << 3,
     191        HashTableEmptyValue             = 1 << 4,
     192        HashTableDeletedValue           = 1 << 5,
     193    };
     194    static OptionSet<FlagsIncludingPrivate> toFlagsIncludingPrivate(OptionSet<Flags> flags) { return OptionSet<FlagsIncludingPrivate>::fromRaw(flags.toRaw()); }
     195
     196    OptionSet<FlagsIncludingPrivate> flags() const;
     197
     198    void setColor(SRGBA<uint8_t>, OptionSet<FlagsIncludingPrivate> = { });
     199    void setExtendedColor(Ref<ExtendedColor>&&, OptionSet<FlagsIncludingPrivate> = { });
     200
     201    PackedColor::RGBA asPackedInline() const;
     202    Ref<ExtendedColor> asExtendedRef() const;
     203
     204#if CPU(ADDRESS64)
     205    static constexpr unsigned maxNumberOfBitsInPointer = 48;
     206#else
     207    static constexpr unsigned maxNumberOfBitsInPointer = 32;
     208#endif
     209    static constexpr uint64_t colorValueMask = (1ULL << maxNumberOfBitsInPointer) - 1;
     210
     211    static uint64_t encodedFlags(OptionSet<FlagsIncludingPrivate>);
     212    static uint64_t encodedInlineColor(SRGBA<uint8_t>);
     213    static uint64_t encodedPackedInlineColor(PackedColor::RGBA);
     214    static uint64_t encodedExtendedColor(Ref<ExtendedColor>&&);
     215
     216    static OptionSet<FlagsIncludingPrivate> decodedFlags(uint64_t);
     217    static SRGBA<uint8_t> decodedInlineColor(uint64_t);
     218    static PackedColor::RGBA decodedPackedInlineColor(uint64_t);
     219    static ExtendedColor& decodedExtendedColor(uint64_t);
     220
     221    static constexpr uint64_t invalidColorAndFlags = 0;
     222    uint64_t m_colorAndFlags { invalidColorAndFlags };
    209223};
    210224
     
    214228// One or both must be extended colors.
    215229bool extendedColorsEqual(const Color&, const Color&);
     230bool extendedColorsEqualIgnoringSemanticColor(const Color&, const Color&);
    216231
    217232#if USE(CG)
     
    225240    if (a.isExtended() || b.isExtended())
    226241        return extendedColorsEqual(a, b);
    227 
    228     return a.m_colorData.inlineColorAndFlags == b.m_colorData.inlineColorAndFlags;
     242    return a.m_colorAndFlags == b.m_colorAndFlags;
    229243}
    230244
     
    237251{
    238252    if (a.isExtended() && b.isExtended())
    239         return a.asExtended() == b.asExtended();
     253        return a.asExtended() == b.asExtended() && a.flags() == b.flags();
    240254
    241255    ASSERT(a.isExtended() || b.isExtended());
     
    243257}
    244258
     259inline bool extendedColorsEqualIgnoringSemanticColor(const Color& a, const Color& b)
     260{
     261    if (a.isExtended() && b.isExtended()) {
     262        auto aFlags = a.flags() - Color::FlagsIncludingPrivate::Semantic;
     263        auto bFlags = b.flags() - Color::FlagsIncludingPrivate::Semantic;
     264        return a.asExtended() == b.asExtended() && aFlags == bFlags;
     265    }
     266
     267    ASSERT(a.isExtended() || b.isExtended());
     268    return false;
     269}
     270
    245271inline bool equalIgnoringSemanticColor(const Color& a, const Color& b)
    246272{
    247273    if (a.isExtended() || b.isExtended())
    248         return extendedColorsEqual(a, b);
    249     return (a.m_colorData.inlineColorAndFlags & ~Color::isSemanticInlineColorBit) == (b.m_colorData.inlineColorAndFlags & ~Color::isSemanticInlineColorBit);
    250 }
    251 
    252 inline Color::Color(SRGBA<uint8_t> color)
    253 {
    254     setColor(color);
    255 }
    256 
    257 inline Color::Color(Optional<SRGBA<uint8_t>> color)
     274        return extendedColorsEqualIgnoringSemanticColor(a, b);
     275
     276    auto aFlags = a.flags() - Color::FlagsIncludingPrivate::Semantic;
     277    auto bFlags = b.flags() - Color::FlagsIncludingPrivate::Semantic;
     278    return a.asPackedInline().value == b.asPackedInline().value && aFlags == bFlags;
     279}
     280
     281inline Color::Color(SRGBA<uint8_t> color, OptionSet<Flags> flags)
     282{
     283    setColor(color, toFlagsIncludingPrivate(flags));
     284}
     285
     286inline Color::Color(Optional<SRGBA<uint8_t>> color, OptionSet<Flags> flags)
    258287{
    259288    if (color)
    260         setColor(*color);
    261 }
    262 
    263 inline Color::Color(SRGBA<uint8_t> color, SemanticTag)
    264 {
    265     setColor(color);
    266     tagAsSemantic();
    267 }
    268 
    269 inline Color::Color(Optional<SRGBA<uint8_t>> color, SemanticTag)
    270 {
    271     if (color) {
    272         setColor(*color);
    273         tagAsSemantic();
    274     }
    275 }
    276 
    277 inline Color::Color(ColorComponents<float> components, ColorSpace colorSpace)
    278 {
    279     setExtendedColor(ExtendedColor::create(components, colorSpace));
     289        setColor(*color, toFlagsIncludingPrivate(flags));
     290}
     291
     292inline Color::Color(ColorComponents<float> components, ColorSpace colorSpace, OptionSet<Flags> flags)
     293{
     294    setExtendedColor(ExtendedColor::create(components, colorSpace), toFlagsIncludingPrivate(flags));
    280295}
    281296
    282297template<typename ColorType, typename std::enable_if_t<IsColorTypeWithComponentType<ColorType, float>>*>
    283 inline Color::Color(const ColorType& color)
    284 {
    285     setExtendedColor(ExtendedColor::create(color));
    286 }
    287 
    288 inline Color::Color(Ref<ExtendedColor>&& extendedColor)
    289 {
    290     setExtendedColor(WTFMove(extendedColor));
     298inline Color::Color(const ColorType& color, OptionSet<Flags> flags)
     299{
     300    setExtendedColor(ExtendedColor::create(color), toFlagsIncludingPrivate(flags));
     301}
     302
     303inline Color::Color(Ref<ExtendedColor>&& extendedColor, OptionSet<Flags> flags)
     304{
     305    setExtendedColor(WTFMove(extendedColor), toFlagsIncludingPrivate(flags));
     306}
     307
     308inline Color::Color(WTF::HashTableEmptyValueType)
     309{
     310    m_colorAndFlags = encodedFlags({ FlagsIncludingPrivate::HashTableEmptyValue });
    291311}
    292312
    293313inline Color::Color(WTF::HashTableDeletedValueType)
    294314{
    295     static_assert(deletedHashValue & invalidInlineColor, "Color's deleted hash value must not look like an ExtendedColor");
    296     static_assert(!(deletedHashValue & validInlineColorBit), "Color's deleted hash value must not look like a valid InlineColor");
    297     static_assert(deletedHashValue & (1 << 4), "Color's deleted hash value must have some bits set that an InlineColor wouldn't have");
    298     m_colorData.inlineColorAndFlags = deletedHashValue;
    299     ASSERT(!isExtended());
    300 }
    301 
    302 inline Color::Color(WTF::HashTableEmptyValueType)
    303 {
    304     static_assert(emptyHashValue & invalidInlineColor, "Color's empty hash value must not look like an ExtendedColor");
    305     static_assert(emptyHashValue & (1 << 4), "Color's deleted hash value must have some bits set that an InlineColor wouldn't have");
    306     m_colorData.inlineColorAndFlags = emptyHashValue;
    307     ASSERT(!isExtended());
     315    m_colorAndFlags = encodedFlags({ FlagsIncludingPrivate::HashTableDeletedValue });
     316}
     317
     318inline bool Color::isHashTableDeletedValue() const
     319{
     320    return flags().contains(FlagsIncludingPrivate::HashTableDeletedValue);
    308321}
    309322
     
    311324{
    312325    if (isExtended())
    313         m_colorData.extendedColor->deref();
     326        asExtended().deref();
    314327}
    315328
     
    317330{
    318331    if (isExtended())
    319         return computeHash(asExtended().components(), asExtended().colorSpace());
    320     return WTF::intHash(m_colorData.inlineColorAndFlags);
     332        return computeHash(asExtended().components(), asExtended().colorSpace(), flags().toRaw());
     333    return computeHash(asPackedInline().value, flags().toRaw());
     334}
     335
     336inline bool Color::isValid() const
     337{
     338    return flags().contains(FlagsIncludingPrivate::Valid);
     339}
     340
     341inline bool Color::isSemantic() const
     342{
     343    return flags().contains(FlagsIncludingPrivate::Semantic);
     344}
     345
     346inline bool Color::usesColorFunctionSerialization() const
     347{
     348    return flags().contains(FlagsIncludingPrivate::UseColorFunctionSerialization);
    321349}
    322350
     
    355383}
    356384
     385inline OptionSet<Color::FlagsIncludingPrivate> Color::flags() const
     386{
     387    return decodedFlags(m_colorAndFlags);
     388}
     389
     390inline bool Color::isExtended() const
     391{
     392    return flags().contains(FlagsIncludingPrivate::Extended);
     393}
     394
     395inline bool Color::isInline() const
     396{
     397    return !flags().contains(FlagsIncludingPrivate::Extended);
     398}
     399
    357400inline const ExtendedColor& Color::asExtended() const
    358401{
    359402    ASSERT(isExtended());
    360     return *m_colorData.extendedColor;
     403    return decodedExtendedColor(m_colorAndFlags);
     404}
     405
     406inline Ref<ExtendedColor> Color::asExtendedRef() const
     407{
     408    ASSERT(isExtended());
     409    return decodedExtendedColor(m_colorAndFlags);
    361410}
    362411
     
    364413{
    365414    ASSERT(isInline());
    366     return asSRGBA(PackedColor::RGBA { static_cast<uint32_t>(m_colorData.inlineColorAndFlags >> 32) });
    367 }
    368 
    369 inline void Color::setColor(SRGBA<uint8_t> color)
    370 {
    371     m_colorData.inlineColorAndFlags = static_cast<uint64_t>(PackedColor::RGBA { color }.value) << 32;
    372     tagAsValid();
    373 }
    374 
    375 inline void Color::setExtendedColor(Ref<ExtendedColor>&& extendedColor)
    376 {
    377     // Zero the union, just in case a 32-bit system only assigns the
    378     // top 32 bits when copying the ExtendedColor pointer below.
    379     m_colorData.inlineColorAndFlags = 0;
    380     m_colorData.extendedColor = &extendedColor.leakRef();
     415    return asSRGBA(asPackedInline());
     416}
     417
     418inline PackedColor::RGBA Color::asPackedInline() const
     419{
     420    ASSERT(isInline());
     421    return decodedPackedInlineColor(m_colorAndFlags);
     422}
     423
     424inline uint64_t Color::encodedFlags(OptionSet<FlagsIncludingPrivate> flags)
     425{
     426    return static_cast<uint64_t>(flags.toRaw()) << maxNumberOfBitsInPointer;
     427}
     428
     429inline uint64_t Color::encodedInlineColor(SRGBA<uint8_t> color)
     430{
     431    return encodedPackedInlineColor(PackedColor::RGBA { color });
     432}
     433
     434inline uint64_t Color::encodedPackedInlineColor(PackedColor::RGBA color)
     435{
     436    return color.value;
     437}
     438
     439inline uint64_t Color::encodedExtendedColor(Ref<ExtendedColor>&& extendedColor)
     440{
     441#if CPU(ADDRESS64)
     442    return bitwise_cast<uint64_t>(&extendedColor.leakRef());
     443#else
     444    return bitwise_cast<uint32_t>(&extendedColor.leakRef());
     445#endif
     446}
     447
     448inline OptionSet<Color::FlagsIncludingPrivate> Color::decodedFlags(uint64_t value)
     449{
     450    return OptionSet<Color::FlagsIncludingPrivate>::fromRaw(static_cast<unsigned>(value >> maxNumberOfBitsInPointer));
     451}
     452
     453inline SRGBA<uint8_t> Color::decodedInlineColor(uint64_t value)
     454{
     455    return asSRGBA(decodedPackedInlineColor(value));
     456}
     457
     458inline PackedColor::RGBA Color::decodedPackedInlineColor(uint64_t value)
     459{
     460    return PackedColor::RGBA { static_cast<uint32_t>(value & colorValueMask) };
     461}
     462
     463inline ExtendedColor& Color::decodedExtendedColor(uint64_t value)
     464{
     465#if CPU(ADDRESS64)
     466    return *bitwise_cast<ExtendedColor*>(value & colorValueMask);
     467#else
     468    return *bitwise_cast<ExtendedColor*>(static_cast<uint32_t>(value & colorValueMask));
     469#endif
     470}
     471
     472inline void Color::setColor(SRGBA<uint8_t> color, OptionSet<FlagsIncludingPrivate> flags)
     473{
     474    flags.add({ FlagsIncludingPrivate::Valid });
     475    m_colorAndFlags = encodedInlineColor(color) | encodedFlags(flags);
     476    ASSERT(isInline());
     477}
     478
     479inline void Color::setExtendedColor(Ref<ExtendedColor>&& color, OptionSet<FlagsIncludingPrivate> flags)
     480{
     481    flags.add({ FlagsIncludingPrivate::Valid, FlagsIncludingPrivate::Extended });
     482    m_colorAndFlags = encodedExtendedColor(WTFMove(color)) | encodedFlags(flags);
    381483    ASSERT(isExtended());
    382484}
     
    398500template<class Encoder> void Color::encode(Encoder& encoder) const
    399501{
     502    if (!isValid()) {
     503        encoder << false;
     504        return;
     505    }
     506    encoder << true;
     507
     508    encoder << flags().contains(FlagsIncludingPrivate::Semantic);
     509    encoder << flags().contains(FlagsIncludingPrivate::UseColorFunctionSerialization);
     510
    400511    if (isExtended()) {
    401512        encoder << true;
     
    410521        return;
    411522    }
    412 
    413523    encoder << false;
    414524
    415     if (!isValid()) {
    416         encoder << false;
    417         return;
    418     }
    419 
    420     // FIXME: This should encode whether the color is semantic.
    421 
    422     encoder << true;
    423     encoder << PackedColor::RGBA { asInline() }.value;
     525    encoder << asPackedInline().value;
    424526}
    425527
    426528template<class Decoder> Optional<Color> Color::decode(Decoder& decoder)
    427529{
     530    bool isValid;
     531    if (!decoder.decode(isValid))
     532        return WTF::nullopt;
     533
     534    if (!isValid)
     535        return Color { };
     536
     537    OptionSet<Flags> flags;
     538
     539    bool isSemantic;
     540    if (!decoder.decode(isSemantic))
     541        return WTF::nullopt;
     542
     543    if (isSemantic)
     544        flags.add(Flags::Semantic);
     545
     546    bool usesColorFunctionSerialization;
     547    if (!decoder.decode(usesColorFunctionSerialization))
     548        return WTF::nullopt;
     549
     550    if (usesColorFunctionSerialization)
     551        flags.add(Flags::UseColorFunctionSerialization);
     552
    428553    bool isExtended;
    429554    if (!decoder.decode(isExtended))
     
    446571        if (!decoder.decode(colorSpace))
    447572            return WTF::nullopt;
    448         return Color { ExtendedColor::create({ c1, c2, c3, alpha }, colorSpace) };
     573        return Color { ExtendedColor::create({ c1, c2, c3, alpha }, colorSpace), flags };
    449574    }
    450 
    451     bool isValid;
    452     if (!decoder.decode(isValid))
    453         return WTF::nullopt;
    454 
    455     if (!isValid)
    456         return Color { };
    457575
    458576    uint32_t value;
     
    460578        return WTF::nullopt;
    461579
    462     return Color { asSRGBA(PackedColor::RGBA { value }) };
     580    return Color { asSRGBA(PackedColor::RGBA { value }), flags };
    463581}
    464582
  • trunk/Source/WebCore/platform/graphics/ColorBlending.cpp

    r271695 r273211  
    8787    // FIXME: Why is preserving the semantic bit desired and/or correct here?
    8888    if (color.isSemantic())
    89         return Color(result, Color::Semantic);
     89        return { result, Color::Flags::Semantic };
    9090    return result;
    9191}
  • trunk/Source/WebCore/platform/graphics/ColorSerialization.cpp

    r273078 r273211  
    3737namespace WebCore {
    3838
    39 static String serializationForCSS(const A98RGB<float>&);
    40 static String serializationForHTML(const A98RGB<float>&);
    41 static String serializationForRenderTreeAsText(const A98RGB<float>&);
    42 
    43 static String serializationForCSS(const DisplayP3<float>&);
    44 static String serializationForHTML(const DisplayP3<float>&);
    45 static String serializationForRenderTreeAsText(const DisplayP3<float>&);
    46 
    47 static String serializationForCSS(const LCHA<float>&);
    48 static String serializationForHTML(const LCHA<float>&);
    49 static String serializationForRenderTreeAsText(const LCHA<float>&);
    50 
    51 static String serializationForCSS(const Lab<float>&);
    52 static String serializationForHTML(const Lab<float>&);
    53 static String serializationForRenderTreeAsText(const Lab<float>&);
    54 
    55 static String serializationForCSS(const LinearSRGBA<float>&);
    56 static String serializationForHTML(const LinearSRGBA<float>&);
    57 static String serializationForRenderTreeAsText(const LinearSRGBA<float>&);
    58 
    59 static String serializationForCSS(const ProPhotoRGB<float>&);
    60 static String serializationForHTML(const ProPhotoRGB<float>&);
    61 static String serializationForRenderTreeAsText(const ProPhotoRGB<float>&);
    62 
    63 static String serializationForCSS(const Rec2020<float>&);
    64 static String serializationForHTML(const Rec2020<float>&);
    65 static String serializationForRenderTreeAsText(const Rec2020<float>&);
    66 
    67 static String serializationForCSS(const SRGBA<float>&);
    68 static String serializationForHTML(const SRGBA<float>&);
    69 static String serializationForRenderTreeAsText(const SRGBA<float>&);
    70 
    71 static String serializationForCSS(SRGBA<uint8_t>);
    72 static String serializationForHTML(SRGBA<uint8_t>);
    73 static String serializationForRenderTreeAsText(SRGBA<uint8_t>);
    74 
    75 static String serializationForCSS(const XYZA<float, WhitePoint::D50>&);
    76 static String serializationForHTML(const XYZA<float, WhitePoint::D50>&);
    77 static String serializationForRenderTreeAsText(const XYZA<float, WhitePoint::D50>&);
     39static String serializationForCSS(const A98RGB<float>&, bool useColorFunctionSerialization);
     40static String serializationForHTML(const A98RGB<float>&, bool useColorFunctionSerialization);
     41static String serializationForRenderTreeAsText(const A98RGB<float>&, bool useColorFunctionSerialization);
     42
     43static String serializationForCSS(const DisplayP3<float>&, bool useColorFunctionSerialization);
     44static String serializationForHTML(const DisplayP3<float>&, bool useColorFunctionSerialization);
     45static String serializationForRenderTreeAsText(const DisplayP3<float>&, bool useColorFunctionSerialization);
     46
     47static String serializationForCSS(const LCHA<float>&, bool useColorFunctionSerialization);
     48static String serializationForHTML(const LCHA<float>&, bool useColorFunctionSerialization);
     49static String serializationForRenderTreeAsText(const LCHA<float>&, bool useColorFunctionSerialization);
     50
     51static String serializationForCSS(const Lab<float>&, bool useColorFunctionSerialization);
     52static String serializationForHTML(const Lab<float>&, bool useColorFunctionSerialization);
     53static String serializationForRenderTreeAsText(const Lab<float>&, bool useColorFunctionSerialization);
     54
     55static String serializationForCSS(const LinearSRGBA<float>&, bool useColorFunctionSerialization);
     56static String serializationForHTML(const LinearSRGBA<float>&, bool useColorFunctionSerialization);
     57static String serializationForRenderTreeAsText(const LinearSRGBA<float>&, bool useColorFunctionSerialization);
     58
     59static String serializationForCSS(const ProPhotoRGB<float>&, bool useColorFunctionSerialization);
     60static String serializationForHTML(const ProPhotoRGB<float>&, bool useColorFunctionSerialization);
     61static String serializationForRenderTreeAsText(const ProPhotoRGB<float>&, bool useColorFunctionSerialization);
     62
     63static String serializationForCSS(const Rec2020<float>&, bool useColorFunctionSerialization);
     64static String serializationForHTML(const Rec2020<float>&, bool useColorFunctionSerialization);
     65static String serializationForRenderTreeAsText(const Rec2020<float>&, bool useColorFunctionSerialization);
     66
     67static String serializationForCSS(const SRGBA<float>&, bool useColorFunctionSerialization);
     68static String serializationForHTML(const SRGBA<float>&, bool useColorFunctionSerialization);
     69static String serializationForRenderTreeAsText(const SRGBA<float>&, bool useColorFunctionSerialization);
     70
     71static String serializationForCSS(SRGBA<uint8_t>, bool useColorFunctionSerialization);
     72static String serializationForHTML(SRGBA<uint8_t>, bool useColorFunctionSerialization);
     73static String serializationForRenderTreeAsText(SRGBA<uint8_t>, bool useColorFunctionSerialization);
     74
     75static String serializationForCSS(const XYZA<float, WhitePoint::D50>&, bool useColorFunctionSerialization);
     76static String serializationForHTML(const XYZA<float, WhitePoint::D50>&, bool useColorFunctionSerialization);
     77static String serializationForRenderTreeAsText(const XYZA<float, WhitePoint::D50>&, bool useColorFunctionSerialization);
    7878
    7979
    8080String serializationForCSS(const Color& color)
    8181{
    82     return color.callOnUnderlyingType([] (auto underlyingColor) {
    83         return serializationForCSS(underlyingColor);
     82    return color.callOnUnderlyingType([&] (auto underlyingColor) {
     83        return serializationForCSS(underlyingColor, color.usesColorFunctionSerialization());
    8484    });
    8585}
     
    8787String serializationForHTML(const Color& color)
    8888{
    89     return color.callOnUnderlyingType([] (auto underlyingColor) {
    90         return serializationForHTML(underlyingColor);
     89    return color.callOnUnderlyingType([&] (auto underlyingColor) {
     90        return serializationForHTML(underlyingColor, color.usesColorFunctionSerialization());
    9191    });
    9292}
     
    9494String serializationForRenderTreeAsText(const Color& color)
    9595{
    96     return color.callOnUnderlyingType([] (auto underlyingColor) {
    97         return serializationForRenderTreeAsText(underlyingColor);
     96    return color.callOnUnderlyingType([&] (auto underlyingColor) {
     97        return serializationForRenderTreeAsText(underlyingColor, color.usesColorFunctionSerialization());
    9898    });
    9999}
     
    126126}
    127127
    128 template<typename ColorType> static String serialization(const ColorType& color)
    129 {
     128template<typename ColorType> static String serializationUsingColorFunction(const ColorType& color)
     129{
     130    static_assert(std::is_same_v<typename ColorType::ComponentType, float>);
     131
    130132    auto [c1, c2, c3, alpha] = color;
    131133    if (WTF::areEssentiallyEqual(alpha, 1.0f))
     
    134136}
    135137
     138static String serializationUsingColorFunction(const Lab<float>& color)
     139{
     140    auto [c1, c2, c3, alpha] = color;
     141    if (WTF::areEssentiallyEqual(alpha, 1.0f))
     142        return makeString("color(", serialization(ColorSpaceFor<Lab<float>>), ' ', c1, "% ", c2, ' ', c3, ')');
     143    return makeString("color(", serialization(ColorSpaceFor<Lab<float>>), ' ', c1, "% ", c2, ' ', c3, " / ", alpha, ')');
     144}
     145
     146static String serializationUsingColorFunction(const SRGBA<uint8_t>& color)
     147{
     148    return serializationUsingColorFunction(convertColor<SRGBA<float>>(color));
     149}
     150
    136151// MARK: A98RGB<float> overloads
    137152
    138 String serializationForCSS(const A98RGB<float>& color)
    139 {
    140     return serialization(color);
    141 }
    142 
    143 String serializationForHTML(const A98RGB<float>& color)
    144 {
    145     return serialization(color);
    146 }
    147 
    148 String serializationForRenderTreeAsText(const A98RGB<float>& color)
    149 {
    150     return serialization(color);
     153String serializationForCSS(const A98RGB<float>& color, bool)
     154{
     155    return serializationUsingColorFunction(color);
     156}
     157
     158String serializationForHTML(const A98RGB<float>& color, bool)
     159{
     160    return serializationUsingColorFunction(color);
     161}
     162
     163String serializationForRenderTreeAsText(const A98RGB<float>& color, bool)
     164{
     165    return serializationUsingColorFunction(color);
    151166}
    152167
    153168// MARK: DisplayP3<float> overloads
    154169
    155 String serializationForCSS(const DisplayP3<float>& color)
    156 {
    157     return serialization(color);
    158 }
    159 
    160 String serializationForHTML(const DisplayP3<float>& color)
    161 {
    162     return serialization(color);
    163 }
    164 
    165 String serializationForRenderTreeAsText(const DisplayP3<float>& color)
    166 {
    167     return serialization(color);
     170String serializationForCSS(const DisplayP3<float>& color, bool)
     171{
     172    return serializationUsingColorFunction(color);
     173}
     174
     175String serializationForHTML(const DisplayP3<float>& color, bool)
     176{
     177    return serializationUsingColorFunction(color);
     178}
     179
     180String serializationForRenderTreeAsText(const DisplayP3<float>& color, bool)
     181{
     182    return serializationUsingColorFunction(color);
    168183}
    169184
    170185// MARK: LCHA<float> overloads
    171186
    172 String serializationForCSS(const LCHA<float>& color)
     187String serializationForCSS(const LCHA<float>& color, bool useColorFunctionSerialization)
    173188{
    174189    // https://www.w3.org/TR/css-color-4/#serializing-lab-lch
     190    if (useColorFunctionSerialization)
     191        return serializationUsingColorFunction(color);
    175192
    176193    auto [c1, c2, c3, alpha] = color;
     
    180197}
    181198
    182 String serializationForHTML(const LCHA<float>& color)
    183 {
    184     return serializationForCSS(color);
    185 }
    186 
    187 String serializationForRenderTreeAsText(const LCHA<float>& color)
    188 {
    189     return serializationForCSS(color);
     199String serializationForHTML(const LCHA<float>& color, bool useColorFunctionSerialization)
     200{
     201    return serializationForCSS(color, useColorFunctionSerialization);
     202}
     203
     204String serializationForRenderTreeAsText(const LCHA<float>& color, bool useColorFunctionSerialization)
     205{
     206    return serializationForCSS(color, useColorFunctionSerialization);
    190207}
    191208
    192209// MARK: Lab<float> overloads
    193210
    194 String serializationForCSS(const Lab<float>& color)
     211String serializationForCSS(const Lab<float>& color, bool useColorFunctionSerialization)
    195212{
    196213    // https://www.w3.org/TR/css-color-4/#serializing-lab-lch
     214    if (useColorFunctionSerialization)
     215        return serializationUsingColorFunction(color);
    197216
    198217    auto [c1, c2, c3, alpha] = color;
     
    202221}
    203222
    204 String serializationForHTML(const Lab<float>& color)
    205 {
    206     return serializationForCSS(color);
    207 }
    208 
    209 String serializationForRenderTreeAsText(const Lab<float>& color)
    210 {
    211     return serializationForCSS(color);
     223String serializationForHTML(const Lab<float>& color, bool useColorFunctionSerialization)
     224{
     225    return serializationForCSS(color, useColorFunctionSerialization);
     226}
     227
     228String serializationForRenderTreeAsText(const Lab<float>& color, bool useColorFunctionSerialization)
     229{
     230    return serializationForCSS(color, useColorFunctionSerialization);
    212231}
    213232
    214233// MARK: LinearSRGBA<float> overloads
    215234
    216 String serializationForCSS(const LinearSRGBA<float>& color)
    217 {
    218     return serialization(color);
    219 }
    220 
    221 String serializationForHTML(const LinearSRGBA<float>& color)
    222 {
    223     return serialization(color);
    224 }
    225 
    226 String serializationForRenderTreeAsText(const LinearSRGBA<float>& color)
    227 {
    228     return serialization(color);
     235String serializationForCSS(const LinearSRGBA<float>& color, bool)
     236{
     237    return serializationUsingColorFunction(color);
     238}
     239
     240String serializationForHTML(const LinearSRGBA<float>& color, bool)
     241{
     242    return serializationUsingColorFunction(color);
     243}
     244
     245String serializationForRenderTreeAsText(const LinearSRGBA<float>& color, bool)
     246{
     247    return serializationUsingColorFunction(color);
    229248}
    230249
    231250// MARK: ProPhotoRGB<float> overloads
    232251
    233 String serializationForCSS(const ProPhotoRGB<float>& color)
    234 {
    235     return serialization(color);
    236 }
    237 
    238 String serializationForHTML(const ProPhotoRGB<float>& color)
    239 {
    240     return serialization(color);
    241 }
    242 
    243 String serializationForRenderTreeAsText(const ProPhotoRGB<float>& color)
    244 {
    245     return serialization(color);
     252String serializationForCSS(const ProPhotoRGB<float>& color, bool)
     253{
     254    return serializationUsingColorFunction(color);
     255}
     256
     257String serializationForHTML(const ProPhotoRGB<float>& color, bool)
     258{
     259    return serializationUsingColorFunction(color);
     260}
     261
     262String serializationForRenderTreeAsText(const ProPhotoRGB<float>& color, bool)
     263{
     264    return serializationUsingColorFunction(color);
    246265}
    247266
    248267// MARK: Rec2020<float> overloads
    249268
    250 String serializationForCSS(const Rec2020<float>& color)
    251 {
    252     return serialization(color);
    253 }
    254 
    255 String serializationForHTML(const Rec2020<float>& color)
    256 {
    257     return serialization(color);
    258 }
    259 
    260 String serializationForRenderTreeAsText(const Rec2020<float>& color)
    261 {
    262     return serialization(color);
     269String serializationForCSS(const Rec2020<float>& color, bool)
     270{
     271    return serializationUsingColorFunction(color);
     272}
     273
     274String serializationForHTML(const Rec2020<float>& color, bool)
     275{
     276    return serializationUsingColorFunction(color);
     277}
     278
     279String serializationForRenderTreeAsText(const Rec2020<float>& color, bool)
     280{
     281    return serializationUsingColorFunction(color);
    263282}
    264283
    265284// MARK: SRGBA<float> overloads
    266285
    267 String serializationForCSS(const SRGBA<float>& color)
    268 {
    269     return serialization(color);
    270 }
    271 
    272 String serializationForHTML(const SRGBA<float>& color)
    273 {
    274     return serialization(color);
    275 }
    276 
    277 String serializationForRenderTreeAsText(const SRGBA<float>& color)
    278 {
    279     return serialization(color);
     286String serializationForCSS(const SRGBA<float>& color, bool)
     287{
     288    return serializationUsingColorFunction(color);
     289}
     290
     291String serializationForHTML(const SRGBA<float>& color, bool)
     292{
     293    return serializationUsingColorFunction(color);
     294}
     295
     296String serializationForRenderTreeAsText(const SRGBA<float>& color, bool)
     297{
     298    return serializationUsingColorFunction(color);
    280299}
    281300
     
    299318}
    300319
    301 String serializationForCSS(SRGBA<uint8_t> color)
    302 {
     320String serializationForCSS(SRGBA<uint8_t> color, bool useColorFunctionSerialization)
     321{
     322    if (useColorFunctionSerialization)
     323        return serializationUsingColorFunction(color);
     324
    303325    auto [red, green, blue, alpha] = color;
    304326    switch (alpha) {
     
    312334}
    313335
    314 String serializationForHTML(SRGBA<uint8_t> color)
    315 {
     336String serializationForHTML(SRGBA<uint8_t> color, bool useColorFunctionSerialization)
     337{
     338    if (useColorFunctionSerialization)
     339        return serializationUsingColorFunction(color);
     340
    316341    auto [red, green, blue, alpha] = color;
    317342    if (alpha == 0xFF)
     
    320345}
    321346
    322 String serializationForRenderTreeAsText(SRGBA<uint8_t> color)
    323 {
     347String serializationForRenderTreeAsText(SRGBA<uint8_t> color, bool useColorFunctionSerialization)
     348{
     349    if (useColorFunctionSerialization)
     350        return serializationUsingColorFunction(color);
     351
    324352    auto [red, green, blue, alpha] = color;
    325353    if (alpha < 0xFF)
     
    330358// MARK: XYZA<float, WhitePoint::D50> overloads
    331359
    332 String serializationForCSS(const XYZA<float, WhitePoint::D50>& color)
    333 {
    334     return serialization(color);
    335 }
    336 
    337 String serializationForHTML(const XYZA<float, WhitePoint::D50>& color)
    338 {
    339     return serialization(color);
    340 }
    341 
    342 String serializationForRenderTreeAsText(const XYZA<float, WhitePoint::D50>& color)
    343 {
    344     return serialization(color);
    345 }
    346 
    347 }
     360String serializationForCSS(const XYZA<float, WhitePoint::D50>& color, bool)
     361{
     362    return serializationUsingColorFunction(color);
     363}
     364
     365String serializationForHTML(const XYZA<float, WhitePoint::D50>& color, bool)
     366{
     367    return serializationUsingColorFunction(color);
     368}
     369
     370String serializationForRenderTreeAsText(const XYZA<float, WhitePoint::D50>& color, bool)
     371{
     372    return serializationUsingColorFunction(color);
     373}
     374
     375}
  • trunk/Source/WebCore/platform/graphics/ColorUtilities.h

    r273078 r273211  
    5353template<typename ColorType, typename Functor> ColorType colorByModifingEachNonAlphaComponent(const ColorType&, Functor&&);
    5454
    55 template<typename ColorType> constexpr ColorType colorWithOverridenAlpha(const ColorType&, uint8_t overrideAlpha);
    56 template<typename ColorType> ColorType colorWithOverridenAlpha(const ColorType&, float overrideAlpha);
    57 
    58 template<typename ColorType> constexpr ColorType invertedColorWithOverridenAlpha(const ColorType&, uint8_t overrideAlpha);
    59 template<typename ColorType> ColorType invertedColorWithOverridenAlpha(const ColorType&, float overrideAlpha);
     55template<typename ColorType> constexpr ColorType colorWithOverriddenAlpha(const ColorType&, uint8_t overrideAlpha);
     56template<typename ColorType> ColorType colorWithOverriddenAlpha(const ColorType&, float overrideAlpha);
     57
     58template<typename ColorType> constexpr ColorType invertedcolorWithOverriddenAlpha(const ColorType&, uint8_t overrideAlpha);
     59template<typename ColorType> ColorType invertedcolorWithOverriddenAlpha(const ColorType&, float overrideAlpha);
    6060
    6161template<typename ColorType, typename std::enable_if_t<std::is_same_v<typename ColorType::Model, RGBModel<typename ColorType::ComponentType>>>* = nullptr> constexpr bool isBlack(const ColorType&);
     
    108108}
    109109
    110 template<typename ColorType> constexpr ColorType colorWithOverridenAlpha(const ColorType& color, uint8_t overrideAlpha)
     110template<typename ColorType> constexpr ColorType colorWithOverriddenAlpha(const ColorType& color, uint8_t overrideAlpha)
    111111{
    112112    auto copy = color;
     
    115115}
    116116
    117 template<typename ColorType> ColorType colorWithOverridenAlpha(const ColorType& color, float overrideAlpha)
     117template<typename ColorType> ColorType colorWithOverriddenAlpha(const ColorType& color, float overrideAlpha)
    118118{
    119119    auto copy = color;
     
    122122}
    123123
    124 template<typename ColorType> constexpr ColorType invertedColorWithOverridenAlpha(const ColorType& color, uint8_t overrideAlpha)
     124template<typename ColorType> constexpr ColorType invertedcolorWithOverriddenAlpha(const ColorType& color, uint8_t overrideAlpha)
    125125{
    126126    static_assert(ColorType::Model::isInvertible);
     
    136136}
    137137
    138 template<typename ColorType> ColorType invertedColorWithOverridenAlpha(const ColorType& color, float overrideAlpha)
     138template<typename ColorType> ColorType invertedcolorWithOverriddenAlpha(const ColorType& color, float overrideAlpha)
    139139{
    140140    static_assert(ColorType::Model::isInvertible);
  • trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp

    r272736 r273211  
    9090}
    9191
    92 Color::Color(CGColorRef color, SemanticTag tag)
    93     : Color(roundAndClampToSRGBALossy(color), tag)
     92Color::Color(CGColorRef color, OptionSet<Flags> flags)
     93    : Color(roundAndClampToSRGBALossy(color), flags)
    9494{
    9595}
  • trunk/Source/WebCore/platform/graphics/mac/ColorMac.mm

    r272731 r273211  
    109109Color semanticColorFromNSColor(NSColor *color)
    110110{
    111     return Color(makeSimpleColorFromNSColor(color), Color::Semantic);
     111    return Color(makeSimpleColorFromNSColor(color), Color::Flags::Semantic);
    112112}
    113113
  • trunk/Source/WebCore/rendering/RenderThemeIOS.mm

    r273014 r273211  
    13921392{
    13931393    if (auto color = wtfObjCMsgSend<UIColor *>(PAL::getUIColorClass(), idAndSelector.selector))
    1394         return Color { color.CGColor, Color::Semantic };
     1394        return Color { color.CGColor, Color::Flags::Semantic };
    13951395    return WTF::nullopt;
    13961396}
     
    14101410    if (auto selector = cssColorToSelector()) {
    14111411        if (auto color = wtfObjCMsgSend<UIColor *>(PAL::getUIColorClass(), selector))
    1412             return Color(color.CGColor, Color::Semantic);
     1412            return Color { color.CGColor, Color::Flags::Semantic };
    14131413    }
    14141414    return WTF::nullopt;
  • trunk/Source/WebCore/rendering/RenderThemeMac.mm

    r272805 r273211  
    730730            // Hardcoded to avoid exposing a user appearance preference to the web for fingerprinting.
    731731            if (localAppearance.usingDarkAppearance())
    732                 return { SRGBA<uint8_t> { 26, 169, 255 }, Color::Semantic };
    733             return { SRGBA<uint8_t> { 0, 103, 244 }, Color::Semantic };
     732                return { SRGBA<uint8_t> { 26, 169, 255 }, Color::Flags::Semantic };
     733            return { SRGBA<uint8_t> { 0, 103, 244 }, Color::Flags::Semantic };
    734734
    735735        case CSSValueAppleSystemControlAccent:
    736736            // Hardcoded to avoid exposing a user appearance preference to the web for fingerprinting.
    737737            // Same color in light and dark appearances.
    738             return { SRGBA<uint8_t> { 0, 122, 255 }, Color::Semantic };
     738            return { SRGBA<uint8_t> { 0, 122, 255 }, Color::Flags::Semantic };
    739739
    740740        case CSSValueAppleSystemSelectedContentBackground:
    741741            // Hardcoded to avoid exposing a user appearance preference to the web for fingerprinting.
    742742            if (localAppearance.usingDarkAppearance())
    743                 return { SRGBA<uint8_t> { 0, 88, 208 }, Color::Semantic };
    744             return { SRGBA<uint8_t> { 0, 99, 225 }, Color::Semantic };
     743                return { SRGBA<uint8_t> { 0, 88, 208 }, Color::Flags::Semantic };
     744            return { SRGBA<uint8_t> { 0, 99, 225 }, Color::Flags::Semantic };
    745745
    746746        case CSSValueHighlight:
     
    748748            // Hardcoded to avoid exposing a user appearance preference to the web for fingerprinting.
    749749            if (localAppearance.usingDarkAppearance())
    750                 return { SRGBA<uint8_t> { 63, 99, 139, 204 }, Color::Semantic };
    751             return { SRGBA<uint8_t> { 128, 188, 254, 153 }, Color::Semantic };
     750                return { SRGBA<uint8_t> { 63, 99, 139, 204 }, Color::Flags::Semantic };
     751            return { SRGBA<uint8_t> { 128, 188, 254, 153 }, Color::Flags::Semantic };
    752752
    753753#if !HAVE(OS_DARK_MODE_SUPPORT)
Note: See TracChangeset for help on using the changeset viewer.