RESOLVED FIXED212059
Remove almost always incorrect Color::getRGBA
https://bugs.webkit.org/show_bug.cgi?id=212059
Summary Remove almost always incorrect Color::getRGBA
Sam Weinig
Reported 2020-05-18 19:40:34 PDT
Simplify Color interface by replacing Color::getRGBA() with a variant returning a FloatComponents
Attachments
Patch (27.67 KB, patch)
2020-05-18 19:48 PDT, Sam Weinig
no flags
Patch (33.93 KB, patch)
2020-05-19 11:15 PDT, Sam Weinig
no flags
Patch (33.74 KB, patch)
2020-05-19 12:26 PDT, Sam Weinig
no flags
Patch (34.09 KB, patch)
2020-05-19 14:52 PDT, Sam Weinig
no flags
Patch (33.83 KB, patch)
2020-05-19 15:12 PDT, Sam Weinig
no flags
Patch (33.96 KB, patch)
2020-05-19 15:58 PDT, Sam Weinig
no flags
Patch (33.98 KB, patch)
2020-05-19 18:02 PDT, Sam Weinig
no flags
Sam Weinig
Comment 1 2020-05-18 19:48:18 PDT
Sam Weinig
Comment 2 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.
Simon Fraser (smfr)
Comment 3 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.
Sam Weinig
Comment 4 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?
Simon Fraser (smfr)
Comment 5 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.
Simon Fraser (smfr)
Comment 6 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.
Sam Weinig
Comment 7 2020-05-19 11:15:25 PDT
Simon Fraser (smfr)
Comment 8 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.
Darin Adler
Comment 9 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.
Simon Fraser (smfr)
Comment 10 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.
Darin Adler
Comment 11 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.
Sam Weinig
Comment 12 2020-05-19 12:26:41 PDT
Sam Weinig
Comment 13 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.
Sam Weinig
Comment 14 2020-05-19 14:52:23 PDT
Darin Adler
Comment 15 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.
Sam Weinig
Comment 16 2020-05-19 15:12:56 PDT
Sam Weinig
Comment 17 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.
Sam Weinig
Comment 18 2020-05-19 15:58:32 PDT
Sam Weinig
Comment 19 2020-05-19 18:02:58 PDT
EWS
Comment 20 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].
Radar WebKit Bug Importer
Comment 21 2020-05-19 19:15:17 PDT
Daniel Bates
Comment 22 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(); =
Sam Weinig
Comment 23 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?
Note You need to log in before you can comment on or make changes to this bug.