1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkMatrix.h"
10 #include "include/pathops/SkPathOps.h"
11 #include "include/private/SkTPin.h"
12 #include "modules/svg/include/SkSVGNode.h"
13 #include "modules/svg/include/SkSVGRenderContext.h"
14 #include "modules/svg/include/SkSVGValue.h"
15 #include "src/core/SkTLazy.h"
16
SkSVGNode(SkSVGTag t)17 SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
18
~SkSVGNode()19 SkSVGNode::~SkSVGNode() { }
20
render(const SkSVGRenderContext & ctx) const21 void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
22 SkSVGRenderContext localContext(ctx, this);
23
24 if (this->onPrepareToRender(&localContext)) {
25 this->onRender(localContext);
26 }
27 }
28
asPaint(const SkSVGRenderContext & ctx,SkPaint * paint) const29 bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
30 SkSVGRenderContext localContext(ctx);
31
32 return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint);
33 }
34
asPath(const SkSVGRenderContext & ctx) const35 SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
36 SkSVGRenderContext localContext(ctx);
37 if (!this->onPrepareToRender(&localContext)) {
38 return SkPath();
39 }
40
41 SkPath path = this->onAsPath(localContext);
42
43 if (const auto* clipPath = localContext.clipPath()) {
44 // There is a clip-path present on the current node.
45 Op(path, *clipPath, kIntersect_SkPathOp, &path);
46 }
47
48 return path;
49 }
50
objectBoundingBox(const SkSVGRenderContext & ctx) const51 SkRect SkSVGNode::objectBoundingBox(const SkSVGRenderContext& ctx) const {
52 return this->onObjectBoundingBox(ctx);
53 }
54
onPrepareToRender(SkSVGRenderContext * ctx) const55 bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
56 ctx->applyPresentationAttributes(fPresentationAttributes,
57 this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);
58
59 // visibility:hidden disables rendering
60 const auto visibility = ctx->presentationContext().fInherited.fVisibility->type();
61 return visibility != SkSVGVisibility::Type::kHidden;
62 }
63
setAttribute(SkSVGAttribute attr,const SkSVGValue & v)64 void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
65 this->onSetAttribute(attr, v);
66 }
67
68 template <typename T>
SetInheritedByDefault(SkTLazy<T> & presentation_attribute,const T & value)69 void SetInheritedByDefault(SkTLazy<T>& presentation_attribute, const T& value) {
70 if (value.type() != T::Type::kInherit) {
71 presentation_attribute.set(value);
72 } else {
73 // kInherited values are semantically equivalent to
74 // the absence of a local presentation attribute.
75 presentation_attribute.reset();
76 }
77 }
78
setColor(const SkSVGColorType & color)79 void SkSVGNode::setColor(const SkSVGColorType& color) {
80 // TODO: Color should be inherited by default
81 fPresentationAttributes.fColor.set(color);
82 }
83
setFillOpacity(const SkSVGNumberType & opacity)84 void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
85 fPresentationAttributes.fFillOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
86 }
87
setOpacity(const SkSVGNumberType & opacity)88 void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
89 fPresentationAttributes.fOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
90 }
91
setStrokeDashOffset(const SkSVGLength & dashOffset)92 void SkSVGNode::setStrokeDashOffset(const SkSVGLength& dashOffset) {
93 fPresentationAttributes.fStrokeDashOffset.set(dashOffset);
94 }
95
setStrokeOpacity(const SkSVGNumberType & opacity)96 void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) {
97 fPresentationAttributes.fStrokeOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
98 }
99
setStrokeMiterLimit(const SkSVGNumberType & ml)100 void SkSVGNode::setStrokeMiterLimit(const SkSVGNumberType& ml) {
101 fPresentationAttributes.fStrokeMiterLimit.set(ml);
102 }
103
setStrokeWidth(const SkSVGLength & strokeWidth)104 void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) {
105 fPresentationAttributes.fStrokeWidth.set(strokeWidth);
106 }
107
onSetAttribute(SkSVGAttribute attr,const SkSVGValue & v)108 void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
109 switch (attr) {
110 case SkSVGAttribute::kColor:
111 if (const SkSVGColorValue* color = v.as<SkSVGColorValue>()) {
112 this->setColor(*color);
113 }
114 break;
115 case SkSVGAttribute::kFillOpacity:
116 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
117 this->setFillOpacity(*opacity);
118 }
119 break;
120 case SkSVGAttribute::kFilter:
121 if (const SkSVGFilterValue* filter = v.as<SkSVGFilterValue>()) {
122 this->setFilter(*filter);
123 }
124 break;
125 case SkSVGAttribute::kOpacity:
126 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
127 this->setOpacity(*opacity);
128 }
129 break;
130 case SkSVGAttribute::kStrokeDashOffset:
131 if (const SkSVGLengthValue* dashOffset= v.as<SkSVGLengthValue>()) {
132 this->setStrokeDashOffset(*dashOffset);
133 }
134 break;
135 case SkSVGAttribute::kStrokeOpacity:
136 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
137 this->setStrokeOpacity(*opacity);
138 }
139 break;
140 case SkSVGAttribute::kStrokeMiterLimit:
141 if (const SkSVGNumberValue* miterLimit = v.as<SkSVGNumberValue>()) {
142 this->setStrokeMiterLimit(*miterLimit);
143 }
144 break;
145 case SkSVGAttribute::kStrokeWidth:
146 if (const SkSVGLengthValue* strokeWidth = v.as<SkSVGLengthValue>()) {
147 this->setStrokeWidth(*strokeWidth);
148 }
149 break;
150 default:
151 #if defined(SK_VERBOSE_SVG_PARSING)
152 SkDebugf("attribute ID <%d> ignored for node <%d>\n", attr, fTag);
153 #endif
154 break;
155 }
156 }
157
parseAndSetAttribute(const char * n,const char * v)158 bool SkSVGNode::parseAndSetAttribute(const char* n, const char* v) {
159 return this->setClipPath(SkSVGAttributeParser::parse<SkSVGClip> ("clip-path" , n, v))
160 || this->setClipRule(SkSVGAttributeParser::parse<SkSVGFillRule> ("clip-rule" , n, v))
161 || this->setFill (SkSVGAttributeParser::parse<SkSVGPaint> ("fill" , n, v))
162 || this->setFillRule(SkSVGAttributeParser::parse<SkSVGFillRule> ("fill-rule" , n, v))
163 || this->setFontFamily
164 (SkSVGAttributeParser::parse<SkSVGFontFamily> ("font-family" , n, v))
165 || this->setFontSize(SkSVGAttributeParser::parse<SkSVGFontSize> ("font-size" , n, v))
166 || this->setFontStyle
167 (SkSVGAttributeParser::parse<SkSVGFontStyle>("font-style" , n, v))
168 || this->setFontWeight
169 (SkSVGAttributeParser::parse<SkSVGFontWeight>("font-weight" , n, v))
170 || this->setStroke (SkSVGAttributeParser::parse<SkSVGPaint> ("stroke" , n, v))
171 || this->setStrokeDashArray
172 (SkSVGAttributeParser::parse<SkSVGDashArray>("stroke-dasharray", n, v))
173 || this->setStrokeLineCap
174 (SkSVGAttributeParser::parse<SkSVGLineCap> ("stroke-linecap" , n ,v))
175 || this->setStrokeLineJoin
176 (SkSVGAttributeParser::parse<SkSVGLineJoin> ("stroke-linejoin" , n ,v))
177 || this->setTextAnchor
178 (SkSVGAttributeParser::parse<SkSVGTextAnchor>("text-anchor" , n, v))
179 || this->setVisibility
180 (SkSVGAttributeParser::parse<SkSVGVisibility>("visibility" , n, v));
181 }
182