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 "SkCanvas.h"
9 #include "SkMatrix.h"
10 #include "SkPathOps.h"
11 #include "SkSVGNode.h"
12 #include "SkSVGRenderContext.h"
13 #include "SkSVGValue.h"
14 #include "SkTLazy.h"
15
SkSVGNode(SkSVGTag t)16 SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
17
~SkSVGNode()18 SkSVGNode::~SkSVGNode() { }
19
render(const SkSVGRenderContext & ctx) const20 void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
21 SkSVGRenderContext localContext(ctx);
22
23 if (this->onPrepareToRender(&localContext)) {
24 this->onRender(localContext);
25 }
26 }
27
asPaint(const SkSVGRenderContext & ctx,SkPaint * paint) const28 bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
29 SkSVGRenderContext localContext(ctx);
30
31 return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint);
32 }
33
asPath(const SkSVGRenderContext & ctx) const34 SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
35 SkSVGRenderContext localContext(ctx);
36 if (!this->onPrepareToRender(&localContext)) {
37 return SkPath();
38 }
39
40 SkPath path = this->onAsPath(localContext);
41
42 if (const auto* clipPath = localContext.clipPath()) {
43 // There is a clip-path present on the current node.
44 Op(path, *clipPath, kIntersect_SkPathOp, &path);
45 }
46
47 return path;
48 }
49
onPrepareToRender(SkSVGRenderContext * ctx) const50 bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
51 ctx->applyPresentationAttributes(fPresentationAttributes,
52 this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);
53
54 // visibility:hidden disables rendering
55 const auto visibility = ctx->presentationContext().fInherited.fVisibility.get()->type();
56 return visibility != SkSVGVisibility::Type::kHidden;
57 }
58
setAttribute(SkSVGAttribute attr,const SkSVGValue & v)59 void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
60 this->onSetAttribute(attr, v);
61 }
62
setClipPath(const SkSVGClip & clip)63 void SkSVGNode::setClipPath(const SkSVGClip& clip) {
64 fPresentationAttributes.fClipPath.set(clip);
65 }
66
setClipRule(const SkSVGFillRule & clipRule)67 void SkSVGNode::setClipRule(const SkSVGFillRule& clipRule) {
68 fPresentationAttributes.fClipRule.set(clipRule);
69 }
70
setFill(const SkSVGPaint & svgPaint)71 void SkSVGNode::setFill(const SkSVGPaint& svgPaint) {
72 fPresentationAttributes.fFill.set(svgPaint);
73 }
74
setFillOpacity(const SkSVGNumberType & opacity)75 void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
76 fPresentationAttributes.fFillOpacity.set(
77 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
78 }
79
setFillRule(const SkSVGFillRule & fillRule)80 void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) {
81 fPresentationAttributes.fFillRule.set(fillRule);
82 }
83
setOpacity(const SkSVGNumberType & opacity)84 void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
85 fPresentationAttributes.fOpacity.set(
86 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
87 }
88
setStroke(const SkSVGPaint & svgPaint)89 void SkSVGNode::setStroke(const SkSVGPaint& svgPaint) {
90 fPresentationAttributes.fStroke.set(svgPaint);
91 }
92
setStrokeDashArray(const SkSVGDashArray & dashArray)93 void SkSVGNode::setStrokeDashArray(const SkSVGDashArray& dashArray) {
94 fPresentationAttributes.fStrokeDashArray.set(dashArray);
95 }
96
setStrokeDashOffset(const SkSVGLength & dashOffset)97 void SkSVGNode::setStrokeDashOffset(const SkSVGLength& dashOffset) {
98 fPresentationAttributes.fStrokeDashOffset.set(dashOffset);
99 }
100
setStrokeOpacity(const SkSVGNumberType & opacity)101 void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) {
102 fPresentationAttributes.fStrokeOpacity.set(
103 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
104 }
105
setStrokeWidth(const SkSVGLength & strokeWidth)106 void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) {
107 fPresentationAttributes.fStrokeWidth.set(strokeWidth);
108 }
109
setVisibility(const SkSVGVisibility & visibility)110 void SkSVGNode::setVisibility(const SkSVGVisibility& visibility) {
111 fPresentationAttributes.fVisibility.set(visibility);
112 }
113
onSetAttribute(SkSVGAttribute attr,const SkSVGValue & v)114 void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
115 switch (attr) {
116 case SkSVGAttribute::kClipPath:
117 if (const SkSVGClipValue* clip = v.as<SkSVGClipValue>()) {
118 this->setClipPath(*clip);
119 }
120 break;
121 case SkSVGAttribute::kClipRule:
122 if (const SkSVGFillRuleValue* clipRule = v.as<SkSVGFillRuleValue>()) {
123 this->setClipRule(*clipRule);
124 }
125 break;
126 case SkSVGAttribute::kFill:
127 if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
128 this->setFill(*paint);
129 }
130 break;
131 case SkSVGAttribute::kFillOpacity:
132 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
133 this->setFillOpacity(*opacity);
134 }
135 break;
136 case SkSVGAttribute::kFillRule:
137 if (const SkSVGFillRuleValue* fillRule = v.as<SkSVGFillRuleValue>()) {
138 this->setFillRule(*fillRule);
139 }
140 break;
141 case SkSVGAttribute::kOpacity:
142 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
143 this->setOpacity(*opacity);
144 }
145 break;
146 case SkSVGAttribute::kStroke:
147 if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
148 this->setStroke(*paint);
149 }
150 break;
151 case SkSVGAttribute::kStrokeDashArray:
152 if (const SkSVGDashArrayValue* dashArray = v.as<SkSVGDashArrayValue>()) {
153 this->setStrokeDashArray(*dashArray);
154 }
155 break;
156 case SkSVGAttribute::kStrokeDashOffset:
157 if (const SkSVGLengthValue* dashOffset= v.as<SkSVGLengthValue>()) {
158 this->setStrokeDashOffset(*dashOffset);
159 }
160 break;
161 case SkSVGAttribute::kStrokeOpacity:
162 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
163 this->setStrokeOpacity(*opacity);
164 }
165 break;
166 case SkSVGAttribute::kStrokeLineCap:
167 if (const SkSVGLineCapValue* lineCap = v.as<SkSVGLineCapValue>()) {
168 fPresentationAttributes.fStrokeLineCap.set(*lineCap);
169 }
170 break;
171 case SkSVGAttribute::kStrokeLineJoin:
172 if (const SkSVGLineJoinValue* lineJoin = v.as<SkSVGLineJoinValue>()) {
173 fPresentationAttributes.fStrokeLineJoin.set(*lineJoin);
174 }
175 break;
176 case SkSVGAttribute::kStrokeMiterLimit:
177 if (const SkSVGNumberValue* miterLimit = v.as<SkSVGNumberValue>()) {
178 fPresentationAttributes.fStrokeMiterLimit.set(*miterLimit);
179 }
180 break;
181 case SkSVGAttribute::kStrokeWidth:
182 if (const SkSVGLengthValue* strokeWidth = v.as<SkSVGLengthValue>()) {
183 this->setStrokeWidth(*strokeWidth);
184 }
185 break;
186 case SkSVGAttribute::kVisibility:
187 if (const SkSVGVisibilityValue* visibility = v.as<SkSVGVisibilityValue>()) {
188 this->setVisibility(*visibility);
189 }
190 break;
191 default:
192 #if defined(SK_VERBOSE_SVG_PARSING)
193 SkDebugf("attribute ID <%d> ignored for node <%d>\n", attr, fTag);
194 #endif
195 break;
196 }
197 }
198