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 16 SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { } 17 18 SkSVGNode::~SkSVGNode() { } 19 20 void SkSVGNode::render(const SkSVGRenderContext& ctx) const { 21 SkSVGRenderContext localContext(ctx); 22 23 if (this->onPrepareToRender(&localContext)) { 24 this->onRender(localContext); 25 } 26 } 27 28 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 34 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 50 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 59 void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) { 60 this->onSetAttribute(attr, v); 61 } 62 63 void SkSVGNode::setClipPath(const SkSVGClip& clip) { 64 fPresentationAttributes.fClipPath.set(clip); 65 } 66 67 void SkSVGNode::setClipRule(const SkSVGFillRule& clipRule) { 68 fPresentationAttributes.fClipRule.set(clipRule); 69 } 70 71 void SkSVGNode::setFill(const SkSVGPaint& svgPaint) { 72 fPresentationAttributes.fFill.set(svgPaint); 73 } 74 75 void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) { 76 fPresentationAttributes.fFillOpacity.set( 77 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 78 } 79 80 void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) { 81 fPresentationAttributes.fFillRule.set(fillRule); 82 } 83 84 void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) { 85 fPresentationAttributes.fOpacity.set( 86 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 87 } 88 89 void SkSVGNode::setStroke(const SkSVGPaint& svgPaint) { 90 fPresentationAttributes.fStroke.set(svgPaint); 91 } 92 93 void SkSVGNode::setStrokeDashArray(const SkSVGDashArray& dashArray) { 94 fPresentationAttributes.fStrokeDashArray.set(dashArray); 95 } 96 97 void SkSVGNode::setStrokeDashOffset(const SkSVGLength& dashOffset) { 98 fPresentationAttributes.fStrokeDashOffset.set(dashOffset); 99 } 100 101 void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) { 102 fPresentationAttributes.fStrokeOpacity.set( 103 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 104 } 105 106 void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) { 107 fPresentationAttributes.fStrokeWidth.set(strokeWidth); 108 } 109 110 void SkSVGNode::setVisibility(const SkSVGVisibility& visibility) { 111 fPresentationAttributes.fVisibility.set(visibility); 112 } 113 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