Changeset 281470 in webkit


Ignore:
Timestamp:
Aug 23, 2021, 2:36:38 PM (4 years ago)
Author:
Cameron McCormack
Message:

LayoutTests/imported/w3c:
Preserve color space when getting current color in DisplayListDrawGlyphsRecorder.
https://bugs.webkit.org/show_bug.cgi?id=229024
<rdar://problem/81828477>

Reviewed by Sam Weinig.

Add tests for calling fillText() and strokeText() with a display-p3
color for fillStyle, strokeStyle, and shadowColor, on a display-p3 canvas.

  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText-expected.txt: Added.
  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html: Added.
  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow-expected.txt: Added.
  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html: Added.
  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText-expected.txt: Added.
  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html: Added.
  • web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml:

Source/WebCore:
Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
https://bugs.webkit.org/show_bug.cgi?id=229024
<rdar://problem/81828477>

Reviewed by Sam Weinig.

When GPU canvas is enabled, DrawGlyphsRecorder records the text fill,
stroke, and shadow colors by getting them from the context using
CGGStateGetFillColor etc. This is done so that color glyphs have each
part painted in the right color. But the current conversion from
CGColor to WebCore::Color lossily converts to sRGB. So we need to get
the color space and color components from the CGColor and preserve them.

The existing Color(CGColorRef) constructor is replaced by two
constructor functions, createAndPreserveColorSpace and
roundAndClampToSRGBALossy, so the conversion behavior is clear at call
sites. createAndPreserveColorSpace will match the CGColor's color
space to one of the predefined spaces that WebCore::Color can
represent. If it's some other color space, we convert to XYZ (on
platforms where that's available), since that will result in the least
loss, or to sRGB (on platforms where XYZ is not available).

CGColorSpaceEqualToColorSpace, which is used when determining the
CGColor's color space, is not very expensive, but it will do more than a
pointer comparison in case we pass in two CGColorSpaceRefs that are
equivalent but not the same pointer value. Since our new
colorSpaceForCGColorSpace function will be used with CGColors that have
been set WebCore during canvas drawing, we will get back the same
pointers that we have cached in sRGBColorSpaceRef(),
displayP3ColorSpaceRef(), etc. If calling CGColorSpaceEqualToColorSpace
on all our supported color spaces turns out to be too expensive, we
could start by doing a pointer comparison on each before calling
CGColorSpaceEqualToColorSpace.

The way colorSpaceForCGColorSpace is written we could end up
instantiating all of our supported color spaces, if an author used an
XYZ color when drawing text (the last color profile we check). We
could try harder to avoid doing this if it's important.

Tests: imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html

imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html
imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html

  • page/CaptionUserPreferencesMediaAF.cpp:

(WebCore::CaptionUserPreferencesMediaAF::captionsWindowCSS const):
(WebCore::CaptionUserPreferencesMediaAF::captionsBackgroundCSS const):
(WebCore::CaptionUserPreferencesMediaAF::captionsTextColor const):

  • platform/graphics/Color.h:

(WebCore::Color::createAndPreserveColorSpace):
(WebCore::Color::createAndLosslesslyConvertToSupportedColorSpace):

  • platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:

(WebCore::PlatformCALayerCocoa::backgroundColor const):

  • platform/graphics/ca/cocoa/WebTiledBackingLayer.mm:

(-[WebTiledBackingLayer setBorderColor:]):

  • platform/graphics/ca/win/PlatformCALayerWin.cpp:

(PlatformCALayerWin::backgroundColor const):
(printColor):

  • platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:

(PlatformCALayerWinInternal::drawRepaintCounters):

  • platform/graphics/cg/ColorCG.cpp:

(WebCore::roundAndClampToSRGBALossy):
(WebCore::Color::createAndLosslesslyConvertToSupportedColorSpace):
(WebCore::Color::createAndPreserveColorSpace):
(WebCore::platformConvertColorComponents):

  • platform/graphics/cg/ColorSpaceCG.cpp:

(WebCore::colorSpaceForCGColorSpace):

  • platform/graphics/cg/ColorSpaceCG.h:
  • platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp:

(WebCore::DisplayList::DrawGlyphsRecorder::updateShadow):
(WebCore::DisplayList::DrawGlyphsRecorder::recordDrawGlyphs):

  • platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp:

(WebCore::MediaPlayerPrivateFullscreenWindow::setRootChildLayer):

  • platform/ios/PlatformPasteboardIOS.mm:

(WebCore::PlatformPasteboard::color):

  • rendering/RenderThemeIOS.mm:

(WebCore::systemColorFromCSSValueSystemColorInformation):

