Bug 212059 - Remove almost always incorrect Color::getRGBA
Summary: Remove almost always incorrect Color::getRGBA
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Sam Weinig
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-05-18 19:40 PDT by Sam Weinig
Modified: 2020-05-20 09:28 PDT (History)
13 users (show)

See Also:


Attachments
Patch (27.67 KB, patch)
2020-05-18 19:48 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (33.93 KB, patch)
2020-05-19 11:15 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (33.74 KB, patch)
2020-05-19 12:26 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (34.09 KB, patch)
2020-05-19 14:52 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (33.83 KB, patch)
2020-05-19 15:12 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (33.96 KB, patch)
2020-05-19 15:58 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (33.98 KB, patch)
2020-05-19 18:02 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sam Weinig 2020-05-18 19:40:34 PDT
Simplify Color interface by replacing Color::getRGBA() with a variant returning a FloatComponents
Comment 1 Sam Weinig 2020-05-18 19:48:18 PDT
Created attachment 399700 [details]
Patch
Comment 2 Sam Weinig 2020-05-18 19:50:35 PDT
Here is a first pass at this. Not sure I am happy with the name Color::rgba(). Maybe Color::toRGBAComponents() for symmetry with Color::toSRGBAComponentsLossy()? Or should we just have everyone using Color::toSRGBAComponentsLossy().

Pretty happy with the structured bindings use, but since that is kind of new-ish, would like more feedback on it.
Comment 3 Simon Fraser (smfr) 2020-05-18 20:00:46 PDT
Comment on attachment 399700 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399700&action=review

> Source/WebCore/platform/graphics/cairo/GradientCairo.cpp:154
> +    if (from.color.isExtended())
> +        fromComponents = from.color.asExtended().channels();
> +    else
> +        fromComponents = from.color.rgba();

Should make rgba() just work for extended colors, as long as they are sRGB. This code should really ask about the colorspace, not about the isExtended. Maybe just call toSRGBAComponentsLossy().

> Source/WebCore/platform/graphics/cairo/GradientCairo.cpp:165
>      float r = r1 + (r2 - r1) * 0.5f;

Maybe we should just put blending into FloatCompontents.

> Source/WebCore/platform/graphics/cg/GradientCG.cpp:73
> +        auto [r, g, b, a] = stop.color.rgba();

Broken with extended colors (not your fault). Call toSRGBAComponentsLossy()?

> Source/WebCore/platform/graphics/filters/FilterOperations.cpp:114
> +    FloatComponents components = color.rgba();

Broken with extended colors (not your fault). Call toSRGBAComponentsLossy()?

> Source/WebCore/platform/graphics/filters/FilterOperations.cpp:133
> +    FloatComponents components = color.rgba();

Ditto.

> Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp:256
> +    auto [r, g, b, a] = Color(premultipliedARGBFromColor(color)).rgba();

Would be nicer to do the premultiply on FloatComponents.

> Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp:281
> +        auto [r, g, b, a] = color.rgba();

toSRGBAComponentsLossy?

> Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp:421
> +            auto [r, g, b, a] = Color(premultipliedARGBFromColor(shadow.color())).rgba();

Would be nicer to do the premultiply on FloatComponents.

> Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp:683
> +    auto [r, g, b, a] = Color(premultipliedARGBFromColor(color)).rgba();

Would be nicer to do the premultiply on FloatComponents.

> Source/WebCore/rendering/TextPaintStyle.cpp:66
> +    return contrastRatio(textColor.rgba(), backgroundColor.rgba()) > 4.5;

Broken with extended colors.

> Source/WebKit/UIProcess/API/wpe/WebKitColor.cpp:85
> +    auto [r, g, b, a] = webCoreColor.rgba().components;

Broken with extended colors.

> Source/WebKit/WebProcess/WebPage/WebFrame.cpp:663
> +    auto [r, g, b, a] = bgColor.rgba();

