Title: [281470] trunk
Revision
281470
Author
hey...@apple.com
Date
2021-08-23 14:36:38 -0700 (Mon, 23 Aug 2021)

Log 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):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (281469 => 281470)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1,3 +1,22 @@
+2021-08-23  Cameron McCormack  <hey...@apple.com>
+
+        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:
+
 2021-08-23  Alan Bujtas  <za...@apple.com>
 
         Simplified text measuring only works with the primary font

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText-expected.txt (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText-expected.txt	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,6 @@
+2d.color.space.p3.fillText
+Test if fillText can be used with a solid display-p3 color
+Actual output:
+
+PASS Test if fillText can be used with a solid display-p3 color
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.html	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.color.space.p3.fillText</title>
+<script src=""
+<script src=""
+<script src=""
+<link rel="stylesheet" href=""
+<body class="show_output">
+
+<h1>2d.color.space.p3.fillText</h1>
+<p class="desc">Test if fillText can be used with a solid display-p3 color</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test if fillText can be used with a solid display-p3 color");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+
+const fullRedInP3 = [255, 0, 0, 255];
+const sRGBRedInP3 = [234, 51, 35, 255];
+
+canvas.width = 100;
+canvas.height = 100;
+
+let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+document.fonts.add(f);
+f.load().then(function() {
+    t.step(function() {
+        ctx.font = "40px Ahem";
+
+        ctx.fillStyle = "#f00";
+        ctx.fillText("A", 0, 50);
+
+        ctx.fillStyle = "black";
+        ctx.fillStyle = "color(display-p3 100% 0 0)";
+        ctx.fillText("A", 50, 50);
+
+        let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+        let pixelAt = function(x, y) {
+            let offset = (y * canvas.width + x) * 4;
+            return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+        };
+
+        assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+        assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+        t.done();
+    });
+});
+
+
+}, {colorSpace: "display-p3"});
+</script>
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow-expected.txt (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow-expected.txt	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,6 @@
+2d.color.space.p3.fillText.shadow
+Test if fillText can be used with a display-p3 shadow color
+Actual output:
+
+PASS Test if fillText can be used with a display-p3 shadow color
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.fillText.shadow.html	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.color.space.p3.fillText.shadow</title>
+<script src=""
+<script src=""
+<script src=""
+<link rel="stylesheet" href=""
+<body class="show_output">
+
+<h1>2d.color.space.p3.fillText.shadow</h1>
+<p class="desc">Test if fillText can be used with a display-p3 shadow color</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test if fillText can be used with a display-p3 shadow color");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+
+const fullRedInP3 = [255, 0, 0, 255];
+const sRGBRedInP3 = [234, 51, 35, 255];
+
+canvas.width = 100;
+canvas.height = 100;
+
+let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+document.fonts.add(f);
+f.load().then(function() {
+    t.step(function() {
+        ctx.font = "40px Ahem";
+
+        ctx.fillStyle = "black";
+        ctx.shadowBlur = 4;
+        ctx.shadowOffsetX = 0;
+        ctx.shadowOffsetY = 50;
+        ctx.shadowColor = "#f00";
+        ctx.fillText("A", 0, 0);
+
+        ctx.shadowColor = "black";
+        ctx.shadowColor = "color(display-p3 100% 0 0)";
+        ctx.fillText("A", 50, 0);
+
+        let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+        let pixelAt = function(x, y) {
+            let offset = (y * canvas.width + x) * 4;
+            return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+        };
+
+        assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+        assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+        t.done();
+    });
+});
+
+
+}, {colorSpace: "display-p3"});
+</script>
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText-expected.txt (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText-expected.txt	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,6 @@
+2d.color.space.p3.strokeText
+Test if strokeText can be used with a solid display-p3 color
+Actual output:
+
+PASS Test if strokeText can be used with a solid display-p3 color
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html (0 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.strokeText.html	2021-08-23 21:36:38 UTC (rev 281470)
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.color.space.p3.strokeText</title>
+<script src=""
+<script src=""
+<script src=""
+<link rel="stylesheet" href=""
+<body class="show_output">
+
+<h1>2d.color.space.p3.strokeText</h1>
+<p class="desc">Test if strokeText can be used with a solid display-p3 color</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test if strokeText can be used with a solid display-p3 color");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+
+const fullRedInP3 = [255, 0, 0, 255];
+const sRGBRedInP3 = [234, 51, 35, 255];
+
+canvas.width = 100;
+canvas.height = 100;
+
+let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+document.fonts.add(f);
+f.load().then(function() {
+    t.step(function() {
+        ctx.font = "40px Ahem";
+
+        ctx.strokeStyle = "#f00";
+        ctx.lineWidth = 20;
+        ctx.strokeText("A", 0, 50);
+
+        ctx.strokeStyle = "black";
+        ctx.strokeStyle = "color(display-p3 100% 0 0)";
+        ctx.strokeText("A", 50, 50);
+
+        let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+        let pixelAt = function(x, y) {
+            let offset = (y * canvas.width + x) * 4;
+            return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+        };
+
+        assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+        assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+        t.done();
+    });
+});
+
+
+}, {colorSpace: "display-p3"});
+</script>
+

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml (281469 => 281470)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/tools/yaml/element/color_space.yaml	2021-08-23 21:36:38 UTC (rev 281470)
@@ -175,3 +175,131 @@
         assert_array_approx_equals(actualPixels, expectedPixels, 2);
     });
     image.src = ""
