[svg] Split out SkSVGColor from paint

This color type will be shared in paint, stop-color, and flood-color
attributes (mainly so they can use 'currentColor').

Change-Id: Ib4200ea729a91a0db5da069c68d64e5e8e3f5010
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/340617
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Tyler Denniston <tdenniston@google.com>
diff --git a/modules/svg/include/SkSVGTypes.h b/modules/svg/include/SkSVGTypes.h
index 2afee73..4adc759 100644
--- a/modules/svg/include/SkSVGTypes.h
+++ b/modules/svg/include/SkSVGTypes.h
@@ -137,18 +137,42 @@
     SkSVGStringType fIRI;
 };
 
+// https://www.w3.org/TR/SVG11/types.html#InterfaceSVGColor
+class SkSVGColor {
+public:
+    enum class Type {
+        kCurrentColor,
+        kColor,
+        kICCColor,
+    };
+
+    SkSVGColor() : fType(Type::kColor), fColor(SK_ColorBLACK) {}
+    explicit SkSVGColor(Type t) : fType(t), fColor(SK_ColorBLACK) {}
+    explicit SkSVGColor(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
+    bool operator==(const SkSVGColor& other) const {
+        return fType == other.fType && fColor == other.fColor;
+    }
+    bool operator!=(const SkSVGColor& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
+
+private:
+    Type fType;
+    SkSVGColorType fColor;
+};
+
 class SkSVGPaint {
 public:
     enum class Type {
         kNone,
-        kCurrentColor,
         kColor,
         kIRI,
     };
 
     SkSVGPaint() : fType(Type::kNone), fColor(SK_ColorBLACK) {}
     explicit SkSVGPaint(Type t) : fType(t), fColor(SK_ColorBLACK) {}
-    explicit SkSVGPaint(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
+    explicit SkSVGPaint(const SkSVGColor& c) : fType(Type::kColor), fColor(c) {}
     explicit SkSVGPaint(const SkString& iri)
         : fType(Type::kIRI), fColor(SK_ColorBLACK), fIRI(iri) {}
 
@@ -161,15 +185,15 @@
     bool operator!=(const SkSVGPaint& other) const { return !(*this == other); }
 
     Type type() const { return fType; }
-    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
+    const SkSVGColor& color() const { SkASSERT(fType == Type::kColor); return fColor; }
     const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
 
 private:
     Type fType;
 
     // Logical union.
-    SkSVGColorType fColor;
-    SkString       fIRI;
+    SkSVGColor fColor;
+    SkString   fIRI;
 };
 
 class SkSVGClip {
diff --git a/modules/svg/src/SkSVGAttribute.cpp b/modules/svg/src/SkSVGAttribute.cpp
index fdc45f6..6a9129d 100644
--- a/modules/svg/src/SkSVGAttribute.cpp
+++ b/modules/svg/src/SkSVGAttribute.cpp
@@ -10,7 +10,7 @@
 SkSVGPresentationAttributes SkSVGPresentationAttributes::MakeInitial() {
     SkSVGPresentationAttributes result;
 
-    result.fFill.set(SkSVGPaint(SkSVGColorType(SK_ColorBLACK)));
+    result.fFill.set(SkSVGPaint(SkSVGColor(SK_ColorBLACK)));
     result.fFillOpacity.set(SkSVGNumberType(1));
     result.fFillRule.set(SkSVGFillRule(SkSVGFillRule::Type::kNonZero));
     result.fClipRule.set(SkSVGFillRule(SkSVGFillRule::Type::kNonZero));
diff --git a/modules/svg/src/SkSVGAttributeParser.cpp b/modules/svg/src/SkSVGAttributeParser.cpp
index 4da7f50..d34f153 100644
--- a/modules/svg/src/SkSVGAttributeParser.cpp
+++ b/modules/svg/src/SkSVGAttributeParser.cpp
@@ -245,6 +245,23 @@
     return parsedValue && this->parseEOSToken();
 }
 
+// https://www.w3.org/TR/SVG11/types.html#InterfaceSVGColor
+template <>
+bool SkSVGAttributeParser::parse(SkSVGColor* color) {
+    SkSVGColorType c;
+    bool parsedValue = false;
+
+    if (this->parse(&c)) {
+        *color = SkSVGColor(c);
+        parsedValue = true;
+    } else if (this->parseExpectedStringToken("currentColor")) {
+        *color = SkSVGColor(SkSVGColor::Type::kCurrentColor);
+        parsedValue = true;
+    }
+
+    return parsedValue && this->parseEOSToken();
+}
+
 // https://www.w3.org/TR/SVG11/linking.html#IRIReference
 template <>
 bool SkSVGAttributeParser::parse(SkSVGIRI* iri) {
@@ -505,7 +522,7 @@
 // https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint
 template <>
 bool SkSVGAttributeParser::parse(SkSVGPaint* paint) {
-    SkSVGColorType c;
+    SkSVGColor c;
     SkSVGStringType iri;
     bool parsedValue = false;
     if (this->parse(&c)) {
@@ -514,9 +531,6 @@
     } else if (this->parseExpectedStringToken("none")) {
         *paint = SkSVGPaint(SkSVGPaint::Type::kNone);
         parsedValue = true;
-    } else if (this->parseExpectedStringToken("currentColor")) {
-        *paint = SkSVGPaint(SkSVGPaint::Type::kCurrentColor);
-        parsedValue = true;
     } else if (this->parseFuncIRI(&iri)) {
         *paint = SkSVGPaint(iri);
         parsedValue = true;
diff --git a/modules/svg/src/SkSVGRenderContext.cpp b/modules/svg/src/SkSVGRenderContext.cpp
index cd87e87..7f7be49 100644
--- a/modules/svg/src/SkSVGRenderContext.cpp
+++ b/modules/svg/src/SkSVGRenderContext.cpp
@@ -103,10 +103,23 @@
     }
 }
 
+SkSVGColorType resolveSvgColor(const SkSVGRenderContext& ctx, const SkSVGColor& color) {
+    switch (color.type()) {
+        case SkSVGColor::Type::kColor:
+            return color.color();
+        case SkSVGColor::Type::kCurrentColor:
+            return *ctx.presentationContext().fInherited.fColor;
+        case SkSVGColor::Type::kICCColor:
+            SkDebugf("ICC color unimplemented");
+            return SK_ColorBLACK;
+    }
+    SkUNREACHABLE;
+}
+
 void applySvgPaint(const SkSVGRenderContext& ctx, const SkSVGPaint& svgPaint, SkPaint* p) {
     switch (svgPaint.type()) {
     case SkSVGPaint::Type::kColor:
-        p->setColor(SkColorSetA(svgPaint.color(), p->getAlpha()));
+        p->setColor(SkColorSetA(resolveSvgColor(ctx, svgPaint.color()), p->getAlpha()));
         break;
     case SkSVGPaint::Type::kIRI: {
         const auto node = ctx.findNodeById(svgPaint.iri());
@@ -115,9 +128,6 @@
         }
         break;
     }
-    case SkSVGPaint::Type::kCurrentColor:
-        p->setColor(*ctx.presentationContext().fInherited.fColor);
-        break;
     case SkSVGPaint::Type::kNone:
         // Do nothing
         break;
@@ -536,14 +546,16 @@
     //   https://www.w3.org/TR/SVG11/color.html#ColorProperty
     // Only fill and stroke require paint updates. The others are resolved at render time.
 
-    if (fPresentationContext->fInherited.fFill->type() == SkSVGPaint::Type::kCurrentColor) {
-        applySvgPaint(*this, *fPresentationContext->fInherited.fFill,
-                      &fPresentationContext.writable()->fFillPaint);
+    const auto& fill = fPresentationContext->fInherited.fFill;
+    if (fill->type() == SkSVGPaint::Type::kColor &&
+        fill->color().type() == SkSVGColor::Type::kCurrentColor) {
+        applySvgPaint(*this, *fill, &fPresentationContext.writable()->fFillPaint);
     }
 
-    if (fPresentationContext->fInherited.fStroke->type() == SkSVGPaint::Type::kCurrentColor) {
-        applySvgPaint(*this, *fPresentationContext->fInherited.fStroke,
-                      &fPresentationContext.writable()->fStrokePaint);
+    const auto& stroke = fPresentationContext->fInherited.fStroke;
+    if (stroke->type() == SkSVGPaint::Type::kColor &&
+        stroke->color().type() == SkSVGColor::Type::kCurrentColor) {
+        applySvgPaint(*this, *stroke, &fPresentationContext.writable()->fStrokePaint);
     }
 }