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 return true;
54 }
55
setAttribute(SkSVGAttribute attr,const SkSVGValue & v)56 void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
57 this->onSetAttribute(attr, v);
58 }
59
setClipPath(const SkSVGClip & clip)60 void SkSVGNode::setClipPath(const SkSVGClip& clip) {
61 fPresentationAttributes.fClipPath.set(clip);
62 }
63
setFill(const SkSVGPaint & svgPaint)64 void SkSVGNode::setFill(const SkSVGPaint& svgPaint) {
65 fPresentationAttributes.fFill.set(svgPaint);
66 }
67
setFillOpacity(const SkSVGNumberType & opacity)68 void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
69 fPresentationAttributes.fFillOpacity.set(
70 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
71 }
72
setFillRule(const SkSVGFillRule & fillRule)73 void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) {
74 fPresentationAttributes.fFillRule.set(fillRule);
75 }
76
setOpacity(const SkSVGNumberType & opacity)77 void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
78 fPresentationAttributes.fOpacity.set(
79 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
80 }
81
setStroke(const SkSVGPaint & svgPaint)82 void SkSVGNode::setStroke(const SkSVGPaint& svgPaint) {
83 fPresentationAttributes.fStroke.set(svgPaint);
84 }
85
setStrokeOpacity(const SkSVGNumberType & opacity)86 void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) {
87 fPresentationAttributes.fStrokeOpacity.set(
88 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
89 }
90
setStrokeWidth(const SkSVGLength & strokeWidth)91 void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) {
92 fPresentationAttributes.fStrokeWidth.set(strokeWidth);
93 }
94
onSetAttribute(SkSVGAttribute attr,const SkSVGValue & v)95 void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
96 switch (attr) {
97 case SkSVGAttribute::kClipPath:
98 if (const SkSVGClipValue* clip = v.as<SkSVGClipValue>()) {
99 this->setClipPath(*clip);
100 }
101 break;
102 case SkSVGAttribute::kFill:
103 if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
104 this->setFill(*paint);
105 }
106 break;
107 case SkSVGAttribute::kFillOpacity:
108 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
109 this->setFillOpacity(*opacity);
110 }
111 break;
112 case SkSVGAttribute::kFillRule:
113 if (const SkSVGFillRuleValue* fillRule = v.as<SkSVGFillRuleValue>()) {
114 this->setFillRule(*fillRule);
115 }
116 break;
117 case SkSVGAttribute::kOpacity:
118 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
119 this->setOpacity(*opacity);
120 }
121 break;
122 case SkSVGAttribute::kStroke:
123 if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
124 this->setStroke(*paint);
125 }
126 break;
127 case SkSVGAttribute::kStrokeOpacity:
128 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
129 this->setStrokeOpacity(*opacity);
130 }
131 break;
132 case SkSVGAttribute::kStrokeLineCap:
133 if (const SkSVGLineCapValue* lineCap = v.as<SkSVGLineCapValue>()) {
134 fPresentationAttributes.fStrokeLineCap.set(*lineCap);
135 }
136 break;
137 case SkSVGAttribute::kStrokeLineJoin:
138 if (const SkSVGLineJoinValue* lineJoin = v.as<SkSVGLineJoinValue>()) {
139 fPresentationAttributes.fStrokeLineJoin.set(*lineJoin);
140 }
141 break;
142 case SkSVGAttribute::kStrokeWidth:
143 if (const SkSVGLengthValue* strokeWidth = v.as<SkSVGLengthValue>()) {
144 this->setStrokeWidth(*strokeWidth);
145 }
146 break;
147 default:
148 SkDebugf("attribute ID <%d> ignored for node <%d>\n", attr, fTag);
149 break;
150 }
151 }
152