Title: [262108] trunk
Revision
262108
Author
[email protected]
Date
2020-05-24 08:53:19 -0700 (Sun, 24 May 2020)

Log Message

Extended Color Cleanup: Stop allowing direct access to the underlying SimpleColor (it is almost always incorrect with respect to extended colors)
https://bugs.webkit.org/show_bug.cgi?id=212184

Reviewed by Dean Jackson.

Source/WebCore:

- Makes Color::rgb() private, removing a class of extended color bugs from users
  of the Color class. To get the equivilent functionality, users of the class must
  now use toSRGBASimpleColorLossy() which does actually does the conversion to sRGB
  if necessary and makes it clear to the caller that precision is being lost.
- Removes Color::red()/green()/blue() entirely. They were just calling down to
  Color::rgb(), and going forward, it won't make sense to think about rgb components
  of Colors in general, since some extended color spaces don't deal in them (e.g. Lab)
  Color::alpha() was kept (and fixed to work even with ExtendedColor) since all
  ExtendedColors do need to have alpha.

* accessibility/AccessibilityNodeObject.cpp:
(WebCore::AccessibilityNodeObject::colorValue const):
Use toSRGBASimpleColorLossy() to get access to color components.

* accessibility/atk/WebKitAccessibleInterfaceText.cpp:
(getAttributeSetForAccessibilityObject):
Use toSRGBASimpleColorLossy() to get access to color components.

* accessibility/isolatedtree/AXIsolatedObject.cpp:
(WebCore::AXIsolatedObject::colorValue const):
Use toSRGBASimpleColorLossy() to get access to color components.

* css/DeprecatedCSSOMRGBColor.h:
Use toSRGBASimpleColorLossy() to get access to color components.

* page/CaptionUserPreferencesMediaAF.cpp:
(WebCore::CaptionUserPreferencesMediaAF::captionsWindowCSS const):
(WebCore::CaptionUserPreferencesMediaAF::captionsBackgroundCSS const):
(WebCore::CaptionUserPreferencesMediaAF::captionsTextColor const):
User Color::colorWithAlpha() to avoid the need to muck with components directly.

* platform/graphics/Color.cpp:
(WebCore::differenceSquared):
Use rgb() directly, which is ok, since this is explicitly checking isExtended().
This code is still wrong (there is a FIXME) as it assumes the two colors are in
the same color space.

(WebCore::Color::Color):
Add constructor which takes an ExtendedColor to allow functions like
Color::invertedColorWithAlpha to delegate their functionality to ExtendedColor.

(WebCore::Color::light const):
Use new SimpleColor::colorWithAlpha() to avoid hardcoding constants here.

(WebCore::Color::blend const):
(WebCore::Color::blendWithWhite const):
Use toSRGBASimpleColorLossy() to get access to color components. These
are still not ideal implementations, as they don't preserve extended colors
as well as they could, but now they don't return bogus values for extended
colors. Minor cleanup bringing constants and lambda inside the function they
are used in.

(WebCore::Color::colorWithAlpha const):
(WebCore::Color::colorWithAlphaUsingAlternativeRounding const):
Minor cleanups to use a more consistent style and make use of the new
SimpleColor::colorWithAlpha.

(WebCore::Color::invertedColorWithAlpha const):
Added. Used to avoid direct component usage in line box code.

(WebCore::Color::semanticColor const):
Added. Hopefully temporary. Used by RenderThemeIOS.mm to convert
a Color from a map into a Color with the semantic bit set. This
should not be necessary as every color in the map should already
have it set, but to avoid uncessary possible behavior changes this
preserves that functionality until it can be researched further.
Fixing coders to preserve the semantic bit may be required to
elliminate the need.

(WebCore::Color::colorSpaceAndComponents const):
Use rgb() rather than the individual components which have been removed.

* platform/graphics/Color.h:
(WebCore::SimpleColor::alphaComponentAsFloat const):
Added. Needed by DeprecatedCSSOMRGBColor and useful to Color.

(WebCore::SimpleColor::colorWithAlpha const):
Useful to simplify Color::colorWithAlpha implementations and
in Color::dark().

(WebCore::SimpleColor::get const):
Added tuple interface to SimpleColor to support structure bindings.
NOTE: Unlike the storage of SimpleColor (ARGB), this produces the
bindings in the more familiar [r,g,b,a] to match FloatComponents.

(WebCore::Color::alpha const):
Made work with ExtendedColor as well.

(WebCore::Color::red const): Deleted.
(WebCore::Color::green const): Deleted.
(WebCore::Color::blue const): Deleted.
Removed.

(CGColorRef cachedCGColor):
(int differenceSquared):
Made friends so they could use Color::rgb().

(WebCore::Color::rgb const):
Made private.

* platform/graphics/ExtendedColor.cpp:
(WebCore::ExtendedColor::invertedColorWithAlpha const):
* platform/graphics/ExtendedColor.h:
Added invertedColorWithAlpha to allow inversion to be encapsulated.
When future color spaces are added, we may need to choose per-colorspace
algorithms for this instead of the trivial one used today.

* platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm:
(WebCore::PlatformCAAnimationCocoa::setFromValue):
(WebCore::PlatformCAAnimationCocoa::setToValue):
(WebCore::PlatformCAAnimationCocoa::setValues):
Use toSRGBASimpleColorLossy() to get access to color components.

* platform/graphics/ca/win/PlatformCAAnimationWin.cpp:
(PlatformCAAnimationWin::setFromValue):
(PlatformCAAnimationWin::setToValue):
(PlatformCAAnimationWin::setValues):
Use toSRGBASimpleColorLossy() to get access to color components.

* platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::drawFocusRing):
Use Color::colorWithAlpha() to avoid needing access to components.

* platform/graphics/cpu/arm/filters/FELightingNEON.h:
(WebCore::FELighting::platformApplyNeon):
Use toSRGBASimpleColorLossy() to get access to color components.

* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::TextureMapperGL::clearColor):
Use toSRGBASimpleColorLossy() to get access to color components.

* platform/graphics/win/Direct2DOperations.cpp:
(WebCore::Direct2D::drawGlyphs):
Use colorWithAlphaMultipliedBy() to avoid needing access to components.

* platform/graphics/win/FontCGWin.cpp:
(WebCore::FontCascade::drawGlyphs):
Use colorWithAlphaMultipliedBy() to avoid needing access to components.

* platform/graphics/win/FontCascadeDirect2D.cpp:
(WebCore::FontCascade::drawGlyphs):
Use colorWithAlphaMultipliedBy() to avoid needing access to components.

* rendering/EllipsisBox.cpp:
(WebCore::EllipsisBox::paintSelection):
Use invertedColorWithAlpha() to avoid needing access to components.

* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::resolveStyleForMarkedText):
Use invertedColorWithAlpha() to avoid needing access to components.

* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintBoxShadow):
Use opaqueColor() to avoid needing access to components.

* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::systemColor const):
Use opaqueColor() to avoid needing access to components.

* svg/properties/SVGAnimationAdditiveValueFunctionImpl.h:
(WebCore::SVGAnimationColorFunction::animate):
Use toSRGBASimpleColorLossy() to get access to color components.

Source/WebKit:

* WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm:
(WebKit::animationValueFromKeyframeValue):
Use toSRGBASimpleColorLossy() to get access to color components.

Tools:

* TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
(TestWebKitAPI::TEST):
Use toSRGBASimpleColorLossy() to get access to color components.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (262107 => 262108)


--- trunk/Source/WebCore/ChangeLog	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/ChangeLog	2020-05-24 15:53:19 UTC (rev 262108)
@@ -1,3 +1,173 @@
+2020-05-24  Sam Weinig  <[email protected]>
+
+        Extended Color Cleanup: Stop allowing direct access to the underlying SimpleColor (it is almost always incorrect with respect to extended colors)
+        https://bugs.webkit.org/show_bug.cgi?id=212184
+
+        Reviewed by Dean Jackson.
+
+        - Makes Color::rgb() private, removing a class of extended color bugs from users 
+          of the Color class. To get the equivilent functionality, users of the class must
+          now use toSRGBASimpleColorLossy() which does actually does the conversion to sRGB
+          if necessary and makes it clear to the caller that precision is being lost. 
+        - Removes Color::red()/green()/blue() entirely. They were just calling down to 
+          Color::rgb(), and going forward, it won't make sense to think about rgb components
+          of Colors in general, since some extended color spaces don't deal in them (e.g. Lab)
+          Color::alpha() was kept (and fixed to work even with ExtendedColor) since all
+          ExtendedColors do need to have alpha.
+
+        * accessibility/AccessibilityNodeObject.cpp:
+        (WebCore::AccessibilityNodeObject::colorValue const):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * accessibility/atk/WebKitAccessibleInterfaceText.cpp:
+        (getAttributeSetForAccessibilityObject):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * accessibility/isolatedtree/AXIsolatedObject.cpp:
+        (WebCore::AXIsolatedObject::colorValue const):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * css/DeprecatedCSSOMRGBColor.h:
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * page/CaptionUserPreferencesMediaAF.cpp:
+        (WebCore::CaptionUserPreferencesMediaAF::captionsWindowCSS const):
+        (WebCore::CaptionUserPreferencesMediaAF::captionsBackgroundCSS const):
+        (WebCore::CaptionUserPreferencesMediaAF::captionsTextColor const):
+        User Color::colorWithAlpha() to avoid the need to muck with components directly.
+
+        * platform/graphics/Color.cpp:
+        (WebCore::differenceSquared):
+        Use rgb() directly, which is ok, since this is explicitly checking isExtended().
+        This code is still wrong (there is a FIXME) as it assumes the two colors are in
+        the same color space.
+
+        (WebCore::Color::Color):
+        Add constructor which takes an ExtendedColor to allow functions like 
+        Color::invertedColorWithAlpha to delegate their functionality to ExtendedColor.
+        
+        (WebCore::Color::light const):
+        Use new SimpleColor::colorWithAlpha() to avoid hardcoding constants here.
+
+        (WebCore::Color::blend const):
+        (WebCore::Color::blendWithWhite const):
+        Use toSRGBASimpleColorLossy() to get access to color components. These
+        are still not ideal implementations, as they don't preserve extended colors
+        as well as they could, but now they don't return bogus values for extended
+        colors. Minor cleanup bringing constants and lambda inside the function they
+        are used in.
+        
+        (WebCore::Color::colorWithAlpha const):
+        (WebCore::Color::colorWithAlphaUsingAlternativeRounding const):
+        Minor cleanups to use a more consistent style and make use of the new
+        SimpleColor::colorWithAlpha.
+        
+        (WebCore::Color::invertedColorWithAlpha const):
+        Added. Used to avoid direct component usage in line box code.
+
+        (WebCore::Color::semanticColor const):
+        Added. Hopefully temporary. Used by RenderThemeIOS.mm to convert
+        a Color from a map into a Color with the semantic bit set. This 
+        should not be necessary as every color in the map should already
+        have it set, but to avoid uncessary possible behavior changes this
+        preserves that functionality until it can be researched further.
+        Fixing coders to preserve the semantic bit may be required to 
+        elliminate the need.
+        
+        (WebCore::Color::colorSpaceAndComponents const):
+        Use rgb() rather than the individual components which have been removed.
+        
+        * platform/graphics/Color.h:
+        (WebCore::SimpleColor::alphaComponentAsFloat const):
+        Added. Needed by DeprecatedCSSOMRGBColor and useful to Color.
+
+        (WebCore::SimpleColor::colorWithAlpha const):
+        Useful to simplify Color::colorWithAlpha implementations and
+        in Color::dark().
+
+        (WebCore::SimpleColor::get const):
+        Added tuple interface to SimpleColor to support structure bindings.
+        NOTE: Unlike the storage of SimpleColor (ARGB), this produces the
+        bindings in the more familiar [r,g,b,a] to match FloatComponents.
+        
+        (WebCore::Color::alpha const):
+        Made work with ExtendedColor as well.
+        
+        (WebCore::Color::red const): Deleted.
+        (WebCore::Color::green const): Deleted.
+        (WebCore::Color::blue const): Deleted.
+        Removed.
+
+        (CGColorRef cachedCGColor): 
+        (int differenceSquared): 
+        Made friends so they could use Color::rgb().
+
+        (WebCore::Color::rgb const): 
+        Made private.
+
+        * platform/graphics/ExtendedColor.cpp:
+        (WebCore::ExtendedColor::invertedColorWithAlpha const):
+        * platform/graphics/ExtendedColor.h:
+        Added invertedColorWithAlpha to allow inversion to be encapsulated.
+        When future color spaces are added, we may need to choose per-colorspace
+        algorithms for this instead of the trivial one used today.
+
+        * platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm:
+        (WebCore::PlatformCAAnimationCocoa::setFromValue):
+        (WebCore::PlatformCAAnimationCocoa::setToValue):
+        (WebCore::PlatformCAAnimationCocoa::setValues):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * platform/graphics/ca/win/PlatformCAAnimationWin.cpp:
+        (PlatformCAAnimationWin::setFromValue):
+        (PlatformCAAnimationWin::setToValue):
+        (PlatformCAAnimationWin::setValues):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * platform/graphics/cairo/CairoOperations.cpp:
+        (WebCore::Cairo::drawFocusRing):
+        Use Color::colorWithAlpha() to avoid needing access to components.
+
+        * platform/graphics/cpu/arm/filters/FELightingNEON.h:
+        (WebCore::FELighting::platformApplyNeon):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * platform/graphics/texmap/TextureMapperGL.cpp:
+        (WebCore::TextureMapperGL::clearColor):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
+        * platform/graphics/win/Direct2DOperations.cpp:
+        (WebCore::Direct2D::drawGlyphs):
+        Use colorWithAlphaMultipliedBy() to avoid needing access to components.
+
+        * platform/graphics/win/FontCGWin.cpp:
+        (WebCore::FontCascade::drawGlyphs):
+        Use colorWithAlphaMultipliedBy() to avoid needing access to components.
+
+        * platform/graphics/win/FontCascadeDirect2D.cpp:
+        (WebCore::FontCascade::drawGlyphs):
+        Use colorWithAlphaMultipliedBy() to avoid needing access to components.
+
+        * rendering/EllipsisBox.cpp:
+        (WebCore::EllipsisBox::paintSelection):
+        Use invertedColorWithAlpha() to avoid needing access to components.
+
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::resolveStyleForMarkedText):
+        Use invertedColorWithAlpha() to avoid needing access to components.
+
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintBoxShadow):
+        Use opaqueColor() to avoid needing access to components.
+
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::RenderThemeIOS::systemColor const):
+        Use opaqueColor() to avoid needing access to components.
+
+        * svg/properties/SVGAnimationAdditiveValueFunctionImpl.h:
+        (WebCore::SVGAnimationColorFunction::animate):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
 2020-05-24  Zalan Bujtas  <[email protected]>
 
         [LFC][TFC] Take sections into account when computing collapsed border.

