blob: 43faff83fa7f3a870300c908cf7f46ae9526c2ca [file] [log] [blame]
fmalita6ceef3d2016-07-26 18:46:34 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkMatrix.h"
10#include "include/pathops/SkPathOps.h"
Mike Klein8aa0edf2020-10-16 11:04:18 -050011#include "include/private/SkTPin.h"
Florin Malitab3418102020-10-15 18:10:29 -040012#include "modules/svg/include/SkSVGNode.h"
13#include "modules/svg/include/SkSVGRenderContext.h"
14#include "modules/svg/include/SkSVGValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/core/SkTLazy.h"
fmalita6ceef3d2016-07-26 18:46:34 -070016
17SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
18
19SkSVGNode::~SkSVGNode() { }
20
fmalita397a5172016-08-08 11:38:55 -070021void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
Tyler Denniston53281c72020-10-22 15:54:24 -040022 SkSVGRenderContext localContext(ctx, this);
fmalita6ceef3d2016-07-26 18:46:34 -070023
fmalita397a5172016-08-08 11:38:55 -070024 if (this->onPrepareToRender(&localContext)) {
25 this->onRender(localContext);
fmalita6ceef3d2016-07-26 18:46:34 -070026 }
fmalita397a5172016-08-08 11:38:55 -070027}
fmalita6ceef3d2016-07-26 18:46:34 -070028
fmalita28d5b722016-09-12 17:06:47 -070029bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
30 SkSVGRenderContext localContext(ctx);
31
32 return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint);
33}
34
Florin Malitace8840e2016-12-08 09:26:47 -050035SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
36 SkSVGRenderContext localContext(ctx);
Florin Malita7d529882016-12-08 16:04:24 -050037 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;
Florin Malitace8840e2016-12-08 09:26:47 -050049}
50
Tyler Dennistonf548a022020-10-27 15:02:02 -040051SkRect SkSVGNode::objectBoundingBox(const SkSVGRenderContext& ctx) const {
52 return this->onObjectBoundingBox(ctx);
Tyler Denniston53281c72020-10-22 15:54:24 -040053}
54
fmalita397a5172016-08-08 11:38:55 -070055bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
fmalitabef51c22016-09-20 15:45:57 -070056 ctx->applyPresentationAttributes(fPresentationAttributes,
57 this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);
Florin Malitaffe6ae42017-10-12 11:33:28 -040058
59 // visibility:hidden disables rendering
John Stilesa008b0f2020-08-16 08:48:02 -040060 const auto visibility = ctx->presentationContext().fInherited.fVisibility->type();
Florin Malitaffe6ae42017-10-12 11:33:28 -040061 return visibility != SkSVGVisibility::Type::kHidden;
fmalita6ceef3d2016-07-26 18:46:34 -070062}
63
Florin Malitaf4403e72020-04-10 14:14:04 +000064void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
fmalita6ceef3d2016-07-26 18:46:34 -070065 this->onSetAttribute(attr, v);
66}
67
Florin Malita09294252020-04-09 08:54:29 -040068template <typename T>
69void 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
Tyler Denniston6c8314e2020-04-09 14:14:10 -040079void SkSVGNode::setColor(const SkSVGColorType& color) {
80 // TODO: Color should be inherited by default
81 fPresentationAttributes.fColor.set(color);
82}
83
fmalitaca39d712016-08-12 13:17:11 -070084void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
Florin Malitaa3626692020-04-09 14:36:45 -040085 fPresentationAttributes.fFillOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
fmalitaca39d712016-08-12 13:17:11 -070086}
87
fmalita6fb06482016-08-15 12:45:11 -070088void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
Florin Malitaa3626692020-04-09 14:36:45 -040089 fPresentationAttributes.fOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
fmalita6fb06482016-08-15 12:45:11 -070090}
91
Florin Malitae1dadd72017-10-13 18:18:32 -040092void SkSVGNode::setStrokeDashOffset(const SkSVGLength& dashOffset) {
93 fPresentationAttributes.fStrokeDashOffset.set(dashOffset);
94}
95
fmalitaca39d712016-08-12 13:17:11 -070096void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) {
Florin Malitaa3626692020-04-09 14:36:45 -040097 fPresentationAttributes.fStrokeOpacity.set(SkSVGNumberType(SkTPin<SkScalar>(opacity, 0, 1)));
fmalitaca39d712016-08-12 13:17:11 -070098}
99
Florin Malita09294252020-04-09 08:54:29 -0400100void SkSVGNode::setStrokeMiterLimit(const SkSVGNumberType& ml) {
101 fPresentationAttributes.fStrokeMiterLimit.set(ml);
102}
103
fmalitaca39d712016-08-12 13:17:11 -0700104void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) {
105 fPresentationAttributes.fStrokeWidth.set(strokeWidth);
106}
107
Florin Malitaf4403e72020-04-10 14:14:04 +0000108void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
fmalita6ceef3d2016-07-26 18:46:34 -0700109 switch (attr) {
Tyler Denniston6c8314e2020-04-09 14:14:10 -0400110 case SkSVGAttribute::kColor:
Florin Malitaf4403e72020-04-10 14:14:04 +0000111 if (const SkSVGColorValue* color = v.as<SkSVGColorValue>()) {
Tyler Denniston6c8314e2020-04-09 14:14:10 -0400112 this->setColor(*color);
113 }
114 break;
fmalita2d961e02016-08-11 09:16:29 -0700115 case SkSVGAttribute::kFillOpacity:
Florin Malitaf4403e72020-04-10 14:14:04 +0000116 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
fmalitaca39d712016-08-12 13:17:11 -0700117 this->setFillOpacity(*opacity);
fmalita6ceef3d2016-07-26 18:46:34 -0700118 }
119 break;
Tyler Dennistonb3cafbc2020-10-30 15:00:48 -0400120 case SkSVGAttribute::kFilter:
121 if (const SkSVGFilterValue* filter = v.as<SkSVGFilterValue>()) {
122 this->setFilter(*filter);
123 }
124 break;
fmalita6fb06482016-08-15 12:45:11 -0700125 case SkSVGAttribute::kOpacity:
Florin Malitaf4403e72020-04-10 14:14:04 +0000126 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
fmalita6fb06482016-08-15 12:45:11 -0700127 this->setOpacity(*opacity);
128 }
129 break;
Florin Malitae1dadd72017-10-13 18:18:32 -0400130 case SkSVGAttribute::kStrokeDashOffset:
Florin Malitaf4403e72020-04-10 14:14:04 +0000131 if (const SkSVGLengthValue* dashOffset= v.as<SkSVGLengthValue>()) {
Florin Malitae1dadd72017-10-13 18:18:32 -0400132 this->setStrokeDashOffset(*dashOffset);
133 }
134 break;
fmalita2d961e02016-08-11 09:16:29 -0700135 case SkSVGAttribute::kStrokeOpacity:
Florin Malitaf4403e72020-04-10 14:14:04 +0000136 if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
fmalitaca39d712016-08-12 13:17:11 -0700137 this->setStrokeOpacity(*opacity);
fmalita2d961e02016-08-11 09:16:29 -0700138 }
139 break;
Florin Malita4de426b2017-10-09 12:57:41 -0400140 case SkSVGAttribute::kStrokeMiterLimit:
Florin Malitaf4403e72020-04-10 14:14:04 +0000141 if (const SkSVGNumberValue* miterLimit = v.as<SkSVGNumberValue>()) {
Florin Malita09294252020-04-09 08:54:29 -0400142 this->setStrokeMiterLimit(*miterLimit);
Florin Malita4de426b2017-10-09 12:57:41 -0400143 }
144 break;
fmalita2d961e02016-08-11 09:16:29 -0700145 case SkSVGAttribute::kStrokeWidth:
Florin Malitaf4403e72020-04-10 14:14:04 +0000146 if (const SkSVGLengthValue* strokeWidth = v.as<SkSVGLengthValue>()) {
fmalitaca39d712016-08-12 13:17:11 -0700147 this->setStrokeWidth(*strokeWidth);
fmalita6ceef3d2016-07-26 18:46:34 -0700148 }
149 break;
150 default:
Florin Malitac9649ce2018-02-16 13:49:48 -0500151#if defined(SK_VERBOSE_SVG_PARSING)
152 SkDebugf("attribute ID <%d> ignored for node <%d>\n", attr, fTag);
153#endif
fmalita6ceef3d2016-07-26 18:46:34 -0700154 break;
155 }
156}
Tyler Denniston57154992020-11-04 16:08:30 -0500157
Florin Malita8c425672020-11-06 13:49:37 -0500158bool 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));
Tyler Denniston57154992020-11-04 16:08:30 -0500181}