+
+- name: 2d.color.space.p3.fillText
+  testing:
+  - 2d.color.space.p3.and.uint8
+  desc: Test if fillText can be used with a solid display-p3 color
+  attributes: |
+    {colorSpace: "display-p3"}
+  code: |
+    deferTest();
+
+    const fullRedInP3 = [255, 0, 0, 255];
+    const sRGBRedInP3 = [234, 51, 35, 255];
+
+    canvas.width = 100;
+    canvas.height = 100;
+
+    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+    document.fonts.add(f);
+    f.load().then(function() {
+        t.step(function() {
+            ctx.font = "40px Ahem";
+
+            ctx.fillStyle = "#f00";
+            ctx.fillText("A", 0, 50);
+
+            ctx.fillStyle = "black";
+            ctx.fillStyle = "color(display-p3 100% 0 0)";
+            ctx.fillText("A", 50, 50);
+
+            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+            let pixelAt = function(x, y) {
+                let offset = (y * canvas.width + x) * 4;
+                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+            };
+
+            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+            assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+            t.done();
+        });
+    });
+
+- name: 2d.color.space.p3.strokeText
+  testing:
+  - 2d.color.space.p3.and.uint8
+  desc: Test if strokeText can be used with a solid display-p3 color
+  attributes: |
+    {colorSpace: "display-p3"}
+  code: |
+    deferTest();
+
+    const fullRedInP3 = [255, 0, 0, 255];
+    const sRGBRedInP3 = [234, 51, 35, 255];
+
+    canvas.width = 100;
+    canvas.height = 100;
+
+    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+    document.fonts.add(f);
+    f.load().then(function() {
+        t.step(function() {
+            ctx.font = "40px Ahem";
+
+            ctx.strokeStyle = "#f00";
+            ctx.lineWidth = 20;
+            ctx.strokeText("A", 0, 50);
+
+            ctx.strokeStyle = "black";
+            ctx.strokeStyle = "color(display-p3 100% 0 0)";
+            ctx.strokeText("A", 50, 50);
+
+            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+            let pixelAt = function(x, y) {
+                let offset = (y * canvas.width + x) * 4;
+                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+            };
+
+            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+            assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+            t.done();
+        });
+    });
+
+- name: 2d.color.space.p3.fillText.shadow
+  testing:
+  - 2d.color.space.p3.and.uint8
+  desc: Test if fillText can be used with a display-p3 shadow color
+  attributes: |
+    {colorSpace: "display-p3"}
+  code: |
+    deferTest();
+
+    const fullRedInP3 = [255, 0, 0, 255];
+    const sRGBRedInP3 = [234, 51, 35, 255];
+
+    canvas.width = 100;
+    canvas.height = 100;
+
+    let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)");
+    document.fonts.add(f);
+    f.load().then(function() {
+        t.step(function() {
+            ctx.font = "40px Ahem";
+
+            ctx.fillStyle = "black";
+            ctx.shadowBlur = 4;
+            ctx.shadowOffsetX = 0;
+            ctx.shadowOffsetY = 50;
+            ctx.shadowColor = "#f00";
+            ctx.fillText("A", 0, 0);
+
+            ctx.shadowColor = "black";
+            ctx.shadowColor = "color(display-p3 100% 0 0)";
+            ctx.fillText("A", 50, 0);
+
+            let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data;
+            let pixelAt = function(x, y) {
+                let offset = (y * canvas.width + x) * 4;
+                return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]];
+            };
+
+            assert_array_equals(pixelAt(25, 25), sRGBRedInP3);
+            assert_array_equals(pixelAt(75, 25), fullRedInP3);
+
+            t.done();
+        });
+    });

