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 16SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { } 17 18SkSVGNode::~SkSVGNode() { } 19 20void SkSVGNode::render(const SkSVGRenderContext& ctx) const { 21 SkSVGRenderContext localContext(ctx); 22 23 if (this->onPrepareToRender(&localContext)) { 24 this->onRender(localContext); 25 } 26} 27 28bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const { 29 SkSVGRenderContext localContext(ctx); 30 31 return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint); 32} 33 34SkPath 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 50bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const { 51 ctx->applyPresentationAttributes(fPresentationAttributes, 52 this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf); 53 return true; 54} 55 56void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) { 57 this->onSetAttribute(attr, v); 58} 59 60void SkSVGNode::setClipPath(const SkSVGClip& clip) { 61 fPresentationAttributes.fClipPath.set(clip); 62} 63 64void SkSVGNode::setFill(const SkSVGPaint& svgPaint) { 65 fPresentationAttributes.fFill.set(svgPaint); 66} 67 68void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) { 69 fPresentationAttributes.fFillOpacity.set( 70 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 71} 72 73void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) { 74 fPresentationAttributes.fFillRule.set(fillRule); 75} 76 77void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) { 78 fPresentationAttributes.fOpacity.set( 79 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 80} 81 82void SkSVGNode::setStroke(const SkSVGPaint& svgPaint) { 83 fPresentationAttributes.fStroke.set(svgPaint); 84} 85 86void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) { 87 fPresentationAttributes.fStrokeOpacity.set( 88 SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1))); 89} 90 91void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) { 92 fPresentationAttributes.fStrokeWidth.set(strokeWidth); 93} 94 95void 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