Modified: trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp (262107 => 262108)


--- trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -1962,10 +1962,10 @@
     if (!is<HTMLInputElement>(node()))
         return;
 
-    auto color = downcast<HTMLInputElement>(*node()).valueAsColor();
-    r = color.red();
-    g = color.green();
-    b = color.blue();
+    auto color = downcast<HTMLInputElement>(*node()).valueAsColor().toSRGBASimpleColorLossy();
+    r = color.redComponent();
+    g = color.greenComponent();
+    b = color.blueComponent();
 #endif
 }
 

Modified: trunk/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp (262107 => 262108)


--- trunk/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -92,13 +92,15 @@
 
     Color bgColor = style->visitedDependentColor(CSSPropertyBackgroundColor);
     if (bgColor.isValid()) {
-        buffer.reset(g_strdup_printf("%i,%i,%i", bgColor.red(), bgColor.green(), bgColor.blue()));
+        auto [r, g, b, a] = bgColor.toSRGBASimpleColorLossy();
+        buffer.reset(g_strdup_printf("%i,%i,%i", r, g, b));
         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_BG_COLOR), buffer.get());
     }
 
     Color fgColor = style->visitedDependentColor(CSSPropertyColor);
     if (fgColor.isValid()) {
-        buffer.reset(g_strdup_printf("%i,%i,%i", fgColor.red(), fgColor.green(), fgColor.blue()));
+        auto [r, g, b, a] = fgColor.toSRGBASimpleColorLossy();
+        buffer.reset(g_strdup_printf("%i,%i,%i", r, g, b));
         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_FG_COLOR), buffer.get());
     }
 

Modified: trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp (262107 => 262108)


--- trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -698,10 +698,10 @@
 
 void AXIsolatedObject::colorValue(int& r, int& g, int& b) const
 {
-    auto color = colorAttributeValue(AXPropertyName::ColorValue);
-    r = color.red();
-    g = color.green();
-    b = color.blue();
+    auto color = colorAttributeValue(AXPropertyName::ColorValue).toSRGBASimpleColorLossy();
+    r = color.redComponent();
+    g = color.greenComponent();
+    b = color.blueComponent();
 }
 
 AXCoreObject* AXIsolatedObject::accessibilityHitTest(const IntPoint& point) const

Modified: trunk/Source/WebCore/css/DeprecatedCSSOMRGBColor.h (262107 => 262108)


--- trunk/Source/WebCore/css/DeprecatedCSSOMRGBColor.h	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/css/DeprecatedCSSOMRGBColor.h	2020-05-24 15:53:19 UTC (rev 262108)
@@ -37,7 +37,7 @@
     DeprecatedCSSOMPrimitiveValue& blue() { return m_blue; }
     DeprecatedCSSOMPrimitiveValue& alpha() { return m_alpha; }
 
-    Color color() const { return m_color; }
+    SimpleColor color() const { return m_color; }
 
 private:
     template<typename NumberType> static Ref<DeprecatedCSSOMPrimitiveValue> createWrapper(CSSStyleDeclaration& owner, NumberType number)
@@ -46,15 +46,15 @@
     }
 
     DeprecatedCSSOMRGBColor(CSSStyleDeclaration& owner, const Color& color)
-        : m_color(color)
-        , m_red(createWrapper(owner, color.red()))
-        , m_green(createWrapper(owner, color.green()))
-        , m_blue(createWrapper(owner, color.blue()))
-        , m_alpha(createWrapper(owner, color.alphaAsFloat()))
+        : m_color(color.toSRGBASimpleColorLossy())
+        , m_red(createWrapper(owner, m_color.redComponent()))
+        , m_green(createWrapper(owner, m_color.greenComponent()))
+        , m_blue(createWrapper(owner, m_color.blueComponent()))
+        , m_alpha(createWrapper(owner, m_color.alphaComponentAsFloat()))
     {
     }
 
-    Color m_color;
+    SimpleColor m_color;
     Ref<DeprecatedCSSOMPrimitiveValue> m_red;
     Ref<DeprecatedCSSOMPrimitiveValue> m_green;
     Ref<DeprecatedCSSOMPrimitiveValue> m_blue;

Modified: trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp (262107 => 262108)


--- trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -276,7 +276,7 @@
     CGFloat opacity = MACaptionAppearanceGetWindowOpacity(kMACaptionAppearanceDomainUser, &behavior);
     if (!important)
         important = behavior == kMACaptionAppearanceBehaviorUseValue;
-    String windowStyle = colorPropertyCSS(CSSPropertyBackgroundColor, Color(windowColor.red(), windowColor.green(), windowColor.blue(), static_cast<int>(opacity * 255)), important);
+    String windowStyle = colorPropertyCSS(CSSPropertyBackgroundColor, windowColor.colorWithAlpha(opacity), important);
 
     if (!opacity)
         return windowStyle;
@@ -301,7 +301,7 @@
     CGFloat opacity = MACaptionAppearanceGetBackgroundOpacity(kMACaptionAppearanceDomainUser, &behavior);
     if (!important)
         important = behavior == kMACaptionAppearanceBehaviorUseValue;
-    return colorPropertyCSS(CSSPropertyBackgroundColor, Color(backgroundColor.red(), backgroundColor.green(), backgroundColor.blue(), static_cast<int>(opacity * 255)), important);
+    return colorPropertyCSS(CSSPropertyBackgroundColor, backgroundColor.colorWithAlpha(opacity), important);
 }
 
 Color CaptionUserPreferencesMediaAF::captionsTextColor(bool& important) const
@@ -317,7 +317,7 @@
     CGFloat opacity = MACaptionAppearanceGetForegroundOpacity(kMACaptionAppearanceDomainUser, &behavior);
     if (!important)
         important = behavior == kMACaptionAppearanceBehaviorUseValue;
-    return Color(textColor.red(), textColor.green(), textColor.blue(), static_cast<int>(opacity * 255));
+    return textColor.colorWithAlpha(opacity);
 }
     
 String CaptionUserPreferencesMediaAF::captionsTextColorCSS() const

Modified: trunk/Source/WebCore/platform/graphics/Color.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/Color.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/Color.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -180,12 +180,12 @@
     // FIXME: This should probably return a floating point number, but many of the call
     // sites have picked comparison values based on feel. We'd need to break out
     // our logarithm tables to change them :)
