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