Broken with extended colors.
Comment 4 Sam Weinig 2020-05-18 20:30:55 PDT
Simon, other than the call to Color::rgba() in Color::toSRGBAComponents(), are any of the other calls valid? Should they all be switched to Color::toSRGBAComponents() and Color::rgba() be made private?
Comment 5 Simon Fraser (smfr) 2020-05-18 20:50:35 PDT
(In reply to Sam Weinig from comment #4)
> Simon, other than the call to Color::rgba() in Color::toSRGBAComponents(),
> are any of the other calls valid? Should they all be switched to
> Color::toSRGBAComponents() and Color::rgba() be made private?

I think it's an error to call Color::rgba() without knowing that the color is sRGB.

So we could either make Color::rgba() private, or have it return Optional<FloatComponents> if there are clients for which that makes sense.

Now that ExtendedColor allows Color to be in any of the supported colorspaces, I think we have to be explicit about colorspace conversions everywhere.
Comment 6 Simon Fraser (smfr) 2020-05-19 11:13:29 PDT
(In reply to Simon Fraser (smfr) from comment #5)
> (In reply to Sam Weinig from comment #4)
> > Simon, other than the call to Color::rgba() in Color::toSRGBAComponents(),
> > are any of the other calls valid? Should they all be switched to
> > Color::toSRGBAComponents() and Color::rgba() be made private?
> 
> I think it's an error to call Color::rgba() without knowing that the color
> is sRGB.

To put it more strongly: Color::rgba() is actively harmful, because it returns garbage for extended colors. We should hide it. For now we can move callers to toSRGBAComponentsLossy(). Callers that want to do the right thing with extended colors can be migrated later.
Comment 7 Sam Weinig 2020-05-19 11:15:25 PDT
Created attachment 399752 [details]
Patch
Comment 8 Simon Fraser (smfr) 2020-05-19 11:33:00 PDT
Comment on attachment 399752 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399752&action=review

> Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm:136
> +        color = cachedCGColor(SimpleColor { argb });

(Not your fault): It blows my mind that the arguments to SimpleColor are argb. Seems very Cocoa-centric, and easy to get wrong. Maybe SimpleColor needs at more scary name like PlatformPixelValue.

> Source/WebCore/platform/graphics/Color.cpp:359
>          return Color(0x54, 0x54, 0x54, alpha());

Can we just say 84 rather than 0x54?

> Source/WebCore/platform/graphics/Color.cpp:393
> +    auto [r, g, b, a] = toSRGBAComponentsLossy();
> +    float largestNonAlphaChannel = std::max(r, std::max(g, b));
> +    return a > 0.5 && largestNonAlphaChannel < 0.5;

This should really compute luminance. Maybe a // FIXME

> Source/WebCore/platform/graphics/Color.cpp:544
> +    return { ColorSpace::SRGB, FloatComponents { red() / 255.0f, green() / 255.0f, blue() / 255.0f,  alpha() / 255.0f } };

I feel like the / 255.0f should be in a helper function somewhere. We've gone back and forth several times on rounding/flooring of color components (e.g. r252598).

> Source/WebCore/platform/graphics/cg/ColorCG.cpp:117
> +        return CGColorCreate(sRGBColorSpaceRef(), components);

We should use the linearRGBColorSpaceRef here (should fix in a separate bug).

> Source/WebCore/platform/graphics/cg/ColorCG.cpp:134
> +            static CGColorRef whiteCGColor = leakCGColor(color)

How does this compile?

> Source/WebCore/platform/graphics/cg/GradientCG.cpp:74
> +        auto [colorSpace, components] = stop.color.colorSpaceAndComponent();
> +        auto [r, g, b, a] = components;

This needs a FIXME; we drop colorSpace on the floor.

> Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp:202
> +    static constexpr SimpleColor spellingPatternColor { makeRGB(255, 0, 0) };
> +    static constexpr SimpleColor grammarPatternColor { makeRGB(0, 128, 0) };

Ugh, my brain hurts. RGBA32 makeRGBA(), despite the name, returns ARGB which is the argument to the SimpleColor ctor, so this is OK. I don't know why SimpleColor doesn't take a RGBA32, and the names all need fixing.

> Source/WebKit/WebProcess/WebPage/WebFrame.cpp:663
> +    auto [r, g, b, a] = bgColor.toSRGBAComponentsLossy();

Sad that I can't have a P3 frame background.
Comment 9 Darin Adler 2020-05-19 12:03:26 PDT
Comment on attachment 399752 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399752&action=review

>> Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm:136
>> +        color = cachedCGColor(SimpleColor { argb });
> 
> (Not your fault): It blows my mind that the arguments to SimpleColor are argb. Seems very Cocoa-centric, and easy to get wrong. Maybe SimpleColor needs at more scary name like PlatformPixelValue.

We should change the arguments, not the class name. The RGBA32 integer type was widespread in KHTML even before it was ported to Mac, so it’s not Cocoa-centric.

What arguments would you prefer? An aggregate of four uint8_t in RGBA order? I would love to change this to something that makes sense to you.
Comment 10 Simon Fraser (smfr) 2020-05-19 12:16:24 PDT
(In reply to Darin Adler from comment #9)
> Comment on attachment 399752 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=399752&action=review
> 
> >> Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm:136
> >> +        color = cachedCGColor(SimpleColor { argb });
> > 
> > (Not your fault): It blows my mind that the arguments to SimpleColor are argb. Seems very Cocoa-centric, and easy to get wrong. Maybe SimpleColor needs at more scary name like PlatformPixelValue.
> 
> We should change the arguments, not the class name. The RGBA32 integer type
> was widespread in KHTML even before it was ported to Mac, so it’s not
> Cocoa-centric.
> 
> What arguments would you prefer? An aggregate of four uint8_t in RGBA order?
> I would love to change this to something that makes sense to you.

Is the long-term plan to replace RGBA32 with SimpleColor?

Ideally we'd just remove it; it's too tied to the old notion that color fits into a uint32_t, with no colorspace information. Color could have some kind of adaptor, only usable when constructing a color, that explicitly converts from a ARGB into an sRGB color with those components.

Note that ColorComponents, based on std::array<uint8_t, 4>, is basically the same thing with RGBA ordering.
Comment 11 Darin Adler 2020-05-19 12:24:16 PDT
(In reply to Simon Fraser (smfr) from comment #10)
> Is the long-term plan to replace RGBA32 with SimpleColor?

Yes.

> Ideally we'd just remove it; it's too tied to the old notion that color fits
> into a uint32_t, with no colorspace information. Color could have some kind
> of adaptor, only usable when constructing a color, that explicitly converts
> from a ARGB into an sRGB color with those components.

I don’t understand what removing it means. I added it as a type safe replacement for the old RGBA32. Which, by the way, is a hilarious name for an integer containing 8-bit color components ordered ARGB.

But once it was type safe, I had planned to change it to a better interface.

> Note that ColorComponents, based on std::array<uint8_t, 4>, is basically the
> same thing with RGBA ordering.

Sure, we could find a way to merge ColorComponents with SimpleColor.

The idea behind SimpleColor is that it contains 8-bit RGBA components with sRGB color space implied. It should only be used in places where that’s useful. Anywhere we need to handle colors that might not be that simple, we would use Color instead.

I borrowed the name SimpleColor from https://html.spec.whatwg.org/#simple-colour where it’s used for RGB colors, without alpha.
Comment 12 Sam Weinig 2020-05-19 12:26:41 PDT
Created attachment 399759 [details]
Patch
Comment 13 Sam Weinig 2020-05-19 14:40:46 PDT
(In reply to Simon Fraser (smfr) from comment #8)
> Comment on attachment 399752 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=399752&action=review
> 
> 
> > Source/WebCore/platform/graphics/Color.cpp:359
> >          return Color(0x54, 0x54, 0x54, alpha());
> 
> Can we just say 84 rather than 0x54?

Going to fix this in another change. Really it should be colorWithOverrideAlpha(lightenedBlack, alpha()) but there is no overload that works for this yet.

> 
> > Source/WebCore/platform/graphics/Color.cpp:393
> > +    auto [r, g, b, a] = toSRGBAComponentsLossy();
> > +    float largestNonAlphaChannel = std::max(r, std::max(g, b));
> > +    return a > 0.5 && largestNonAlphaChannel < 0.5;
> 
> This should really compute luminance. Maybe a // FIXME

Ok. Will add.

> 
> > Source/WebCore/platform/graphics/Color.cpp:544
> > +    return { ColorSpace::SRGB, FloatComponents { red() / 255.0f, green() / 255.0f, blue() / 255.0f,  alpha() / 255.0f } };
> 
> I feel like the / 255.0f should be in a helper function somewhere. We've
> gone back and forth several times on rounding/flooring of color components
> (e.g. r252598).

Have a name in mind? 

> 
> > Source/WebCore/platform/graphics/cg/ColorCG.cpp:117
> > +        return CGColorCreate(sRGBColorSpaceRef(), components);
> 
> We should use the linearRGBColorSpaceRef here (should fix in a separate bug).

Ok. Will leave.

> 
> > Source/WebCore/platform/graphics/cg/ColorCG.cpp:134
> > +            static CGColorRef whiteCGColor = leakCGColor(color)
> 
> How does this compile?

It didn't. Fixed.

> 
> > Source/WebCore/platform/graphics/cg/GradientCG.cpp:74
> > +        auto [colorSpace, components] = stop.color.colorSpaceAndComponent();
> > +        auto [r, g, b, a] = components;
> 
> This needs a FIXME; we drop colorSpace on the floor.

It's not completely dropping the color space on the floor, but you have to look at the surrounding code. These components will only be used if it's not an ExtendedColor, and therefore we know it's sRGB. The whole function is odd though and wrong. Probably, something needs to confirm that all the colors are in the same color space, or otherwise convert everything to a single colorspace. No sure. Not really clear on how the extendedSRGBColorSpaceRef works.


> > Source/WebKit/WebProcess/WebPage/WebFrame.cpp:663
> > +    auto [r, g, b, a] = bgColor.toSRGBAComponentsLossy();
> 
> Sad that I can't have a P3 frame background.

Probably time for someone to add WKBundleFrameCopyDocumentBackgroundColor that returns a CGColorRef.
Comment 14 Sam Weinig 2020-05-19 14:52:23 PDT
Created attachment 399772 [details]
Patch
Comment 15 Darin Adler 2020-05-19 15:00:42 PDT
Comment on attachment 399772 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399772&action=review

> Source/WebCore/platform/graphics/Color.cpp:393
> +    float largestNonAlphaChannel = std::max(r, std::max(g, b));

I think we could write: std::max({ r, g, b })

> Source/WebCore/platform/graphics/Color.h:97
> +RGBA32 colorWithOverrideAlpha(RGBA32 color, int overrideAlpha);

I’d think we’d want this to be uint8_t, not int.
Comment 16 Sam Weinig 2020-05-19 15:12:56 PDT
Created attachment 399773 [details]
Patch
Comment 17 Sam Weinig 2020-05-19 15:55:41 PDT
(In reply to Sam Weinig from comment #16)
> Created attachment 399773 [details]
> Patch

Hm, MSVC is really not happy with those colorSpace switches.
Comment 18 Sam Weinig 2020-05-19 15:58:32 PDT
Created attachment 399777 [details]
Patch
Comment 19 Sam Weinig 2020-05-19 18:02:58 PDT
Created attachment 399796 [details]
Patch
Comment 20 EWS 2020-05-19 19:14:01 PDT
Committed r261901: <https://trac.webkit.org/changeset/261901>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 399796 [details].
Comment 21 Radar WebKit Bug Importer 2020-05-19 19:15:17 PDT
<rdar://problem/63426594>
Comment 22 Daniel Bates 2020-05-19 22:52:39 PDT
Comment on attachment 399796 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399796&action=review

> Source/WebCore/platform/graphics/win/GradientDirect2D.cpp:75
> +        auto [r, g, b, a] stop.color.toSRGBAComponentsLossy();

=
Comment 23 Sam Weinig 2020-05-20 09:28:37 PDT
(In reply to Daniel Bates from comment #22)
> Comment on attachment 399796 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=399796&action=review
> 
> > Source/WebCore/platform/graphics/win/GradientDirect2D.cpp:75
> > +        auto [r, g, b, a] stop.color.toSRGBAComponentsLossy();
> 
> =

erg. Will fix. 

But, this means we don't have any ews bots building Direct2D support. Do we have any non-EWS build bots building this?