-    int c1Red = c1.isExtended() ? c1.asExtended().red() * 255 : c1.red();
-    int c1Green = c1.isExtended() ? c1.asExtended().green() * 255 : c1.green();
-    int c1Blue = c1.isExtended() ? c1.asExtended().blue() * 255 : c1.blue();
-    int c2Red = c2.isExtended() ? c2.asExtended().red() * 255 : c2.red();
-    int c2Green = c2.isExtended() ? c2.asExtended().green() * 255 : c2.green();
-    int c2Blue = c2.isExtended() ? c2.asExtended().blue() * 255 : c2.blue();
+    int c1Red = c1.isExtended() ? c1.asExtended().red() * 255 : c1.rgb().redComponent();
+    int c1Green = c1.isExtended() ? c1.asExtended().green() * 255 : c1.rgb().greenComponent();
+    int c1Blue = c1.isExtended() ? c1.asExtended().blue() * 255 : c1.rgb().blueComponent();
+    int c2Red = c2.isExtended() ? c2.asExtended().red() * 255 : c2.rgb().redComponent();
+    int c2Green = c2.isExtended() ? c2.asExtended().green() * 255 : c2.rgb().greenComponent();
+    int c2Blue = c2.isExtended() ? c2.asExtended().blue() * 255 : c2.rgb().blueComponent();
     int dR = c1Red - c2Red;
     int dG = c1Green - c2Green;
     int dB = c1Blue - c2Blue;
@@ -250,12 +250,16 @@
 }
 
 Color::Color(float c1, float c2, float c3, float alpha, ColorSpace colorSpace)
+    : Color(ExtendedColor::create(c1, c2, c3, alpha, colorSpace))
 {
+}
+
+Color::Color(Ref<ExtendedColor>&& extendedColor)
+{
     // Zero the union, just in case a 32-bit system only assigns the
     // top 32 bits when copying the extendedColor pointer below.
     m_colorData.rgbaAndFlags = 0;
-    auto extendedColorRef = ExtendedColor::create(c1, c2, c3, alpha, colorSpace);
-    m_colorData.extendedColor = &extendedColorRef.leakRef();
+    m_colorData.extendedColor = &extendedColor.leakRef();
     ASSERT(isExtended());
 }
 
@@ -363,17 +367,17 @@
 
     float v = std::max({ r, g, b });
 
-    if (v == 0.0f) {
-        // Lightened black with alpha.
-        return Color(0x54, 0x54, 0x54, alpha());
-    }
+    if (v == 0.0f)
+        return lightenedBlack.colorWithAlpha(alpha());
 
     float multiplier = std::min(1.0f, v + 0.33f) / v;
 
-    return Color(static_cast<int>(multiplier * r * scaleFactor),
-                 static_cast<int>(multiplier * g * scaleFactor),
-                 static_cast<int>(multiplier * b * scaleFactor),
-                 alpha());
+    return {
+        static_cast<int>(multiplier * r * scaleFactor),
+        static_cast<int>(multiplier * g * scaleFactor),
+        static_cast<int>(multiplier * b * scaleFactor),
+        alpha()
+    };
 }
 
 Color Color::dark() const
@@ -389,10 +393,12 @@
     float v = std::max({ r, g, b });
     float multiplier = std::max(0.0f, (v - 0.33f) / v);
 
-    return Color(static_cast<int>(multiplier * r * scaleFactor),
-                 static_cast<int>(multiplier * g * scaleFactor),
-                 static_cast<int>(multiplier * b * scaleFactor),
-                 alpha());
+    return {
+        static_cast<int>(multiplier * r * scaleFactor),
+        static_cast<int>(multiplier * g * scaleFactor),
+        static_cast<int>(multiplier * b * scaleFactor),
+        alpha()
+    };
 }
 
 bool Color::isDark() const
@@ -409,19 +415,6 @@
     return WebCore::lightness(toSRGBAComponentsLossy());
 }
 
