Skip to content

Commit 308c072

Browse files
tdennistonSkia Commit-Bot
authored andcommitted
[svg] Implement currentColor for gradient stops
Required introducing a new type for stop-color attribute. A test that exercises this is 'color-prop-01-b'. Note that stop-color should be an inherited presentation attribute, but that is not addressed in this CL. Change-Id: I65b99bfc989f1d4b5a0746de31011b0e72eb6c59 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/282592 Commit-Queue: Tyler Denniston <tdenniston@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org>
1 parent 2b9f53e commit 308c072

File tree

10 files changed

+95
-8
lines changed

10 files changed

+95
-8
lines changed

experimental/svg/model/SkSVGAttribute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ struct SkSVGPresentationAttributes {
8787

8888
SkTLazy<SkSVGColorType> fColor;
8989

90+
// TODO(tdenniston): add SkSVGStopColor
91+
9092
// uninherited
9193
SkTLazy<SkSVGNumberType> fOpacity;
9294
SkTLazy<SkSVGClip> fClipPath;

experimental/svg/model/SkSVGAttributeParser.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,23 @@ bool SkSVGAttributeParser::parseSpreadMethod(SkSVGSpreadMethod* spread) {
533533
return parsedValue && this->parseEOSToken();
534534
}
535535

536+
// https://www.w3.org/TR/SVG11/pservers.html#StopElement
537+
bool SkSVGAttributeParser::parseStopColor(SkSVGStopColor* stopColor) {
538+
SkSVGColorType c;
539+
bool parsedValue = false;
540+
if (this->parseColor(&c)) {
541+
*stopColor = SkSVGStopColor(c);
542+
parsedValue = true;
543+
} else if (this->parseExpectedStringToken("currentColor")) {
544+
*stopColor = SkSVGStopColor(SkSVGStopColor::Type::kCurrentColor);
545+
parsedValue = true;
546+
} else if (this->parseExpectedStringToken("inherit")) {
547+
*stopColor = SkSVGStopColor(SkSVGStopColor::Type::kInherit);
548+
parsedValue = true;
549+
}
550+
return parsedValue && this->parseEOSToken();
551+
}
552+
536553
// https://www.w3.org/TR/SVG11/shapes.html#PolygonElementPointsAttribute
537554
bool SkSVGAttributeParser::parsePoints(SkSVGPointsType* points) {
538555
SkTDArray<SkPoint> pts;

experimental/svg/model/SkSVGAttributeParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class SkSVGAttributeParser : public SkNoncopyable {
2828
bool parsePoints(SkSVGPointsType*);
2929
bool parseIRI(SkSVGStringType*);
3030
bool parseSpreadMethod(SkSVGSpreadMethod*);
31+
bool parseStopColor(SkSVGStopColor*);
3132
bool parseVisibility(SkSVGVisibility*);
3233
bool parseDashArray(SkSVGDashArray*);
3334

experimental/svg/model/SkSVGDOM.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ bool SetSpreadMethodAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
188188
return true;
189189
}
190190

191+
bool SetStopColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
192+
const char* stringValue) {
193+
SkSVGStopColor stopColor;
194+
SkSVGAttributeParser parser(stringValue);
195+
if (!parser.parseStopColor(&stopColor)) {
196+
return false;
197+
}
198+
199+
node->setAttribute(attr, SkSVGStopColorValue(stopColor));
200+
return true;
201+
}
202+
191203
bool SetPointsAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
192204
const char* stringValue) {
193205
SkSVGPointsType points;
@@ -338,7 +350,7 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
338350
{ "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
339351
{ "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
340352
{ "spreadMethod" , { SkSVGAttribute::kSpreadMethod , SetSpreadMethodAttribute }},
341-
{ "stop-color" , { SkSVGAttribute::kStopColor , SetColorAttribute }},
353+
{ "stop-color" , { SkSVGAttribute::kStopColor , SetStopColorAttribute }},
342354
{ "stop-opacity" , { SkSVGAttribute::kStopOpacity , SetNumberAttribute }},
343355
{ "stroke" , { SkSVGAttribute::kStroke , SetPaintAttribute }},
344356
{ "stroke-dasharray" , { SkSVGAttribute::kStrokeDashArray , SetDashArrayAttribute }},

experimental/svg/model/SkSVGGradient.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ void SkSVGGradient::collectColorStops(const SkSVGRenderContext& ctx,
5757
}
5858

5959
const auto& stop = static_cast<const SkSVGStop&>(*child);
60-
colors->push_back(SkColorSetA(stop.stopColor(),
61-
SkScalarRoundToInt(stop.stopOpacity() * 255)));
60+
colors->push_back(this->resolveStopColor(ctx, stop));
6261
pos->push_back(SkTPin(ltx.resolve(stop.offset(), SkSVGLengthContext::LengthType::kOther),
6362
0.f, 1.f));
6463
}
@@ -74,6 +73,29 @@ void SkSVGGradient::collectColorStops(const SkSVGRenderContext& ctx,
7473
}
7574
}
7675

76+
SkColor SkSVGGradient::resolveStopColor(const SkSVGRenderContext& ctx,
77+
const SkSVGStop& stop) const {
78+
const SkSVGStopColor& stopColor = stop.stopColor();
79+
SkColor color;
80+
switch (stopColor.type()) {
81+
case SkSVGStopColor::Type::kColor:
82+
color = stopColor.color();
83+
break;
84+
case SkSVGStopColor::Type::kCurrentColor:
85+
color = *ctx.presentationContext().fInherited.fColor;
86+
break;
87+
case SkSVGStopColor::Type::kICCColor:
88+
SkDebugf("unimplemented 'icccolor' stop-color type\n");
89+
color = SK_ColorBLACK;
90+
break;
91+
case SkSVGStopColor::Type::kInherit:
92+
SkDebugf("unimplemented 'inherit' stop-color type\n");
93+
color = SK_ColorBLACK;
94+
break;
95+
}
96+
return SkColorSetA(color, SkScalarRoundToInt(stop.stopOpacity() * 255));
97+
}
98+
7799
bool SkSVGGradient::onAsPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
78100
StopColorArray colors;
79101
StopPositionArray pos;

experimental/svg/model/SkSVGGradient.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
class SkMatrix;
1616
class SkSVGRenderContext;
17+
class SkSVGStop;
1718

1819
class SkSVGGradient : public SkSVGHiddenContainer {
1920
public:
@@ -38,6 +39,7 @@ class SkSVGGradient : public SkSVGHiddenContainer {
3839
using StopPositionArray = SkSTArray<2, SkScalar, true>;
3940
using StopColorArray = SkSTArray<2, SkColor, true>;
4041
void collectColorStops(const SkSVGRenderContext&, StopPositionArray*, StopColorArray*) const;
42+
SkColor resolveStopColor(const SkSVGRenderContext&, const SkSVGStop&) const;
4143

4244
SkSVGStringType fHref;
4345
SkSVGTransformType fGradientTransform = SkSVGTransformType(SkMatrix::I());

experimental/svg/model/SkSVGStop.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void SkSVGStop::setOffset(const SkSVGLength& offset) {
1515
fOffset = offset;
1616
}
1717

18-
void SkSVGStop::setStopColor(const SkSVGColorType& color) {
18+
void SkSVGStop::setStopColor(const SkSVGStopColor& color) {
1919
fStopColor = color;
2020
}
2121

@@ -31,7 +31,7 @@ void SkSVGStop::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
3131
}
3232
break;
3333
case SkSVGAttribute::kStopColor:
34-
if (const auto* color = v.as<SkSVGColorValue>()) {
34+
if (const auto* color = v.as<SkSVGStopColorValue>()) {
3535
this->setStopColor(*color);
3636
}
3737
break;

experimental/svg/model/SkSVGStop.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ class SkSVGStop : public SkSVGHiddenContainer {
2121
}
2222

2323
const SkSVGLength& offset() const { return fOffset; }
24-
const SkSVGColorType& stopColor() const { return fStopColor; }
24+
const SkSVGStopColor& stopColor() const { return fStopColor; }
2525
const SkSVGNumberType& stopOpacity() const { return fStopOpacity; }
2626

2727
void setOffset(const SkSVGLength&);
28-
void setStopColor(const SkSVGColorType&);
28+
void setStopColor(const SkSVGStopColor&);
2929
void setStopOpacity(const SkSVGNumberType&);
3030

3131
protected:
@@ -35,7 +35,7 @@ class SkSVGStop : public SkSVGHiddenContainer {
3535
SkSVGStop();
3636

3737
SkSVGLength fOffset = SkSVGLength(0 , SkSVGLength::Unit::kPercentage);
38-
SkSVGColorType fStopColor = SkSVGColorType(SK_ColorBLACK);
38+
SkSVGStopColor fStopColor = SkSVGStopColor(SK_ColorBLACK);
3939
SkSVGNumberType fStopOpacity = SkSVGNumberType(1);
4040

4141
typedef SkSVGHiddenContainer INHERITED;

experimental/svg/model/SkSVGTypes.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,33 @@ class SkSVGDashArray {
279279
SkTDArray<SkSVGLength> fDashArray;
280280
};
281281

282+
class SkSVGStopColor {
283+
public:
284+
enum class Type {
285+
kColor,
286+
kCurrentColor,
287+
kICCColor,
288+
kInherit,
289+
};
290+
291+
SkSVGStopColor() : fType(Type::kColor), fColor(SK_ColorBLACK) {}
292+
explicit SkSVGStopColor(Type t) : fType(t), fColor(SK_ColorBLACK) {}
293+
explicit SkSVGStopColor(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
294+
295+
SkSVGStopColor(const SkSVGStopColor&) = default;
296+
SkSVGStopColor& operator=(const SkSVGStopColor&) = default;
297+
298+
bool operator==(const SkSVGStopColor& other) const {
299+
return fType == other.fType && fColor == other.fColor;
300+
}
301+
bool operator!=(const SkSVGStopColor& other) const { return !(*this == other); }
302+
303+
Type type() const { return fType; }
304+
const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
305+
306+
private:
307+
Type fType;
308+
SkSVGColorType fColor;
309+
};
310+
282311
#endif // SkSVGTypes_DEFINED

experimental/svg/model/SkSVGValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SkSVGValue : public SkNoncopyable {
3030
kPath,
3131
kPoints,
3232
kSpreadMethod,
33+
kStopColor,
3334
kString,
3435
kTransform,
3536
kViewBox,
@@ -89,6 +90,7 @@ using SkSVGPointsValue = SkSVGWrapperValue<SkSVGPointsType , SkSVGValue:
8990
using SkSVGStringValue = SkSVGWrapperValue<SkSVGStringType , SkSVGValue::Type::kString >;
9091
using SkSVGSpreadMethodValue = SkSVGWrapperValue<SkSVGSpreadMethod ,
9192
SkSVGValue::Type::kSpreadMethod>;
93+
using SkSVGStopColorValue = SkSVGWrapperValue<SkSVGStopColor , SkSVGValue::Type::kStopColor >;
9294
using SkSVGVisibilityValue = SkSVGWrapperValue<SkSVGVisibility , SkSVGValue::Type::kVisibility>;
9395
using SkSVGDashArrayValue = SkSVGWrapperValue<SkSVGDashArray , SkSVGValue::Type::kDashArray >;
9496

0 commit comments

Comments
 (0)