Modified: trunk/Source/WebCore/ChangeLog (281469 => 281470)


--- trunk/Source/WebCore/ChangeLog	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/ChangeLog	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1,3 +1,82 @@
+2021-08-23  Cameron McCormack  <hey...@apple.com>
+
+        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):
+
 2021-08-23  Alan Bujtas  <za...@apple.com>
 
         Simplified text measuring only works with the primary font

Modified: trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp (281469 => 281470)


--- trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -317,7 +317,7 @@
     MACaptionAppearanceBehavior behavior;
     RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyWindowColor(kMACaptionAppearanceDomainUser, &behavior));
 
-    Color windowColor(color.get());
+    Color windowColor(roundAndClampToSRGBALossy(color.get()));
     if (!windowColor.isValid())
         windowColor = Color::transparentBlack;
 
@@ -342,7 +342,7 @@
     MACaptionAppearanceBehavior behavior;
 
     RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyBackgroundColor(kMACaptionAppearanceDomainUser, &behavior));
-    Color backgroundColor(color.get());
+    Color backgroundColor(roundAndClampToSRGBALossy(color.get()));
     if (!backgroundColor.isValid())
         backgroundColor = defaultBackgroundColor;
 
@@ -356,7 +356,8 @@
 Color CaptionUserPreferencesMediaAF::captionsTextColor(bool& important) const
 {
     MACaptionAppearanceBehavior behavior;
-    Color textColor = adoptCF(MACaptionAppearanceCopyForegroundColor(kMACaptionAppearanceDomainUser, &behavior)).get();
+    RetainPtr<CGColorRef> color = adoptCF(MACaptionAppearanceCopyForegroundColor(kMACaptionAppearanceDomainUser, &behavior)).get();
+    Color textColor(roundAndClampToSRGBALossy(color.get()));
     if (!textColor.isValid()) {
         // This default value must be the same as the one specified in mediaControls.css for -webkit-media-text-track-container.
         textColor = Color::white;

Modified: trunk/Source/WebCore/platform/graphics/Color.h (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/Color.h	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/Color.h	2021-08-23 21:36:38 UTC (rev 281470)
@@ -150,7 +150,7 @@
 #endif
 
 #if USE(CG)
-    WEBCORE_EXPORT Color(CGColorRef, OptionSet<Flags> = { });
+    WEBCORE_EXPORT static Color createAndPreserveColorSpace(CGColorRef, OptionSet<Flags> = { });
 #endif
 
 #if PLATFORM(WIN)
@@ -207,6 +207,10 @@
     };
     Color(Ref<OutOfLineComponents>&&, ColorSpace, OptionSet<Flags> = { });
 
+#if USE(CG)
+    WEBCORE_EXPORT static Color createAndLosslesslyConvertToSupportedColorSpace(CGColorRef, OptionSet<Flags> = { });
+#endif
+
     enum class FlagsIncludingPrivate : uint8_t {
         Semantic                        = static_cast<uint8_t>(Flags::Semantic),
         UseColorFunctionSerialization   = static_cast<uint8_t>(Flags::UseColorFunctionSerialization),
@@ -268,6 +272,7 @@
 #if USE(CG)
 WEBCORE_EXPORT CGColorRef cachedCGColor(const Color&);
 WEBCORE_EXPORT ColorComponents<float, 4> platformConvertColorComponents(ColorSpace, ColorComponents<float, 4>, const DestinationColorSpace&);
+WEBCORE_EXPORT std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef);
 #endif
 
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const Color&);

Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -820,7 +820,7 @@
 
 Color PlatformCALayerCocoa::backgroundColor() const
 {
-    return [m_layer backgroundColor];
+    return roundAndClampToSRGBALossy([m_layer backgroundColor]);
 }
 
 void PlatformCALayerCocoa::setBackgroundColor(const Color& value)

Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/WebTiledBackingLayer.mm (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/ca/cocoa/WebTiledBackingLayer.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/WebTiledBackingLayer.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -147,7 +147,7 @@
 
 - (void)setBorderColor:(CGColorRef)borderColor
 {
-    _tileController->setTileDebugBorderColor(WebCore::Color(borderColor));
+    _tileController->setTileDebugBorderColor(WebCore::roundAndClampToSRGBALossy(borderColor));
 }
 
 - (void)setBorderWidth:(CGFloat)borderWidth

Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -572,7 +572,7 @@
 
 Color PlatformCALayerWin::backgroundColor() const
 {
-    return CACFLayerGetBackgroundColor(m_layer.get());
+    return roundAndClampToSRGBALossy(CACFLayerGetBackgroundColor(m_layer.get()));
 }
 
 void PlatformCALayerWin::setBackgroundColor(const Color& value)
@@ -703,7 +703,7 @@
 
 static void printColor(StringBuilder& builder, int indent, const String& label, CGColorRef color)
 {
-    Color layerColor(color);
+    Color layerColor(roundAndClampToSRGBALossy(color));
     if (!layerColor.isValid())
         return;
 

Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -130,7 +130,7 @@
         backgroundColor = cachedCGColor(Color::red);
 
     GraphicsContextCG graphicsContext(context);
-    PlatformCALayer::drawRepaintIndicator(graphicsContext, owner(), drawCount, backgroundColor);
+    PlatformCALayer::drawRepaintIndicator(graphicsContext, owner(), drawCount, roundAndClampToSRGBALossy(backgroundColor));
 }
 
 void PlatformCALayerWinInternal::internalSetNeedsDisplay(const FloatRect* dirtyRect)

Modified: trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -54,9 +54,10 @@
 
 namespace WebCore {
 
-static std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef color)
+std::optional<SRGBA<uint8_t>> roundAndClampToSRGBALossy(CGColorRef color)
 {
-    // FIXME: ExtendedColor - needs to handle color spaces.
+    // FIXME: Interpreting components of a color in an arbitrary color space
+    // as sRGB could be wrong, not just lossy.
 
     if (!color)
         return std::nullopt;
@@ -87,11 +88,54 @@
     return convertColor<SRGBA<uint8_t>>(makeFromComponentsClamping<SRGBA<float>>(r, g, b, a ));
 }
 
-Color::Color(CGColorRef color, OptionSet<Flags> flags)
-    : Color(roundAndClampToSRGBALossy(color), flags)
+Color Color::createAndLosslesslyConvertToSupportedColorSpace(CGColorRef color, OptionSet<Flags> flags)
 {
+    auto sourceCGColorSpace = CGColorGetColorSpace(color);
+#if HAVE(CORE_GRAPHICS_XYZ_COLOR_SPACE)
+    auto destinationCGColorSpace = xyzColorSpaceRef();
+    auto destinationColorSpace = ColorSpace::XYZ_D50;
+#else
+    auto destinationCGColorSpace = sRGBColorSpaceRef();
+    auto destinationColorSpace = ColorSpace::SRGB;
+#endif
+    ASSERT(CGColorSpaceGetNumberOfComponents(destinationCGColorSpace) == 3);
+
+    auto sourceComponents = CGColorGetComponents(color);
+    CGFloat destinationComponents[3] { };
+
+    auto transform = adoptCF(CGColorTransformCreate(destinationCGColorSpace, nullptr));
+    auto result = CGColorTransformConvertColorComponents(transform.get(), sourceCGColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
+    ASSERT_UNUSED(result, result);
+
+    float a = destinationComponents[0];
+    float b = destinationComponents[1];
+    float c = destinationComponents[2];
+    float alpha = CGColorGetAlpha(color);
+
+    return Color(OutOfLineComponents::create({ a, b, c, alpha }), destinationColorSpace, flags);
 }
 
+Color Color::createAndPreserveColorSpace(CGColorRef color, OptionSet<Flags> flags)
+{
+    if (!color)
+        return Color();
+
+    size_t numComponents = CGColorGetNumberOfComponents(color);
+    auto colorSpace = colorSpaceForCGColorSpace(CGColorGetColorSpace(color));
+
+    if (numComponents != 4 || !colorSpace)
+        return createAndLosslesslyConvertToSupportedColorSpace(color, flags);
+
+    const CGFloat* components = CGColorGetComponents(color);
+
+    float a = components[0];
+    float b = components[1];
+    float c = components[2];
+    float alpha = components[3];
+
+    return Color(OutOfLineComponents::create({ a, b, c, alpha }), *colorSpace, flags);
+}
+
 static std::pair<CGColorSpaceRef, ColorComponents<float, 4>> convertToCGCompatibleComponents(ColorSpace colorSpace, ColorComponents<float, 4> components)
 {
     // Some CG ports don't support all the color spaces required and return
@@ -181,6 +225,7 @@
     auto transform = adoptCF(CGColorTransformCreate(outputColorSpace.platformColorSpace(), nullptr));
     auto result = CGColorTransformConvertColorComponents(transform.get(), cgInputColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
     ASSERT_UNUSED(result, result);
+    // FIXME: CGColorTransformConvertColorComponents doesn't copy over any alpha component.
     return { static_cast<float>(destinationComponents[0]), static_cast<float>(destinationComponents[1]), static_cast<float>(destinationComponents[2]), static_cast<float>(destinationComponents[3]) };
 }
 

Modified: trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -108,6 +108,46 @@
 }
 #endif
 
+std::optional<ColorSpace> colorSpaceForCGColorSpace(CGColorSpaceRef colorSpace)
+{
+    if (CGColorSpaceEqualToColorSpace(colorSpace, sRGBColorSpaceRef()))
+        return ColorSpace::SRGB;
+
+#if HAVE(CORE_GRAPHICS_ADOBE_RGB_1998_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, adobeRGB1998ColorSpaceRef()))
+        return ColorSpace::A98RGB;
+#endif
+
+#if HAVE(CORE_GRAPHICS_DISPLAY_P3_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, displayP3ColorSpaceRef()))
+        return ColorSpace::DisplayP3;
+#endif
+
+    // FIXME: labColorSpaceRef() not implemented.
+
+#if HAVE(CORE_GRAPHICS_LINEAR_SRGB_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, linearSRGBColorSpaceRef()))
+        return ColorSpace::LinearSRGB;
+#endif
+
+#if HAVE(CORE_GRAPHICS_ROMMRGB_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, ROMMRGBColorSpaceRef()))
+        return ColorSpace::ProPhotoRGB;
+#endif
+
+#if HAVE(CORE_GRAPHICS_ITUR_2020_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, ITUR_2020ColorSpaceRef()))
+        return ColorSpace::Rec2020;
+#endif
+
+#if HAVE(CORE_GRAPHICS_XYZ_COLOR_SPACE)
+    if (CGColorSpaceEqualToColorSpace(colorSpace, xyzColorSpaceRef()))
+        return ColorSpace::XYZ_D50;
+#endif
+
+    return std::nullopt;
 }
 
+}
+
 #endif // USE(CG)

Modified: trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorSpaceCG.h	2021-08-23 21:36:38 UTC (rev 281470)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "ColorSpace.h"
+#include <optional>
 
 typedef struct CGColorSpace *CGColorSpaceRef;
 
@@ -65,6 +66,8 @@
 WEBCORE_EXPORT CGColorSpaceRef xyzColorSpaceRef();
 #endif
 
+std::optional<ColorSpace> colorSpaceForCGColorSpace(CGColorSpaceRef);
+
 static inline CGColorSpaceRef cachedNullableCGColorSpace(ColorSpace colorSpace)
 {
     switch (colorSpace) {

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -261,7 +261,8 @@
     const auto& shadowStyle = *static_cast<const CGShadowStyle*>(CGStyleGetData(style));
     auto rad = deg2rad(shadowStyle.azimuth - 180);
     auto shadowOffset = FloatSize(std::cos(rad), std::sin(rad)) * shadowStyle.height;
-    updateShadow(shadowOffset, shadowStyle.radius, CGStyleGetColor(style), ShadowsIgnoreTransforms::Yes);
+    auto shadowColor = CGStyleGetColor(style);
+    updateShadow(shadowOffset, shadowStyle.radius, Color::createAndPreserveColorSpace(shadowColor), ShadowsIgnoreTransforms::Yes);
 }
 
 void DrawGlyphsRecorder::recordBeginLayer(CGRenderingStateRef, CGGStateRef gstate, CGRect)
@@ -330,8 +331,10 @@
         ctmFixup = AffineTransform();
     m_owner.concatCTM(ctmFixup);
 
-    updateFillColor(CGGStateGetFillColor(gstate));
-    updateStrokeColor(CGGStateGetStrokeColor(gstate));
+    auto fillColor = CGGStateGetFillColor(gstate);
+    auto strokeColor = CGGStateGetStrokeColor(gstate);
+    updateFillColor(Color::createAndPreserveColorSpace(fillColor));
+    updateStrokeColor(Color::createAndPreserveColorSpace(strokeColor));
     updateShadow(CGGStateGetStyle(gstate));
 
     m_owner.appendDrawGlyphsItemWithCachedFont(*m_originalFont, glyphs, computeAdvancesFromPositions(positions, count, currentTextMatrix).data(), count, currentTextMatrix.mapPoint(positions[0]), m_smoothingMode);

Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp (281469 => 281470)


--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp	2021-08-23 21:36:38 UTC (rev 281470)
@@ -116,12 +116,11 @@
     CGRect rootBounds = m_rootChild->rootLayer()->bounds();
     m_rootChild->setPosition(rootBounds.origin);
     m_rootChild->setBounds(FloatRect(FloatPoint(), FloatSize(rootBounds.size)));
-    m_rootChild->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack));
+    m_rootChild->setBackgroundColor(Color::black);
 #ifndef NDEBUG
-    RetainPtr<CGColorRef> redColor = adoptCF(CGColorCreateGenericRGB(1, 0, 0, 1));
-    rootLayer->setBackgroundColor(redColor.get());
+    rootLayer->setBackgroundColor(Color::red);
 #else
-    rootLayer->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack));
+    rootLayer->setBackgroundColor(Color::black);
 #endif
 }
 #endif

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (281469 => 281470)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -315,7 +315,7 @@
 {
     NSData *data = "" dataForPasteboardType:UIColorPboardType];
     UIColor *uiColor = [NSKeyedUnarchiver unarchivedObjectOfClass:PAL::getUIColorClass() fromData:data error:nil];