-static int blendComponent(int c, int a)
-{
-    // We use white.
-    float alpha = a / 255.0f;
-    int whiteBlend = 255 - a;
-    c -= whiteBlend;
-    return static_cast<int>(c / alpha);
-}
-
-const int cStartAlpha = 153; // 60%
-const int cEndAlpha = 204; // 80%;
-const int cAlphaIncrement = 17; // Increments in between.
-
 Color Color::blend(const Color& source) const
 {
     if (!isVisible() || source.isOpaque())
@@ -430,37 +423,55 @@
     if (!source.alpha())
         return *this;
 
-    int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
-    int a = d / 255;
-    int r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d;
-    int g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d;
-    int b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d;
-    return Color(r, g, b, a);
+    auto [selfR, selfG, selfB, selfA] = toSRGBASimpleColorLossy();
+    auto [sourceR, sourceG, sourceB, sourceA] = source.toSRGBASimpleColorLossy();
+
+    int d = 0xFF * (selfA + sourceA) - selfA * sourceA;
+    int a = d / 0xFF;
+    int r = (selfR * selfA * (0xFF - sourceA) + 0xFF * sourceA * sourceR) / d;
+    int g = (selfG * selfA * (0xFF - sourceA) + 0xFF * sourceA * sourceG) / d;
+    int b = (selfB * selfA * (0xFF - sourceA) + 0xFF * sourceA * sourceB) / d;
+
+    return makeRGBA(r, g, b, a);
 }
 
 Color Color::blendWithWhite() const
 {
+    constexpr int startAlpha = 153; // 60%
+    constexpr int endAlpha = 204; // 80%;
+    constexpr int alphaIncrement = 17;
+
+    auto blendComponent = [](int c, int a) -> int {
+        float alpha = a / 255.0f;
+        int whiteBlend = 255 - a;
+        c -= whiteBlend;
+        return static_cast<int>(c / alpha);
+    };
+
     // If the color contains alpha already, we leave it alone.
     if (!isOpaque())
         return *this;
 
-    Color newColor;
-    for (int alpha = cStartAlpha; alpha <= cEndAlpha; alpha += cAlphaIncrement) {
+    auto [existingR, existingG, existingB, existingAlpha] = toSRGBASimpleColorLossy();
+
+    Color result;
+    for (int alpha = startAlpha; alpha <= endAlpha; alpha += alphaIncrement) {
         // We have a solid color.  Convert to an equivalent color that looks the same when blended with white
         // at the current alpha.  Try using less transparency if the numbers end up being negative.
-        int r = blendComponent(red(), alpha);
-        int g = blendComponent(green(), alpha);
-        int b = blendComponent(blue(), alpha);
+        int r = blendComponent(existingR, alpha);
+        int g = blendComponent(existingG, alpha);
+        int b = blendComponent(existingB, alpha);
         
-        newColor = Color(r, g, b, alpha);
+        result = makeRGBA(r, g, b, alpha);
 
         if (r >= 0 && g >= 0 && b >= 0)
             break;
     }
 
+    // FIXME: Why is preserving the semantic bit desired and/or correct here?
     if (isSemantic())
-        newColor.setIsSemantic();
-    return newColor;
+        result.setIsSemantic();
+    return result;
 }
 
 Color Color::colorWithAlphaMultipliedBy(float amount) const
@@ -477,13 +488,15 @@
 
 Color Color::colorWithAlpha(float alpha) const
 {
-    if (isExtended())
-        return Color { m_colorData.extendedColor->red(), m_colorData.extendedColor->green(), m_colorData.extendedColor->blue(), alpha, m_colorData.extendedColor->colorSpace() };
+    if (isExtended()) {
+        auto& extendedColor = asExtended();
+        return Color { extendedColor.red(), extendedColor.green(), extendedColor.blue(), alpha, extendedColor.colorSpace() };
+    }
 
     // FIXME: This is where this function differs from colorWithAlphaUsingAlternativeRounding.
-    int newAlpha = alpha * 255;
+    uint8_t newAlpha = alpha * 0xFF;
 
-    Color result = { red(), green(), blue(), newAlpha };
+    Color result = rgb().colorWithAlpha(newAlpha);
     if (isSemantic())
         result.setIsSemantic();
     return result;
@@ -491,15 +504,37 @@
 
 Color Color::colorWithAlphaUsingAlternativeRounding(float alpha) const
 {
-    if (isExtended())
-        return Color { m_colorData.extendedColor->red(), m_colorData.extendedColor->green(), m_colorData.extendedColor->blue(), alpha, m_colorData.extendedColor->colorSpace() };
+    if (isExtended()) {
+        auto& extendedColor = asExtended();
+        return Color { extendedColor.red(), extendedColor.green(), extendedColor.blue(), alpha, extendedColor.colorSpace() };
+    }
 
-    Color result = SimpleColor { (rgb().value() & 0x00FFFFFF) | colorFloatToRGBAByte(alpha) << 24 };
+    // FIXME: This is where this function differs from colorWithAlphaUsing.
+    uint8_t newAlpha = colorFloatToRGBAByte(alpha);
+
+    Color result = rgb().colorWithAlpha(newAlpha);
     if (isSemantic())
         result.setIsSemantic();
     return result;
 }
 
+Color Color::invertedColorWithAlpha(float alpha) const
+{
+    if (isExtended())
+        return Color { asExtended().invertedColorWithAlpha(alpha) };
+
+    auto [r, g, b, existingAlpha] = rgb();
+    return { 0xFF - r, 0xFF - g, 0xFF - b, colorFloatToRGBAByte(alpha) };
+}
+
+Color Color::semanticColor() const
+{
+    if (isSemantic())
+        return *this;
+
+    return { toSRGBASimpleColorLossy(), Semantic };
+}
+
 std::pair<ColorSpace, FloatComponents> Color::colorSpaceAndComponents() const
 {
     if (isExtended()) {
@@ -507,7 +542,8 @@
         return { extendedColor.colorSpace(), extendedColor.channels() };
     }
 
-    return { ColorSpace::SRGB, FloatComponents { red() / 255.0f, green() / 255.0f, blue() / 255.0f,  alpha() / 255.0f } };
+    auto [r, g, b, a] = rgb();
+    return { ColorSpace::SRGB, FloatComponents { r / 255.0f, g / 255.0f, b / 255.0f,  a / 255.0f } };
 }
 
 SimpleColor Color::toSRGBASimpleColorLossy() const

Modified: trunk/Source/WebCore/platform/graphics/Color.h (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/Color.h	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/Color.h	2020-05-24 15:53:19 UTC (rev 262108)
@@ -69,6 +69,8 @@
     constexpr uint8_t blueComponent() const { return m_value; }
     constexpr uint8_t alphaComponent() const { return m_value >> 24; }
 
+    constexpr float alphaComponentAsFloat() const { return static_cast<float>(alphaComponent()) / 0xFF; }
+
     constexpr bool isOpaque() const { return alphaComponent() == 0xFF; }
     constexpr bool isVisible() const { return alphaComponent(); }
 
@@ -76,6 +78,22 @@
     String serializationForCSS() const;
     String serializationForRenderTreeAsText() const;
 
+    constexpr SimpleColor colorWithAlpha(uint8_t alpha) const { return { (m_value & 0x00FFFFFF) | alpha << 24 }; }
+
+    template<std::size_t N>
+    constexpr uint8_t get() const
+    {
+        static_assert(N < 4);
+        if constexpr (!N)
+            return redComponent();
+        else if constexpr (N == 1)
+            return greenComponent();
+        else if constexpr (N == 2)
+            return blueComponent();
+        else if constexpr (N == 3)
+            return alphaComponent();
+    }
+
 private:
     uint32_t m_value { 0 };
 };
@@ -171,6 +189,7 @@
     // FIXME: If the colorSpace is sRGB and the values can all be
     // converted exactly to integers, we should make a normal Color.
     WEBCORE_EXPORT Color(float, float, float, float, ColorSpace);
+    WEBCORE_EXPORT Color(Ref<ExtendedColor>&&);
 
     WEBCORE_EXPORT Color(const Color&);
     WEBCORE_EXPORT Color(Color&&);
@@ -195,15 +214,9 @@
     bool isOpaque() const { return isExtended() ? asExtended().alpha() == 1.0 : rgb().isOpaque(); }
     bool isVisible() const { return isExtended() ? asExtended().alpha() > 0.0 : rgb().isVisible(); }
 
-    int red() const { return rgb().redComponent(); }
-    int green() const { return rgb().greenComponent(); }
-    int blue() const { return rgb().blueComponent(); }
-    int alpha() const { return rgb().alphaComponent(); }
+    int alpha() const { return isExtended() ? asExtended().alpha() * 255 : rgb().alphaComponent(); }
+    float alphaAsFloat() const { return isExtended() ? asExtended().alpha() : rgb().alphaComponentAsFloat(); }
 
-    float alphaAsFloat() const { return isExtended() ? asExtended().alpha() : static_cast<float>(rgb().alphaComponent()) / 0xFF; }
-
-    RGBA32 rgb() const;
-
     unsigned hash() const;
 
     WEBCORE_EXPORT std::pair<ColorSpace, FloatComponents> colorSpaceAndComponents() const;
@@ -225,6 +238,8 @@
     Color blend(const Color&) const;
     Color blendWithWhite() const;
 
+    Color invertedColorWithAlpha(float alpha) const;
+
     Color colorWithAlphaMultipliedBy(float) const;
     Color colorWithAlpha(float) const;
 
@@ -235,6 +250,7 @@
     WEBCORE_EXPORT Color colorWithAlphaUsingAlternativeRounding(float) const;
 
     Color opaqueColor() const { return colorWithAlpha(1.0f); }
+    Color semanticColor() const;
 
     // True if the color originated from a CSS semantic color name.
     bool isSemantic() const { return !isExtended() && (m_colorData.rgbaAndFlags & isSemanticRBGAColorBit); }
@@ -247,6 +263,7 @@
 #if USE(CG)
     WEBCORE_EXPORT Color(CGColorRef);
     WEBCORE_EXPORT Color(CGColorRef, SemanticTag);
+    friend WEBCORE_EXPORT CGColorRef cachedCGColor(const Color&);
 #endif
 
 #if PLATFORM(WIN)
@@ -288,6 +305,8 @@
     friend bool operator==(const Color& a, const Color& b);
     friend bool equalIgnoringSemanticColor(const Color& a, const Color& b);
 
+    friend int differenceSquared(const Color&, const Color&);
+
     static bool isBlackColor(const Color&);
     static bool isWhiteColor(const Color&);
 
@@ -295,6 +314,7 @@
     template<class Decoder> static Optional<Color> decode(Decoder&);
 
 private:
+    RGBA32 rgb() const;
     void setRGB(int r, int g, int b) { setRGB(makeRGB(r, g, b)); }
     void setRGB(RGBA32);
     void setIsSemantic() { m_colorData.rgbaAndFlags |= isSemanticRBGAColorBit; }
@@ -530,3 +550,17 @@
 template<> struct DefaultHash<WebCore::Color>;
 template<> struct HashTraits<WebCore::Color>;
 }
+
+namespace std {
+
+template<>
+class tuple_size<WebCore::SimpleColor> : public std::integral_constant<std::size_t, 4> {
+};
+
+template<std::size_t N>
+class tuple_element<N, WebCore::SimpleColor> {
+public:
+    using type = uint8_t;
+};
+
+}

Modified: trunk/Source/WebCore/platform/graphics/ExtendedColor.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/ExtendedColor.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/ExtendedColor.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -63,4 +63,10 @@
     return makeString("color(", colorSpace, ' ', red(), ' ', green(), ' ', blue(), " / ", alpha(), ')');
 }
 