Source/WebKit:
Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
https://bugs.webkit.org/show_bug.cgi?id=229024
<rdar://problem/81828477>

Reviewed by Sam Weinig.

Change existing CGColor -> WebCore::Color conversions to be explicit
about lossily converting to sRGB.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView setUnderPageBackgroundColor:]):

  • UIProcess/API/Cocoa/_WKApplicationManifest.mm:

(-[_WKApplicationManifest initWithCoder:]):

  • UIProcess/mac/WebPageProxyMac.mm:

(WebKit::WebPageProxy::platformUnderPageBackgroundColor const):

  • WebProcess/Plugins/PDF/PDFPlugin.mm:

(WebKit::PDFPlugin::PDFPlugin):

Tools:
Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
https://bugs.webkit.org/show_bug.cgi?id=229024
<rdar://problem/81828477>

Reviewed by Sam Weinig.

Change existing CGColor -> WebCore::Color conversions to be explicit
about lossily converting to sRGB.

  • TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm:

(TEST):

Location:
trunk
Files:
6 added
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r281465 r281470  
     12021-08-23  Cameron McCormack  <heycam@apple.com>
     2
     3        Preserve color space when getting current color in DisplayListDrawGlyphsRecorder.
     4        https://bugs.webkit.org/show_bug.cgi?id=229024
     5        <rdar://problem/81828477>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Add tests for calling fillText() and strokeText() with a display-p3
     10        color for fillStyle, strokeStyle, and shadowColor, on a display-p3 canvas.
     11
     12        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText-expected.txt: Added.
     13        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html: Added.
     14        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow-expected.txt: Added.
     15        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html: Added.
     16        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText-expected.txt: Added.
     17        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html: Added.
     18        * web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml:
     19
    1202021-08-23  Alan Bujtas  <zalan@apple.com>
    221
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml

    r279427 r281470  
    176176    });
    177177    image.src = canvas.toDataURL();
     178
     179- name: 2d.color.space.p3.fillText
     180  testing:
     181  - 2d.color.space.p3.and.uint8
     182  desc: Test if fillText can be used with a solid display-p3 color
     183  attributes: |
     184    {colorSpace: "display-p3"}
     185  code: |
     186    deferTest();
     187
     188    const fullRedInP3 = [255, 0, 0, 255];
     189    const sRGBRedInP3 = [234, 51, 35, 255];
     190
     191    canvas.width = 100;
     192    canvas.height = 100;
     193
     194    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
     195    document.fonts.add(f);
     196    f.load().then(function() {
     197        t.step(function() {
     198            ctx.font = "40px Ahem";
     199
     200            ctx.fillStyle = "#f00";
     201            ctx.fillText("A", 0, 50);
     202
     203            ctx.fillStyle = "black";
     204            ctx.fillStyle = "color(display-p3 100% 0 0)";
     205            ctx.fillText("A", 50, 50);
     206
     207            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
     208            let pixelAt = function(x, y) {
     209                let offset = (y * canvas.width + x) * 4;
     210                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
     211            };
     212
     213            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
     214            assert_array_equals(pixelAt(75, 25), fullRedInP3);
     215
     216            t.done();
     217        });
     218    });
     219
     220- name: 2d.color.space.p3.strokeText
     221  testing:
     222  - 2d.color.space.p3.and.uint8
     223  desc: Test if strokeText can be used with a solid display-p3 color
     224  attributes: |
     225    {colorSpace: "display-p3"}
     226  code: |
     227    deferTest();
     228
     229    const fullRedInP3 = [255, 0, 0, 255];
     230    const sRGBRedInP3 = [234, 51, 35, 255];
     231
     232    canvas.width = 100;
     233    canvas.height = 100;
     234
     235    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
     236    document.fonts.add(f);
     237    f.load().then(function() {
     238        t.step(function() {
     239            ctx.font = "40px Ahem";
     240
     241            ctx.strokeStyle = "#f00";
     242            ctx.lineWidth = 20;
     243            ctx.strokeText("A", 0, 50);
     244
     245            ctx.strokeStyle = "black";
     246            ctx.strokeStyle = "color(display-p3 100% 0 0)";
     247            ctx.strokeText("A", 50, 50);
     248
     249            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
     250            let pixelAt = function(x, y) {
     251                let offset = (y * canvas.width + x) * 4;
     252                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
     253            };
     254
     255            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
     256            assert_array_equals(pixelAt(75, 25), fullRedInP3);
     257
     258            t.done();
     259        });
     260    });
     261
     262- name: 2d.color.space.p3.fillText.shadow
     263  testing:
     264  - 2d.color.space.p3.and.uint8
     265  desc: Test if fillText can be used with a display-p3 shadow color
     266  attributes: |
     267    {colorSpace: "display-p3"}
     268  code: |
     269    deferTest();
     270
     271    const fullRedInP3 = [255, 0, 0, 255];
     272    const sRGBRedInP3 = [234, 51, 35, 255];
     273
     274    canvas.width = 100;
     275    canvas.height = 100;
     276
     277    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
     278    document.fonts.add(f);
     279    f.load().then(function() {
     280        t.step(function() {
     281            ctx.font = "40px Ahem";
     282
     283            ctx.fillStyle = "black";
     284            ctx.shadowBlur = 4;
     285            ctx.shadowOffsetX = 0;
     286            ctx.shadowOffsetY = 50;
     287            ctx.shadowColor = "#f00";
     288            ctx.fillText("A", 0, 0);
     289
     290            ctx.shadowColor = "black";
     291            ctx.shadowColor = "color(display-p3 100% 0 0)";
     292            ctx.fillText("A", 50, 0);
     293
     294            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
     295            let pixelAt = function(x, y) {
     296                let offset = (y * canvas.width + x) * 4;
     297                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
     298            };
     299
     300            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
     301            assert_array_equals(pixelAt(75, 25), fullRedInP3);
     302
     303            t.done();
     304        });
     305    });
  • trunk/Source/WebCore/ChangeLog

    r281465 r281470  
     12021-08-23  Cameron McCormack  <heycam@apple.com>
     2
     3        Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
     4        https://bugs.webkit.org/show_bug.cgi?id=229024
     5        <rdar://problem/81828477>
     6
     7        Reviewed by Sam Weinig.
     8
     9        When GPU canvas is enabled, DrawGlyphsRecorder records the text fill,
     10        stroke, and shadow colors by getting them from the context using
     11        CGGStateGetFillColor etc.  This is done so that color glyphs have each
     12        part painted in the right color.  But the current conversion from
     13        CGColor to WebCore::Color lossily converts to sRGB.  So we need to get
     14        the color space and color components from the CGColor and preserve them.
     15
     16        The existing Color(CGColorRef) constructor is replaced by two
     17        constructor functions, createAndPreserveColorSpace and
     18        roundAndClampToSRGBALossy, so the conversion behavior is clear at call
     19        sites.  createAndPreserveColorSpace will match the CGColor's color
     20        space to one of the predefined spaces that WebCore::Color can
     21        represent.  If it's some other color space, we convert to XYZ (on
     22        platforms where that's available), since that will result in the least
     23        loss, or to sRGB (on platforms where XYZ is not available).
     24
     25        CGColorSpaceEqualToColorSpace, which is used when determining the
     26        CGColor's color space, is not very expensive, but it will do more than a
     27        pointer comparison in case we pass in two CGColorSpaceRefs that are
     28        equivalent but not the same pointer value.  Since our new
     29        colorSpaceForCGColorSpace function will be used with CGColors that have
     30        been set WebCore during canvas drawing, we will get back the same
     31        pointers that we have cached in sRGBColorSpaceRef(),
     32        displayP3ColorSpaceRef(), etc.  If calling CGColorSpaceEqualToColorSpace
     33        on all our supported color spaces turns out to be too expensive, we
     34        could start by doing a pointer comparison on each before calling
     35        CGColorSpaceEqualToColorSpace.
     36
     37        The way colorSpaceForCGColorSpace is written we could end up
     38        instantiating all of our supported color spaces, if an author used an
     39        XYZ color when drawing text (the last color profile we check).  We
     40        could try harder to avoid doing this if it's important.
     41
     42        Tests: imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html
     43               imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html
     44               imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html
     45
     46        * page/CaptionUserPreferencesMediaAF.cpp:
     47        (WebCore::CaptionUserPreferencesMediaAF::captionsWindowCSS const):
     48        (WebCore::CaptionUserPreferencesMediaAF::captionsBackgroundCSS const):
     49        (WebCore::CaptionUserPreferencesMediaAF::captionsTextColor const):
     50        * platform/graphics/Color.h:
     51        (WebCore::Color::createAndPreserveColorSpace):
     52        (WebCore::Color::createAndLosslesslyConvertToSupportedColorSpace):
     53        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
     54        (WebCore::PlatformCALayerCocoa::backgroundColor const):
     55        * platform/graphics/ca/cocoa/WebTiledBackingLayer.mm:
     56        (-[WebTiledBackingLayer setBorderColor:]):
     57        * platform/graphics/ca/win/PlatformCALayerWin.cpp:
     58        (PlatformCALayerWin::backgroundColor const):
     59        (printColor):
     60        * platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:
     61        (PlatformCALayerWinInternal::drawRepaintCounters):
     62        * platform/graphics/cg/ColorCG.cpp:
     63        (WebCore::roundAndClampToSRGBALossy):
     64        (WebCore::Color::createAndLosslesslyConvertToSupportedColorSpace):
     65        (WebCore::Color::createAndPreserveColorSpace):
     66        (WebCore::platformConvertColorComponents):
     67        * platform/graphics/cg/ColorSpaceCG.cpp:
     68        (WebCore::colorSpaceForCGColorSpace):
     69        * platform/graphics/cg/ColorSpaceCG.h:
     70        * platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp:
     71        (WebCore::DisplayList::DrawGlyphsRecorder::updateShadow):
     72        (WebCore::DisplayList::DrawGlyphsRecorder::recordDrawGlyphs):
     73        * platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp:
     74        (WebCore::MediaPlayerPrivateFullscreenWindow::setRootChildLayer):
     75        * platform/ios/PlatformPasteboardIOS.mm:
     76        (WebCore::PlatformPasteboard::color):
     77        * rendering/RenderThemeIOS.mm:
     78        (WebCore::systemColorFromCSSValueSystemColorInformation):
     79
    1802021-08-23  Alan Bujtas  <zalan@apple.com>
    281
  • trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp

    r279720 r281470  
    318318    RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyWindowColor(kMACaptionAppearanceDomainUser, &behavior));
    319319
    320     Color windowColor(color.get());
     320    Color windowColor(roundAndClampToSRGBALossy(color.get()));
    321321    if (!windowColor.isValid())
    322322        windowColor = Color::transparentBlack;
     
    343343
    344344    RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyBackgroundColor(kMACaptionAppearanceDomainUser, &behavior));
    345     Color backgroundColor(color.get());
     345    Color backgroundColor(roundAndClampToSRGBALossy(color.get()));
    346346    if (!backgroundColor.isValid())
    347347        backgroundColor = defaultBackgroundColor;
     
    357357{
    358358    MACaptionAppearanceBehavior behavior;
    359     Color textColor = adoptCF(MACaptionAppearanceCopyForegroundColor(kMACaptionAppearanceDomainUser, &behavior)).get();
     359    RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyForegroundColor(kMACaptionAppearanceDomainUser, &behavior)).get();
     360    Color textColor(roundAndClampToSRGBALossy(color.get()));
    360361    if (!textColor.isValid()) {
    361362        // This default value must be the same as the one specified in mediaControls.css for -webkit-media-text-track-container.
  • trunk/Source/WebCore/platform/graphics/Color.h

    r278340 r281470  
    151151
    152152#if USE(CG)
    153     WEBCORE_EXPORT Color(CGColorRef, OptionSet<Flags> = { });
     153    WEBCORE_EXPORT static Color createAndPreserveColorSpace(CGColorRef, OptionSet<Flags> = { });
    154154#endif
    155155
     
    208208    Color(Ref<OutOfLineComponents>&&, ColorSpace, OptionSet<Flags> = { });
    209209
     210#if USE(CG)
     211    WEBCORE_EXPORT static Color createAndLosslesslyConvertToSupportedColorSpace(CGColorRef, OptionSet<Flags> = { });
     212#endif
     213
    210214    enum class FlagsIncludingPrivate : uint8_t {
    211215        Semantic                        = static_cast<uint8_t>(Flags::Semantic),
     
    269273WEBCORE_EXPORT CGColorRef cachedCGColor(const Color&);
    270274WEBCORE_EXPORT ColorComponents<float, 4> platformConvertColorComponents(ColorSpace, ColorComponents<float, 4>, const DestinationColorSpace&);
     275WEBCORE_EXPORT std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef);
    271276#endif
    272277
  • trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm

    r280467 r281470  
    821821Color PlatformCALayerCocoa::backgroundColor() const
    822822{
    823     return [m_layer backgroundColor];
     823    return roundAndClampToSRGBALossy([m_layer backgroundColor]);
    824824}
    825825
  • trunk/Source/WebCore/platform/graphics/ca/cocoa/WebTiledBackingLayer.mm

    r259871 r281470  
    148148- (void)setBorderColor:(CGColorRef)borderColor
    149149{
    150     _tileController->setTileDebugBorderColor(WebCore::Color(borderColor));
     150    _tileController->setTileDebugBorderColor(WebCore::roundAndClampToSRGBALossy(borderColor));
    151151}
    152152
  • trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp

    r278062 r281470  
    573573Color PlatformCALayerWin::backgroundColor() const
    574574{
    575     return CACFLayerGetBackgroundColor(m_layer.get());
     575    return roundAndClampToSRGBALossy(CACFLayerGetBackgroundColor(m_layer.get()));
    576576}
    577577
     
    704704static void printColor(StringBuilder& builder, int indent, const String& label, CGColorRef color)
    705705{
    706     Color layerColor(color);
     706    Color layerColor(roundAndClampToSRGBALossy(color));
    707707    if (!layerColor.isValid())
    708708        return;
  • trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp

    r278062 r281470  
    131131
    132132    GraphicsContextCG graphicsContext(context);
    133     PlatformCALayer::drawRepaintIndicator(graphicsContext, owner(), drawCount, backgroundColor);
     133    PlatformCALayer::drawRepaintIndicator(graphicsContext, owner(), drawCount, roundAndClampToSRGBALossy(backgroundColor));
    134134}
    135135
  • trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp

    r278253 r281470  
    5555namespace WebCore {
    5656
    57 static std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef color)
    58 {
    59     // FIXME: ExtendedColor - needs to handle color spaces.
     57std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef color)
     58{
     59    // FIXME: Interpreting components of a color in an arbitrary color space
     60    // as sRGB could be wrong, not just lossy.
    6061
    6162    if (!color)
     
    8889}
    8990
    90 Color::Color(CGColorRef color, OptionSet<Flags> flags)
    91     : Color(roundAndClampToSRGBALossy(color), flags)
    92 {
     91Color Color::createAndLosslesslyConvertToSupportedColorSpace(CGColorRef color, OptionSet<Flags> flags)
     92{
     93    auto sourceCGColorSpace = CGColorGetColorSpace(color);
     94#if HAVE(CORE_GRAPHICS_XYZ_COLOR_SPACE)
     95    auto destinationCGColorSpace = xyzColorSpaceRef();
     96    auto destinationColorSpace = ColorSpace::XYZ_D50;
     97#else
     98    auto destinationCGColorSpace = sRGBColorSpaceRef();
     99    auto destinationColorSpace = ColorSpace::SRGB;
     100#endif
     101    ASSERT(CGColorSpaceGetNumberOfComponents(destinationCGColorSpace) == 3);
     102
     103    auto sourceComponents = CGColorGetComponents(color);
     104    CGFloat destinationComponents[3] { };
     105
     106    auto transform = adoptCF(CGColorTransformCreate(destinationCGColorSpace, nullptr));
     107    auto result = CGColorTransformConvertColorComponents(transform.get(), sourceCGColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
     108    ASSERT_UNUSED(result, result);
     109
     110    float a = destinationComponents[0];
     111    float b = destinationComponents[1];
     112    float c = destinationComponents[2];
     113    float alpha = CGColorGetAlpha(color);
     114
     115    return Color(OutOfLineComponents::create({ a, b, c, alpha }), destinationColorSpace, flags);
     116}
     117
     118Color Color::createAndPreserveColorSpace(CGColorRef color, OptionSet<Flags> flags)
     119{
     120    if (!color)
     121        return Color();
     122
     123    size_t numComponents = CGColorGetNumberOfComponents(color);
     124    auto colorSpace = colorSpaceForCGColorSpace(CGColorGetColorSpace(color));
     125
     126    if (numComponents != 4 || !colorSpace)
     127        return createAndLosslesslyConvertToSupportedColorSpace(color, flags);
     128
     129    const CGFloat* components = CGColorGetComponents(color);
     130
     131    float a = components[0];
     132    float b = components[1];
     133    float c = components[2];
     134    float alpha = components[3];
     135
     136    return Color(OutOfLineComponents::create({ a, b, c, alpha }), *colorSpace, flags);
    93137}
    94138
     
    182226    auto result = CGColorTransformConvertColorComponents(transform.get(), cgInputColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
    183227    ASSERT_UNUSED(result, result);
     228    // FIXME: CGColorTransformConvertColorComponents doesn't copy over any alpha component.
    184229    return { static_cast<float>(destinationComponents[0]), static_cast<float>(destinationComponents[1]), static_cast<float>(destinationComponents[2]), static_cast<float>(destinationComponents[3]) };
    185230}
  • trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp

    r274256 r281470  
    109109#endif
    110110
     111std::optional<ColorSpace> colorSpaceForCGColorSpace(CGColorSpaceRef colorSpace)
     112{
     113    if (CGColorSpaceEqualToColorSpace(colorSpace, sRGBColorSpaceRef()))
     114        return ColorSpace::SRGB;
     115
     116#if HAVE(CORE_GRAPHICS_ADOBE_RGB_1998_COLOR_SPACE)
     117    if (CGColorSpaceEqualToColorSpace(colorSpace, adobeRGB1998ColorSpaceRef()))
     118        return ColorSpace::A98RGB;
     119#endif
     120
     121#if HAVE(CORE_GRAPHICS_DISPLAY_P3_COLOR_SPACE)
     122    if (CGColorSpaceEqualToColorSpace(colorSpace, displayP3ColorSpaceRef()))
     123        return ColorSpace::DisplayP3;
     124#endif
     125
     126    // FIXME: labColorSpaceRef() not implemented.
     127
     128#if HAVE(CORE_GRAPHICS_LINEAR_SRGB_COLOR_SPACE)
     129    if (CGColorSpaceEqualToColorSpace(colorSpace, linearSRGBColorSpaceRef()))
     130        return ColorSpace::LinearSRGB;
     131#endif
     132
     133#if HAVE(CORE_GRAPHICS_ROMMRGB_COLOR_SPACE)
     134    if (CGColorSpaceEqualToColorSpace(colorSpace, ROMMRGBColorSpaceRef()))
     135        return ColorSpace::ProPhotoRGB;
     136#endif
     137
     138#if HAVE(CORE_GRAPHICS_ITUR_2020_COLOR_SPACE)
     139    if (CGColorSpaceEqualToColorSpace(colorSpace, ITUR_2020ColorSpaceRef()))
     140        return ColorSpace::Rec2020;
     141#endif
     142
     143#if HAVE(CORE_GRAPHICS_XYZ_COLOR_SPACE)
     144    if (CGColorSpaceEqualToColorSpace(colorSpace, xyzColorSpaceRef()))
     145        return ColorSpace::XYZ_D50;
     146#endif
     147
     148    return std::nullopt;
     149}
     150
    111151}
    112152
  • trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h

    r277986 r281470  
    2727
    2828#include "ColorSpace.h"
     29#include <optional>
    2930
    3031typedef struct CGColorSpace *CGColorSpaceRef;
     
    6566WEBCORE_EXPORT CGColorSpaceRef xyzColorSpaceRef();
    6667#endif
     68
     69std::optional<ColorSpace> colorSpaceForCGColorSpace(CGColorSpaceRef);
    6770
    6871static inline CGColorSpaceRef cachedNullableCGColorSpace(ColorSpace colorSpace)
  • trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp

    r278253 r281470  
    262262    auto rad = deg2rad(shadowStyle.azimuth - 180);
    263263    auto shadowOffset = FloatSize(std::cos(rad), std::sin(rad)) * shadowStyle.height;
    264     updateShadow(shadowOffset, shadowStyle.radius, CGStyleGetColor(style), ShadowsIgnoreTransforms::Yes);
     264    auto shadowColor = CGStyleGetColor(style);
     265    updateShadow(shadowOffset, shadowStyle.radius, Color::createAndPreserveColorSpace(shadowColor), ShadowsIgnoreTransforms::Yes);
    265266}
    266267
     
    331332    m_owner.concatCTM(ctmFixup);
    332333
    333     updateFillColor(CGGStateGetFillColor(gstate));
    334     updateStrokeColor(CGGStateGetStrokeColor(gstate));
     334    auto fillColor = CGGStateGetFillColor(gstate);
     335    auto strokeColor = CGGStateGetStrokeColor(gstate);
     336    updateFillColor(Color::createAndPreserveColorSpace(fillColor));
     337    updateStrokeColor(Color::createAndPreserveColorSpace(strokeColor));
    335338    updateShadow(CGGStateGetStyle(gstate));
    336339
  • trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp

    r239092 r281470  
    117117    m_rootChild->setPosition(rootBounds.origin);
    118118    m_rootChild->setBounds(FloatRect(FloatPoint(), FloatSize(rootBounds.size)));
    119     m_rootChild->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack));
     119    m_rootChild->setBackgroundColor(Color::black);
    120120#ifndef NDEBUG
    121     RetainPtr<CGColorRef> redColor = adoptCF(CGColorCreateGenericRGB(1, 0, 0, 1));
    122     rootLayer->setBackgroundColor(redColor.get());
     121    rootLayer->setBackgroundColor(Color::red);
    123122#else
    124     rootLayer->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack));
     123    rootLayer->setBackgroundColor(Color::black);
    125124#endif
    126125}
  • trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm

    r278253 r281470  
    316316    NSData *data = [m_pasteboard dataForPasteboardType:UIColorPboardType];
    317317    UIColor *uiColor = [NSKeyedUnarchiver unarchivedObjectOfClass:PAL::getUIColorClass() fromData:data error:nil];
    318     return Color(uiColor.CGColor);
     318    return roundAndClampToSRGBALossy(uiColor.CGColor);
    319319}
    320320
  • trunk/Source/WebCore/rendering/RenderThemeIOS.mm

    r279795 r281470  
    13451345{
    13461346    if (auto color = wtfObjCMsgSend<UIColor *>(PAL::getUIColorClass(), systemColorInformation.selector)) {
    1347         Color systemColor = { color.CGColor, Color::Flags::Semantic };
     1347        Color systemColor(roundAndClampToSRGBALossy(color.CGColor), Color::Flags::Semantic);
    13481348
    13491349        if (systemColorInformation.opacity < 1.0f)
  • trunk/Source/WebKit/ChangeLog

    r281450 r281470  
     12021-08-23  Cameron McCormack  <heycam@apple.com>
     2
     3        Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
     4        https://bugs.webkit.org/show_bug.cgi?id=229024
     5        <rdar://problem/81828477>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Change existing CGColor -> WebCore::Color conversions to be explicit
     10        about lossily converting to sRGB.
     11
     12        * UIProcess/API/Cocoa/WKWebView.mm:
     13        (-[WKWebView setUnderPageBackgroundColor:]):
     14        * UIProcess/API/Cocoa/_WKApplicationManifest.mm:
     15        (-[_WKApplicationManifest initWithCoder:]):
     16        * UIProcess/mac/WebPageProxyMac.mm:
     17        (WebKit::WebPageProxy::platformUnderPageBackgroundColor const):
     18        * WebProcess/Plugins/PDF/PDFPlugin.mm:
     19        (WebKit::PDFPlugin::PDFPlugin):
     20
    1212021-08-23  Wenson Hsieh  <wenson_hsieh@apple.com>
    222
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r281332 r281470  
    17851785- (void)setUnderPageBackgroundColor:(CocoaColor *)underPageBackgroundColorOverride
    17861786{
    1787     _page->setUnderPageBackgroundColorOverride(underPageBackgroundColorOverride.CGColor);
     1787    _page->setUnderPageBackgroundColorOverride(WebCore::roundAndClampToSRGBALossy(underPageBackgroundColorOverride.CGColor));
    17881788}
    17891789
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.mm

    r276333 r281470  
    6868        static_cast<WebCore::ApplicationManifest::Display>(display),
    6969        URL(startURL),
    70         WebCore::Color(themeColor.CGColor),
     70        WebCore::roundAndClampToSRGBALossy(themeColor.CGColor),
    7171    };
    7272
  • trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm

    r281246 r281470  
    482482{
    483483    if (webView->_customContentView)
    484         return [webView->_customContentView backgroundColor].CGColor;
     484        return WebCore::roundAndClampToSRGBALossy([webView->_customContentView backgroundColor].CGColor);
    485485
    486486    if (webView->_gestureController) {
     
    508508
    509509    if (!color.isValid() && webView->_contentView)
    510         color = [webView->_contentView backgroundColor].CGColor;
     510        color = WebCore::roundAndClampToSRGBALossy([webView->_contentView backgroundColor].CGColor);
    511511
    512512    if (!color.isValid()) {
    513513#if HAVE(OS_DARK_MODE_SUPPORT)
    514         color = UIColor.systemBackgroundColor.CGColor;
     514        color = WebCore::roundAndClampToSRGBALossy(UIColor.systemBackgroundColor.CGColor);
    515515#else
    516516        color = WebCore::Color::white;
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm

    r281279 r281470  
    10161016WebCore::Color PageClientImpl::contentViewBackgroundColor()
    10171017{
    1018     return [m_contentView backgroundColor].CGColor;
     1018    return WebCore::roundAndClampToSRGBALossy([m_contentView backgroundColor].CGColor);
    10191019}
    10201020
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r281277 r281470  
    36313631- (void)_setTextColorForWebView:(UIColor *)color sender:(id)sender
    36323632{
    3633     _page->executeEditCommand("ForeColor"_s, WebCore::serializationForHTML(WebCore::Color(color.CGColor)));
     3633    WebCore::Color textColor(WebCore::roundAndClampToSRGBALossy(color.CGColor));
     3634    _page->executeEditCommand("ForeColor"_s, WebCore::serializationForHTML(textColor));
    36343635}
    36353636
     
    48724873- (void)updateFocusedElementValueAsColor:(UIColor *)value
    48734874{
    4874     WebCore::Color color(value.CGColor);
     4875    WebCore::Color color(WebCore::roundAndClampToSRGBALossy(value.CGColor));
    48754876    String valueAsString = WebCore::serializationForHTML(color);
    48764877
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r281279 r281470  
    15601560
    15611561#if HAVE(OS_DARK_MODE_SUPPORT)
    1562     return UIColor.systemBackgroundColor.CGColor;
     1562    return WebCore::roundAndClampToSRGBALossy(UIColor.systemBackgroundColor.CGColor);
    15631563#else
    1564     return UIColor.whiteColor.CGColor;
     1564    return WebCore::Color::white;
    15651565#endif
    15661566}
  • trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm

    r280736 r281470  
    729729{
    730730#if ENABLE(DARK_MODE_CSS)
    731     return NSColor.controlBackgroundColor.CGColor;
     731    return WebCore::roundAndClampToSRGBALossy(NSColor.controlBackgroundColor.CGColor);
    732732#else
    733     return NSColor.whiteColor.CGColor;
     733    return WebCore::Color::white;
    734734#endif
    735735}
  • trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm

    r279826 r281470  
    625625
    626626        // FIXME: <rdar://problem/75332948> get the background color from PDFKit instead of hardcoding it
    627         document->bodyOrFrameset()->setInlineStyleProperty(WebCore::CSSPropertyBackgroundColor, WebCore::serializationForHTML([CocoaColor grayColor].CGColor));
     627        document->bodyOrFrameset()->setInlineStyleProperty(WebCore::CSSPropertyBackgroundColor, WebCore::serializationForHTML(WebCore::roundAndClampToSRGBALossy([CocoaColor grayColor].CGColor)));
    628628    }
    629629
  • trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm

    r281247 r281470  
    444444            ALLOW_DEPRECATED_DECLARATIONS_END
    445445#else
    446             WebCore::Color color = WebCore::Color(backgroundColor);
     446            WebCore::Color color(WebCore::roundAndClampToSRGBALossy(backgroundColor));
    447447#endif
    448448            view->setBaseBackgroundColor(color);
     
    13891389- (void)setCaretColor:(CGColorRef)color
    13901390{
    1391     WebCore::Color qColor = color ? WebCore::Color(color) : WebCore::Color::black;
     1391    WebCore::Color qColor = color ? WebCore::Color(WebCore::roundAndClampToSRGBALossy(color)) : WebCore::Color::black;
    13921392    WebCore::Frame *frame = core(self);
    13931393    frame->selection().setCaretColor(qColor);
  • trunk/Tools/ChangeLog

    r281468 r281470  
     12021-08-23  Cameron McCormack  <heycam@apple.com>
     2
     3        Preserve color space when getting current color in DisplayList::DrawGlyphsRecorder
     4        https://bugs.webkit.org/show_bug.cgi?id=229024
     5        <rdar://problem/81828477>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Change existing CGColor -> WebCore::Color conversions to be explicit
     10        about lossily converting to sRGB.
     11
     12        * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm:
     13        (TEST):
     14
    1152021-08-23  Wenson Hsieh  <wenson_hsieh@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm

    r278189 r281470  
    150150
    151151    waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops("right"_s, { "red"_s, "red"_s }));
    152     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
     152    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
    153153}
    154154
     
    302302
    303303    waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<body style='margin: 0'><canvas style='width: 100%; height: 100%; background-color: red'></canvas>Test");
    304     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
     304    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
    305305}
    306306
     
    329329
    330330    waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<body style='margin: 0; transition: background-color 1s'>Test");
    331     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     331    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
    332332}
    333333
     
    361361    [webView objectByEvaluatingJavaScript:@"document.body.textContent = 'Test'"];
    362362    waitForSampledPageTopColorToChange(webView.get());
    363     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
     363    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
    364364}
    365365
     
    370370
    371371    waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<style>@keyframes changeBackgroundRed { to { background-color: red; } }</style><body style='margin: 0; animation: changeBackgroundRed 1s forwards paused'>Test");
    372     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     372    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
    373373}
    374374
     
    400400    [webView objectByEvaluatingJavaScript:@"document.body.textContent = 'Test'"];
    401401    waitForSampledPageTopColorToChange(webView.get());
    402     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
     402    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
    403403}
    404404
     
    409409
    410410    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body style='margin: 0'><div style='width: 100%; height: 100%; background-color: red; pointer-events: none'></div>Test"];
    411     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
     411    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
    412412}
    413413
     
    444444
    445445    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
    446     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     446    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
    447447    EXPECT_EQ(notificationCount, 1UL);
    448448
     
    450450
    451451    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
    452     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     452    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
    453453    // Depending on timing, a notification can be sent for when the main document changes and then
    454454    // when the new main document renders or both can be coalesced if rendering is fast enough.
     
    470470
    471471    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
    472     EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     472    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
    473473    EXPECT_EQ(notificationCount, 1UL);
    474474}
Note: See TracChangeset for help on using the changeset viewer.