-    return Color(uiColor.CGColor);
+    return roundAndClampToSRGBALossy(uiColor.CGColor);
 }
 
 URL PlatformPasteboard::url()

Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (281469 => 281470)


--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1344,7 +1344,7 @@
 static inline std::optional<Color> systemColorFromCSSValueSystemColorInformation(CSSValueSystemColorInformation systemColorInformation, bool useDarkAppearance)
 {
     if (auto color = wtfObjCMsgSend<UIColor *>(PAL::getUIColorClass(), systemColorInformation.selector)) {
-        Color systemColor = { color.CGColor, Color::Flags::Semantic };
+        Color systemColor(roundAndClampToSRGBALossy(color.CGColor), Color::Flags::Semantic);
 
         if (systemColorInformation.opacity < 1.0f)
             systemColor = systemColor.colorWithAlphaMultipliedBy(systemColorInformation.opacity);

Modified: trunk/Source/WebKit/ChangeLog (281469 => 281470)


--- trunk/Source/WebKit/ChangeLog	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/ChangeLog	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1,3 +1,23 @@
+2021-08-23  Cameron McCormack  <hey...@apple.com>
+
+        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):
+
 2021-08-23  Wenson Hsieh  <wenson_hs...@apple.com>
 
         REGRESSION (r271146): editing/selection/ios/scrolling-to-focused-element-inside-iframe.html is failing

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1784,7 +1784,7 @@
 
 - (void)setUnderPageBackgroundColor:(CocoaColor *)underPageBackgroundColorOverride
 {
-    _page->setUnderPageBackgroundColorOverride(underPageBackgroundColorOverride.CGColor);
+    _page->setUnderPageBackgroundColorOverride(WebCore::roundAndClampToSRGBALossy(underPageBackgroundColorOverride.CGColor));
 }
 
 + (BOOL)automaticallyNotifiesObserversOfUnderPageBackgroundColor

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -67,7 +67,7 @@
         URL(scopeURL),
         static_cast<WebCore::ApplicationManifest::Display>(display),
         URL(startURL),
-        WebCore::Color(themeColor.CGColor),
+        WebCore::roundAndClampToSRGBALossy(themeColor.CGColor),
     };
 
     API::Object::constructInWrapper<API::ApplicationManifest>(self, WTFMove(coreApplicationManifest));

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -481,7 +481,7 @@
 static WebCore::Color baseScrollViewBackgroundColor(WKWebView *webView, AllowPageBackgroundColorOverride allowPageBackgroundColorOverride)
 {
     if (webView->_customContentView)
-        return [webView->_customContentView backgroundColor].CGColor;
+        return WebCore::roundAndClampToSRGBALossy([webView->_customContentView backgroundColor].CGColor);
 
     if (webView->_gestureController) {
         WebCore::Color color = webView->_gestureController->backgroundColorForCurrentSnapshot();
@@ -507,11 +507,11 @@
     WebCore::Color color = baseScrollViewBackgroundColor(webView, allowPageBackgroundColorOverride);
 
     if (!color.isValid() && webView->_contentView)
-        color = [webView->_contentView backgroundColor].CGColor;
+        color = WebCore::roundAndClampToSRGBALossy([webView->_contentView backgroundColor].CGColor);
 
     if (!color.isValid()) {
 #if HAVE(OS_DARK_MODE_SUPPORT)
-        color = UIColor.systemBackgroundColor.CGColor;
+        color = WebCore::roundAndClampToSRGBALossy(UIColor.systemBackgroundColor.CGColor);
 #else
         color = WebCore::Color::white;
 #endif

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1015,7 +1015,7 @@
 
 WebCore::Color PageClientImpl::contentViewBackgroundColor()
 {
-    return [m_contentView backgroundColor].CGColor;
+    return WebCore::roundAndClampToSRGBALossy([m_contentView backgroundColor].CGColor);
 }
 
 void PageClientImpl::requestScrollToRect(const FloatRect& targetRect, const FloatPoint& origin)

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -3630,7 +3630,8 @@
 
 - (void)_setTextColorForWebView:(UIColor *)color sender:(id)sender
 {
-    _page->executeEditCommand("ForeColor"_s, WebCore::serializationForHTML(WebCore::Color(color.CGColor)));
+    WebCore::Color textColor(WebCore::roundAndClampToSRGBALossy(color.CGColor));
+    _page->executeEditCommand("ForeColor"_s, WebCore::serializationForHTML(textColor));
 }
 
 - (void)toggleStrikeThroughForWebView:(id)sender
@@ -4871,7 +4872,7 @@
 
 - (void)updateFocusedElementValueAsColor:(UIColor *)value
 {
-    WebCore::Color color(value.CGColor);
+    WebCore::Color color(WebCore::roundAndClampToSRGBALossy(value.CGColor));
     String valueAsString = WebCore::serializationForHTML(color);
 
     _page->setFocusedElementValue(_focusedElementInformation.elementContext, valueAsString);

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1559,9 +1559,9 @@
         return contentViewBackgroundColor;
 
 #if HAVE(OS_DARK_MODE_SUPPORT)
-    return UIColor.systemBackgroundColor.CGColor;
+    return WebCore::roundAndClampToSRGBALossy(UIColor.systemBackgroundColor.CGColor);
 #else
-    return UIColor.whiteColor.CGColor;
+    return WebCore::Color::white;
 #endif
 }
 

Modified: trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm (281469 => 281470)


--- trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -728,9 +728,9 @@
 Color WebPageProxy::platformUnderPageBackgroundColor() const
 {
 #if ENABLE(DARK_MODE_CSS)
-    return NSColor.controlBackgroundColor.CGColor;
+    return WebCore::roundAndClampToSRGBALossy(NSColor.controlBackgroundColor.CGColor);
 #else
-    return NSColor.whiteColor.CGColor;
+    return WebCore::Color::white;
 #endif
 }
 

Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm (281469 => 281470)


--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -624,7 +624,7 @@
         auto* document = frame.coreFrame()->document();
 
         // FIXME: <rdar://problem/75332948> get the background color from PDFKit instead of hardcoding it
-        document->bodyOrFrameset()->setInlineStyleProperty(WebCore::CSSPropertyBackgroundColor, WebCore::serializationForHTML([CocoaColor grayColor].CGColor));
+        document->bodyOrFrameset()->setInlineStyleProperty(WebCore::CSSPropertyBackgroundColor, WebCore::serializationForHTML(WebCore::roundAndClampToSRGBALossy([CocoaColor grayColor].CGColor)));
     }
 
     if (supportsForms()) {

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm (281469 => 281470)


--- trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -443,7 +443,7 @@
             WebCore::Color color = WebCore::colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
             ALLOW_DEPRECATED_DECLARATIONS_END
 #else
-            WebCore::Color color = WebCore::Color(backgroundColor);
+            WebCore::Color color(WebCore::roundAndClampToSRGBALossy(backgroundColor));
 #endif
             view->setBaseBackgroundColor(color);
             view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
@@ -1388,7 +1388,7 @@
 
 - (void)setCaretColor:(CGColorRef)color
 {
-    WebCore::Color qColor = color ? WebCore::Color(color) : WebCore::Color::black;
+    WebCore::Color qColor = color ? WebCore::Color(WebCore::roundAndClampToSRGBALossy(color)) : WebCore::Color::black;
     WebCore::Frame *frame = core(self);
     frame->selection().setCaretColor(qColor);
 }

Modified: trunk/Tools/ChangeLog (281469 => 281470)


--- trunk/Tools/ChangeLog	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Tools/ChangeLog	2021-08-23 21:36:38 UTC (rev 281470)
@@ -1,3 +1,17 @@
+2021-08-23  Cameron McCormack  <hey...@apple.com>
+
+        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):
+
 2021-08-23  Wenson Hsieh  <wenson_hs...@apple.com>
 
         editing/selection/ios/select-text-in-existing-selection.html fails on iOS 15

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm (281469 => 281470)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm	2021-08-23 21:05:44 UTC (rev 281469)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm	2021-08-23 21:36:38 UTC (rev 281470)
@@ -149,7 +149,7 @@
     EXPECT_NULL([webView _sampledPageTopColor]);
 
     waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops("right"_s, { "red"_s, "red"_s }));
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
 }
 
 TEST(SampledPageTopColor, DifferentColorsWithoutOutlierBelowMaxDifference)