+Ref<ExtendedColor> ExtendedColor::invertedColorWithAlpha(float alpha) const
+{
+    auto [c1, c2, c3, existingAlpha] = channels();
+    return ExtendedColor::create(1.0f - c1, 1.0f - c2, 1.0f - c3, alpha, colorSpace());
 }
+
+}

Modified: trunk/Source/WebCore/platform/graphics/ExtendedColor.h (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/ExtendedColor.h	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/ExtendedColor.h	2020-05-24 15:53:19 UTC (rev 262108)
@@ -63,6 +63,8 @@
 
     WEBCORE_EXPORT String cssText() const;
 
+    Ref<ExtendedColor> invertedColorWithAlpha(float) const;
+
 private:
     ExtendedColor(float c1, float c2, float c3, float alpha, ColorSpace colorSpace)
         : m_channels(c1, c2, c3, alpha)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -64,16 +64,16 @@
     disconnect();
 }
 
-static bool makeRGBA32FromARGBCFArray(CFArrayRef colorArray, RGBA32& color)
+static Optional<SimpleColor> makeRGBA32FromARGBCFArray(CFArrayRef colorArray)
 {
     if (CFArrayGetCount(colorArray) < 4)
-        return false;
+        return WTF::nullopt;
 
     float componentArray[4];
     for (int i = 0; i < 4; i++) {
         CFNumberRef value = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(colorArray, i));
         if (CFGetTypeID(value) != CFNumberGetTypeID())
-            return false;
+            return WTF::nullopt;
 
         float component;
         CFNumberGetValue(value, kCFNumberFloatType, &component);
@@ -80,8 +80,7 @@
         componentArray[i] = component;
     }
 
-    color = makeRGBA32FromFloats(componentArray[1], componentArray[2], componentArray[3], componentArray[0]);
-    return true;
+    return makeRGBA32FromFloats(componentArray[1], componentArray[2], componentArray[3], componentArray[0]);
 }
 
 Ref<InbandGenericCue> InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attributedString)
@@ -268,10 +267,10 @@
                 if (CFGetTypeID(arrayValue) != CFArrayGetTypeID())
                     continue;
                 
-                RGBA32 color;
-                if (!makeRGBA32FromARGBCFArray(arrayValue, color))
+                auto color = makeRGBA32FromARGBCFArray(arrayValue);
+                if (!color)
                     continue;
-                cueData->setForegroundColor(color);
+                cueData->setForegroundColor(*color);
                 continue;
             }
             
@@ -280,10 +279,10 @@
                 if (CFGetTypeID(arrayValue) != CFArrayGetTypeID())
                     continue;
                 
-                RGBA32 color;
-                if (!makeRGBA32FromARGBCFArray(arrayValue, color))
+                auto color = makeRGBA32FromARGBCFArray(arrayValue);
+                if (!color)
                     continue;
-                cueData->setBackgroundColor(color);
+                cueData->setBackgroundColor(*color);
                 continue;
             }
 
@@ -292,10 +291,10 @@
                 if (CFGetTypeID(arrayValue) != CFArrayGetTypeID())
                     continue;
                 
-                RGBA32 color;
-                if (!makeRGBA32FromARGBCFArray(arrayValue, color))
+                auto color = makeRGBA32FromARGBCFArray(arrayValue);
+                if (!color)
                     continue;
-                cueData->setHighlightColor(color);
+                cueData->setHighlightColor(*color);
                 continue;
             }
         }

Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm	2020-05-24 15:53:19 UTC (rev 262108)
@@ -396,7 +396,8 @@
 {
     if (!isBasicAnimation())
         return;
-    [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:@[@(value.red()), @(value.green()), @(value.blue()), @(value.alpha())]];
+    auto [r, g, b, a] = value.toSRGBASimpleColorLossy();
+    [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:@[@(r), @(g), @(b), @(a)]];
 }
 
 void PlatformCAAnimationCocoa::setFromValue(const FilterOperation* operation, int internalFilterPropertyIndex)
@@ -438,7 +439,8 @@
 {
     if (!isBasicAnimation())
         return;
-    [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:@[@(value.red()), @(value.green()), @(value.blue()), @(value.alpha())]];
+    auto [r, g, b, a] = value.toSRGBASimpleColorLossy();
+    [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:@[@(r), @(g), @(b), @(a)]];
 }
 
 void PlatformCAAnimationCocoa::setToValue(const FilterOperation* operation, int internalFilterPropertyIndex)
@@ -494,7 +496,8 @@
         return;
 
     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:createNSArray(value, [] (auto& color) {
-        return @[@(color.red()), @(color.green()), @(color.blue()), @(color.alpha())];
+        auto [r, g, b, a] = color.toSRGBASimpleColorLossy();
+        return @[@(r), @(g), @(b), @(a)];
     }).get()];
 }
 

Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -367,7 +367,8 @@
     if (animationType() != Basic)
         return;
 
-    CGFloat a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
+    auto simpleColor = value.toSRGBASimpleColorLossy();
+    CGFloat a[4] = { simpleColor.redComponent(), simpleColor.greenComponent(), simpleColor.blueComponent(), simpleColor.alphaComponent() };
     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
     CACFAnimationSetFromValue(m_animation.get(), v.get());
 }
@@ -418,7 +419,8 @@
     if (animationType() != Basic)
         return;
 
-    CGFloat a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
+    auto simpleColor = value.toSRGBASimpleColorLossy();
+    CGFloat a[4] = { simpleColor.redComponent(), simpleColor.greenComponent(), simpleColor.blueComponent(), simpleColor.alphaComponent() };
     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
     CACFAnimationSetToValue(m_animation.get(), v.get());
 }
@@ -487,7 +489,8 @@
         
     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
     for (size_t i = 0; i < value.size(); ++i) {
-        CGFloat a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() };
+        auto simpleColor = value[i].toSRGBASimpleColorLossy();
+        CGFloat a[4] = { simpleColor.redComponent(), simpleColor.greenComponent(), simpleColor.blueComponent(), simpleColor.alphaComponent() };
         RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
         CFArrayAppendValue(array.get(), v.get());
     }

Modified: trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -78,7 +78,7 @@
     } else {
         // Solid color source
         if (globalAlpha < 1)
-            setSourceRGBAFromColor(cr, color.colorWithAlphaUsingAlternativeRounding(color.alpha() / 255.f * globalAlpha));
+            setSourceRGBAFromColor(cr, color.colorWithAlphaMultipliedByUsingAlternativeRounding(globalAlpha));
         else
             setSourceRGBAFromColor(cr, color);
     }
@@ -1121,7 +1121,7 @@
     // so as to be consistent with how we draw rectangular focus rings.
 
     // Force the alpha to 50%. This matches what the Mac does with outline rings.
