Home | History | Annotate | Download | only in model
      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