@@ -301,7 +301,7 @@
     EXPECT_NULL([webView _sampledPageTopColor]);
 
     waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<body style='margin: 0'><canvas style='width: 100%; height: 100%; background-color: red'></canvas>Test");
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
 }
 
 TEST(SampledPageTopColor, HitTestHTMLCanvasWithRenderingContext)
@@ -328,7 +328,7 @@
     EXPECT_NULL([webView _sampledPageTopColor]);
 
     waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<body style='margin: 0; transition: background-color 1s'>Test");
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
 }
 
 TEST(SampledPageTopColor, HitTestDuringCSSTransition)
@@ -360,7 +360,7 @@
     // Not setting this until now prevents the sampling logic from running because without it the page isn't considered contentful.
     [webView objectByEvaluatingJavaScript:@"document.body.textContent = 'Test'"];
     waitForSampledPageTopColorToChange(webView.get());
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
 }
 
 TEST(SampledPageTopColor, HitTestBeforeCSSAnimation)
@@ -369,7 +369,7 @@
     EXPECT_NULL([webView _sampledPageTopColor]);
 
     waitForSampledPageTopColorToChangeForHTML(webView.get(), @"<style>@keyframes changeBackgroundRed { to { background-color: red; } }</style><body style='margin: 0; animation: changeBackgroundRed 1s forwards paused'>Test");
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
 }
 
 TEST(SampledPageTopColor, HitTestDuringCSSAnimation)