-    Color ringColor = makeRGBA(color.red(), color.green(), color.blue(), 127);
+    Color ringColor = color.colorWithAlpha(.5);
 
     cairo_t* cr = platformContext.cr();
     cairo_save(cr);

Modified: trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h	2020-05-24 15:53:19 UTC (rev 262108)
@@ -111,9 +111,11 @@
     // Set light source arguments.
     floatArguments.constOne = 1;
 
-    floatArguments.colorRed = m_lightingColor.red();
-    floatArguments.colorGreen = m_lightingColor.green();
-    floatArguments.colorBlue = m_lightingColor.blue();
+    auto simpleColor = m_lightingColor.toSRGBASimpleColorLossy();
+
+    floatArguments.colorRed = simpleColor.redComponent();
+    floatArguments.colorGreen = simpleColor.greenComponent();
+    floatArguments.colorBlue = simpleColor.blueComponent();
     floatArguments.padding4 = 0;
 
     if (m_lightSource->type() == LS_POINT) {

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -686,7 +686,8 @@
 
 void TextureMapperGL::clearColor(const Color& color)
 {
-    glClearColor(color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, color.alpha() / 255.0f);
+    auto [r, g, b, a] = color.toSRGBAComponentsLossy();
+    glClearColor(r, g, b, a);
     glClear(GL_COLOR_BUFFER_BIT);
 }
 

Modified: trunk/Source/WebCore/platform/graphics/win/Direct2DOperations.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/win/Direct2DOperations.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/win/Direct2DOperations.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -780,7 +780,7 @@
         // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
         graphicsContext.clearShadow();
         Color fillColor = graphicsContext.fillColor();
-        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
+        Color shadowFillColor = shadowColor.colorWithAlphaMultipliedBy(fillColor.alphaAsFloat());
         float shadowTextX = point.x() + shadowOffset.width();
         // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
         float shadowTextY = point.y() + shadowOffset.height() * (graphicsContext.shadowsIgnoreTransforms() ? -1 : 1);

Modified: trunk/Source/WebCore/platform/graphics/win/FontCGWin.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/win/FontCGWin.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/win/FontCGWin.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -186,7 +186,7 @@
         // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
         graphicsContext.clearShadow();
         Color fillColor = graphicsContext.fillColor();
-        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
+        Color shadowFillColor = shadowColor.colorWithAlphaMultipliedBy(fillColor.alphaAsFloat());
         graphicsContext.setFillColor(shadowFillColor);
         float shadowTextX = point.x() + shadowOffset.width();
         // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.

Modified: trunk/Source/WebCore/platform/graphics/win/FontCascadeDirect2D.cpp (262107 => 262108)


--- trunk/Source/WebCore/platform/graphics/win/FontCascadeDirect2D.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/platform/graphics/win/FontCascadeDirect2D.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -121,7 +121,7 @@
         // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
         graphicsContext.clearShadow();
         Color fillColor = graphicsContext.fillColor();
-        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
+        Color shadowFillColor = shadowColor.colorWithAlphaMultipliedBy(fillColor.alphaAsFloat());
         float shadowTextX = point.x() + shadowOffset.width();
         // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
         float shadowTextY = point.y() + shadowOffset.height() * (graphicsContext.shadowsIgnoreTransforms() ? -1 : 1);

Modified: trunk/Source/WebCore/rendering/EllipsisBox.cpp (262107 => 262108)


--- trunk/Source/WebCore/rendering/EllipsisBox.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/rendering/EllipsisBox.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -134,7 +134,7 @@
     // If the text color ends up being the same as the selection background, invert the selection
     // background.
     if (textColor == c)
-        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
+        c = c.invertedColorWithAlpha(1.0);
 
     const RootInlineBox& rootBox = root();
     GraphicsContextStateSaver stateSaver(context);

Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (262107 => 262108)


--- trunk/Source/WebCore/rendering/InlineTextBox.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -854,7 +854,7 @@
         Color selectionBackgroundColor = renderer().selectionBackgroundColor();
         style.backgroundColor = selectionBackgroundColor;
         if (selectionBackgroundColor.isValid() && selectionBackgroundColor.alpha() && style.textStyles.fillColor == selectionBackgroundColor)
-            style.backgroundColor = { 0xff - selectionBackgroundColor.red(), 0xff - selectionBackgroundColor.green(), 0xff - selectionBackgroundColor.blue() };
+            style.backgroundColor = selectionBackgroundColor.invertedColorWithAlpha(1.0);
         break;
     }
     case MarkedText::TextMatch: {

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (262107 => 262108)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -2495,7 +2495,7 @@
                 continue;
             }
 
-            Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);
+            Color fillColor = shadowColor.opaqueColor();
             auto shadowCastingRect = areaCastingShadowInHole(borderRect.rect(), shadowPaintingExtent, shadowSpread, shadowOffset);
             auto pixelSnappedOuterRect = snapRectToDevicePixels(shadowCastingRect, deviceScaleFactor);
 

Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (262107 => 262108)


--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2020-05-24 15:53:19 UTC (rev 262108)
@@ -1554,7 +1554,7 @@
             auto it = globalCSSValueToSystemColorMap().find(CSSValueKey { cssValueID, useDarkAppearance, useElevatedUserInterfaceLevel });
             if (it == globalCSSValueToSystemColorMap().end())
                 return RenderTheme::systemColor(cssValueID, options);
-            return Color(it->value.rgb(), Color::Semantic);
+            return it->value.semanticColor();
         }
         auto color = systemColorFromCSSValueID(cssValueID, useDarkAppearance, useElevatedUserInterfaceLevel);
         if (color)

Modified: trunk/Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.h (262107 => 262108)


--- trunk/Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.h	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.h	2020-05-24 15:53:19 UTC (rev 262108)
@@ -81,12 +81,15 @@
 
     void animate(SVGElement*, float progress, unsigned repeatCount, Color& animated)
     {
-        Color from = m_animationMode == AnimationMode::To ? animated : m_from;
+        auto simpleAnimated = animated.toSRGBASimpleColorLossy();
+        auto simpleFrom = m_animationMode == AnimationMode::To ? simpleAnimated : m_from.toSRGBASimpleColorLossy();
+        auto simpleTo = m_to.toSRGBASimpleColorLossy();
+        auto simpleToAtEndOfDuration = toAtEndOfDuration().toSRGBASimpleColorLossy();
         
-        float red = Base::animate(progress, repeatCount, from.red(), m_to.red(), toAtEndOfDuration().red(), animated.red());
-        float green = Base::animate(progress, repeatCount, from.green(), m_to.green(), toAtEndOfDuration().green(), animated.green());
-        float blue = Base::animate(progress, repeatCount, from.blue(), m_to.blue(), toAtEndOfDuration().blue(), animated.blue());
-        float alpha = Base::animate(progress, repeatCount, from.alpha(), m_to.alpha(), toAtEndOfDuration().alpha(), animated.alpha());
+        float red = Base::animate(progress, repeatCount, simpleFrom.redComponent(), simpleTo.redComponent(), simpleToAtEndOfDuration.redComponent(), simpleAnimated.redComponent());
+        float green = Base::animate(progress, repeatCount, simpleFrom.greenComponent(), simpleTo.greenComponent(), simpleToAtEndOfDuration.greenComponent(), simpleAnimated.greenComponent());
+        float blue = Base::animate(progress, repeatCount, simpleFrom.blueComponent(), simpleTo.blueComponent(), simpleToAtEndOfDuration.blueComponent(), simpleAnimated.blueComponent());
+        float alpha = Base::animate(progress, repeatCount, simpleFrom.alphaComponent(), simpleTo.alphaComponent(), simpleToAtEndOfDuration.alphaComponent(), simpleAnimated.alphaComponent());
         
         animated = { roundAndClampColorChannel(red), roundAndClampColorChannel(green), roundAndClampColorChannel(blue), roundAndClampColorChannel(alpha) };
     }
