Use StyleColor for the stop-color property

This changes the ComputedStyle storage for the stop-color property to be
a StyleColor rather than a plain color. This fixes explicit inheritance
for the property ('currentcolor' computes to itself).
It also means we'll properly pick up changes to 'color'.

Bug: 914728
Change-Id: I3c78a3615220b9149d1ea5102a6e5863526a6d51
Reviewed-on: https://chromium-review.googlesource.com/c/1377437
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#616660}
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 17d04cc..8bab7d7d 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2884,7 +2884,7 @@
       property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
       interpolable: true,
       svg: true,
-      converter: "ConvertColor",
+      converter: "ConvertStyleColor",
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
     },
diff --git a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
index e2ad997..fa4bf50 100644
--- a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
+++ b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
@@ -461,8 +461,9 @@
 
     Element* element = GetDocument().getElementById("test");
     ASSERT_NE(nullptr, element);
-    EXPECT_EQ(0xff008000, element->ComputedStyleRef().SvgStyle().StopColor());
-    EXPECT_EQ(.5f, element->ComputedStyleRef().SvgStyle().StopOpacity());
+    const SVGComputedStyle& svg_style = element->ComputedStyleRef().SvgStyle();
+    EXPECT_EQ(0xff008000, svg_style.StopColor().GetColor());
+    EXPECT_EQ(.5f, svg_style.StopOpacity());
   };
 
   EXPECT_TRUE(GetDocument().IsRenderingReady());
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 63263e8..4b28646 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2488,7 +2488,7 @@
 
   StyleColor DecorationColorIncludingFallback(bool visited_link) const;
 
-  Color StopColor() const { return SvgStyle().StopColor(); }
+  const StyleColor& StopColor() const { return SvgStyle().StopColor(); }
   StyleColor FloodColor() const { return SvgStyle().FloodColor(); }
   StyleColor LightingColor() const { return SvgStyle().LightingColor(); }
 
diff --git a/third_party/blink/renderer/core/style/svg_computed_style.h b/third_party/blink/renderer/core/style/svg_computed_style.h
index 3eb4bc6a..c0d4aac 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style.h
+++ b/third_party/blink/renderer/core/style/svg_computed_style.h
@@ -232,7 +232,7 @@
       stops.Access()->opacity = obj;
   }
 