@@ -399,7 +399,7 @@
     // Not setting this until now prevents the sampling logic from running because without it the page isn't considered contentful.
     [webView objectByEvaluatingJavaScript:@"document.body.textContent = 'Test'"];
     waitForSampledPageTopColorToChange(webView.get());
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
 }
 
 TEST(SampledPageTopColor, HitTestCSSPointerEventsNone)
@@ -408,7 +408,7 @@
     EXPECT_NULL([webView _sampledPageTopColor]);
 
     [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body style='margin: 0'><div style='width: 100%; height: 100%; background-color: red; pointer-events: none'></div>Test"];
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
 }
 
 // FIXME: <https://webkit.org/b/225167> (Sampled Page Top Color: hook into painting logic instead of taking snapshots)
@@ -443,13 +443,13 @@
     }]);
 
     [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     EXPECT_EQ(notificationCount, 1UL);
 
     notificationCount = 0;
 
     [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     // Depending on timing, a notification can be sent for when the main document changes and then
     // when the new main document renders or both can be coalesced if rendering is fast enough.
     EXPECT_TRUE(notificationCount == 0 || notificationCount == 2);
@@ -469,6 +469,6 @@
     notificationCount = 0;
 
     [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:@"<body>Test"];
-    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
+    EXPECT_EQ(WebCore::roundAndClampToSRGBALossy([webView _sampledPageTopColor].CGColor), WebCore::Color::white);
     EXPECT_EQ(notificationCount, 1UL);
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to