@@ -99,9 +102,14 @@
         Color toColor = CSSParser::parseColor(to.stripWhiteSpace());
         if (!toColor.isValid())
             return { };
-        float red = fromColor.red() - toColor.red();
-        float green = fromColor.green() - toColor.green();
-        float blue = fromColor.blue() - toColor.blue();
+            
+        auto simpleFrom = fromColor.toSRGBASimpleColorLossy();
+        auto simpleTo = toColor.toSRGBASimpleColorLossy();
+
+        float red = simpleFrom.redComponent() - simpleTo.redComponent();
+        float green = simpleFrom.greenComponent() - simpleTo.greenComponent();
+        float blue = simpleFrom.blueComponent() - simpleTo.blueComponent();
+
         return std::hypot(red, green, blue);
     }
 
@@ -108,11 +116,14 @@
 private:
     void addFromAndToValues(SVGElement*) override
     {
+        auto simpleFrom = m_from.toSRGBASimpleColorLossy();
+        auto simpleTo = m_to.toSRGBASimpleColorLossy();
+
         // Ignores any alpha and sets alpha on result to 100% opaque.
         m_to = {
-            roundAndClampColorChannel(m_to.red() + m_from.red()),
-            roundAndClampColorChannel(m_to.green() + m_from.green()),
-            roundAndClampColorChannel(m_to.blue() + m_from.blue())
+            roundAndClampColorChannel(simpleTo.redComponent() + simpleFrom.redComponent()),
+            roundAndClampColorChannel(simpleTo.greenComponent() + simpleFrom.greenComponent()),
+            roundAndClampColorChannel(simpleTo.blueComponent() + simpleFrom.blueComponent())
         };
     }
 

Modified: trunk/Source/WebKit/ChangeLog (262107 => 262108)


--- trunk/Source/WebKit/ChangeLog	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebKit/ChangeLog	2020-05-24 15:53:19 UTC (rev 262108)
@@ -1,3 +1,14 @@
+2020-05-24  Sam Weinig  <[email protected]>
+
+        Extended Color Cleanup: Stop allowing direct access to the underlying SimpleColor (it is almost always incorrect with respect to extended colors)
+        https://bugs.webkit.org/show_bug.cgi?id=212184
+
+        Reviewed by Dean Jackson.
+
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm:
+        (WebKit::animationValueFromKeyframeValue):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
 2020-05-24  Carlos Garcia Campos  <[email protected]>
 
         Unreviewed. Remove unused file since r261570

Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm (262107 => 262108)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm	2020-05-24 15:53:19 UTC (rev 262108)
@@ -693,8 +693,8 @@
         return @(keyframeValue.numberValue());
             
     case PlatformCAAnimationRemote::KeyframeValue::ColorKeyType: {
-        Color color = keyframeValue.colorValue();
-        return @[ @(color.red()), @(color.green()), @(color.blue()), @(color.alpha()) ];
+        auto [r, g, b, a] = keyframeValue.colorValue().toSRGBASimpleColorLossy();
+        return @[ @(r), @(g), @(b), @(a) ];
     }
 
     case PlatformCAAnimationRemote::KeyframeValue::PointKeyType: {

Modified: trunk/Tools/ChangeLog (262107 => 262108)


--- trunk/Tools/ChangeLog	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Tools/ChangeLog	2020-05-24 15:53:19 UTC (rev 262108)
@@ -1,3 +1,14 @@
+2020-05-24  Sam Weinig  <[email protected]>
+
+        Extended Color Cleanup: Stop allowing direct access to the underlying SimpleColor (it is almost always incorrect with respect to extended colors)
+        https://bugs.webkit.org/show_bug.cgi?id=212184
+
+        Reviewed by Dean Jackson.
+
+        * TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
+        (TestWebKitAPI::TEST):
+        Use toSRGBASimpleColorLossy() to get access to color components.
+
 2020-05-22  Alex Christensen  <[email protected]>
 
         Make download resume workaround forgiving of changes in CFNetwork

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp (262107 => 262108)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp	2020-05-24 15:34:44 UTC (rev 262107)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp	2020-05-24 15:53:19 UTC (rev 262108)
@@ -182,26 +182,29 @@
     validColor = Color(1, 2, 3, 4);
     EXPECT_TRUE(validColor.isValid());
     EXPECT_FALSE(validColor.isExtended());
-    EXPECT_EQ(validColor.red(), 1);
-    EXPECT_EQ(validColor.green(), 2);
-    EXPECT_EQ(validColor.blue(), 3);
-    EXPECT_EQ(validColor.alpha(), 4);
+    auto simpleValidColor = validColor.toSRGBASimpleColorLossy();
+    EXPECT_EQ(simpleValidColor.redComponent(), 1);
+    EXPECT_EQ(simpleValidColor.greenComponent(), 2);
+    EXPECT_EQ(simpleValidColor.blueComponent(), 3);
+    EXPECT_EQ(simpleValidColor.alphaComponent(), 4);
 
     Color yetAnotherValidColor(WTFMove(validColor));
     EXPECT_TRUE(yetAnotherValidColor.isValid());
     EXPECT_FALSE(yetAnotherValidColor.isExtended());
-    EXPECT_EQ(yetAnotherValidColor.red(), 1);
-    EXPECT_EQ(yetAnotherValidColor.green(), 2);
-    EXPECT_EQ(yetAnotherValidColor.blue(), 3);
-    EXPECT_EQ(yetAnotherValidColor.alpha(), 4);
+    auto simpleYetAnotherValidColor = yetAnotherValidColor.toSRGBASimpleColorLossy();
+    EXPECT_EQ(simpleYetAnotherValidColor.redComponent(), 1);
+    EXPECT_EQ(simpleYetAnotherValidColor.greenComponent(), 2);
+    EXPECT_EQ(simpleYetAnotherValidColor.blueComponent(), 3);
+    EXPECT_EQ(simpleYetAnotherValidColor.alphaComponent(), 4);
 
     otherValidColor = WTFMove(yetAnotherValidColor);
     EXPECT_TRUE(otherValidColor.isValid());
     EXPECT_FALSE(otherValidColor.isExtended());
-    EXPECT_EQ(otherValidColor.red(), 1);
-    EXPECT_EQ(otherValidColor.green(), 2);
-    EXPECT_EQ(otherValidColor.blue(), 3);
-    EXPECT_EQ(otherValidColor.alpha(), 4);
+    auto simpleOtherValidColor = otherValidColor.toSRGBASimpleColorLossy();
+    EXPECT_EQ(simpleOtherValidColor.redComponent(), 1);
+    EXPECT_EQ(simpleOtherValidColor.greenComponent(), 2);
+    EXPECT_EQ(simpleOtherValidColor.blueComponent(), 3);
+    EXPECT_EQ(simpleOtherValidColor.alphaComponent(), 4);
 }
 
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to