-  void SetStopColor(const Color& obj) {
+  void SetStopColor(const StyleColor& obj) {
     if (!(stops->color == obj))
       stops.Access()->color = obj;
   }
@@ -320,7 +320,7 @@
   const UnzoomedLength& StrokeWidth() const { return stroke->width; }
   const Length& StrokeDashOffset() const { return stroke->dash_offset; }
   float StopOpacity() const { return stops->opacity; }
-  const Color& StopColor() const { return stops->color; }
+  const StyleColor& StopColor() const { return stops->color; }
   float FloodOpacity() const { return misc->flood_opacity; }
   StyleColor FloodColor() const {
     return misc->flood_color_is_current_color ? StyleColor::CurrentColor()
diff --git a/third_party/blink/renderer/core/style/svg_computed_style_defs.cc b/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
index 95d40a0..c6d8ee1e 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
+++ b/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
@@ -93,11 +93,11 @@
 }
 
 StyleStopData::StyleStopData()
-    : opacity(SVGComputedStyle::InitialStopOpacity()),
-      color(SVGComputedStyle::InitialStopColor()) {}
+    : color(SVGComputedStyle::InitialStopColor()),
+      opacity(SVGComputedStyle::InitialStopOpacity()) {}
 
 StyleStopData::StyleStopData(const StyleStopData& other)
-    : RefCounted<StyleStopData>(), opacity(other.opacity), color(other.color) {}
+    : RefCounted<StyleStopData>(), color(other.color), opacity(other.opacity) {}
 
 bool StyleStopData::operator==(const StyleStopData& other) const {
   return color == other.color && opacity == other.opacity;
diff --git a/third_party/blink/renderer/core/style/svg_computed_style_defs.h b/third_party/blink/renderer/core/style/svg_computed_style_defs.h
index 5920c75..915d9bc 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style_defs.h
+++ b/third_party/blink/renderer/core/style/svg_computed_style_defs.h
@@ -30,6 +30,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/style_color.h"
 #include "third_party/blink/renderer/core/style/style_path.h"
 #include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
@@ -249,8 +250,8 @@
     return !(*this == other);
   }
 
+  StyleColor color;
   float opacity;
-  Color color;
 
  private:
   StyleStopData();
diff --git a/third_party/blink/renderer/core/svg/svg_stop_element.cc b/third_party/blink/renderer/core/svg/svg_stop_element.cc
index 03ecf0e..18bf829 100644
--- a/third_party/blink/renderer/core/svg/svg_stop_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_stop_element.cc
@@ -80,8 +80,8 @@
   if (!style)
     return Color::kBlack;
 
-  const SVGComputedStyle& svg_style = style->SvgStyle();
-  return svg_style.StopColor().CombineWithAlpha(svg_style.StopOpacity());
+  Color base_color = style->VisitedDependentColor(GetCSSPropertyStopColor());
+  return base_color.CombineWithAlpha(style->SvgStyle().StopOpacity());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg
new file mode 100644
index 0000000..b05a69f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
+  <title>SVG Paint Servers: getComputedStyle().stopColor</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+    <h:link rel="help" href="https://drafts.csswg.org/css-color/#resolve-color-values"/>
+    <h:link rel="help" href="https://drafts.csswg.org/cssom/#serializing-css-values"/>
+  </metadata>
+  <g id="target" style="color: blue"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/computed-testcommon.js"/>
+  <script><![CDATA[
+
+test_computed_value("stop-color", "currentcolor", "rgb(0, 0, 255)");
+test_computed_value("stop-color", "white", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "transparent", "rgba(0, 0, 0, 0)");
+test_computed_value("stop-color", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "#ffffff", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "rgba(255, 255, 255, 1.0)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "rgba(255, 255, 255, 0.4)");
+test_computed_value("stop-color", "hsl(0deg, 100%, 100%)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "hsla(0deg, 100%, 100%, 1.0)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "hsla(0deg, 100%, 100%, 0.4)", "rgba(255, 255, 255, 0.4)");
+
+  ]]></script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg
new file mode 100644
index 0000000..1209414
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect width="100" height="100" fill="green"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg
new file mode 100644
index 0000000..da0a05d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"
+     style="color: red">
+  <title>stop-color: Dynamically changing 'color' for a gradient with a stop with 'currentcolor'</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <linearGradient id="g">
+    <stop stop-color="currentcolor"/>
+  </linearGradient>
+  <rect width="50" height="100" fill="url(#g)"/>
+  <rect width="50" height="100" x="50" fill="currentcolor"/>
+  <script>
+    <![CDATA[
+      let root = document.querySelector(':root');
+      root.getBoundingClientRect();  // Force layout
+      root.style.color = 'green';
+    ]]>
+  </script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg
new file mode 100644
index 0000000..22bf513c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"
+     color="red">
+  <title>SVG Paint Servers: 'stop-color' inheritance of 'currentcolor'</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+    <h:link rel="help" href="https://drafts.csswg.org/css-color/#resolve-color-values"/>
+  </metadata>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <linearGradient stop-color="currentcolor" id="g">
+    <stop stop-color="inherit" color="green"/>
+  </linearGradient>
+  <script><![CDATA[
+
+    test(function() {
+      let stop = document.querySelector('stop');
+      assert_equals(getComputedStyle(stop).stopColor, 'rgb(0, 128, 0)');
+    }, '"currentcolor" is inherited as a keyword');
+
+  ]]></script>
+</svg>