2016-07-27 01:46:34 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SkCanvas.h"
|
|
|
|
#include "SkMatrix.h"
|
2016-12-08 21:04:24 +00:00
|
|
|
#include "SkPathOps.h"
|
2016-07-27 01:46:34 +00:00
|
|
|
#include "SkSVGNode.h"
|
|
|
|
#include "SkSVGRenderContext.h"
|
|
|
|
#include "SkSVGValue.h"
|
|
|
|
#include "SkTLazy.h"
|
|
|
|
|
|
|
|
SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
|
|
|
|
|
|
|
|
SkSVGNode::~SkSVGNode() { }
|
|
|
|
|
2016-08-08 18:38:55 +00:00
|
|
|
void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
|
|
|
|
SkSVGRenderContext localContext(ctx);
|
|
|
|
|
|
|
|
if (this->onPrepareToRender(&localContext)) {
|
|
|
|
this->onRender(localContext);
|
2016-07-27 01:46:34 +00:00
|
|
|
}
|
2016-08-08 18:38:55 +00:00
|
|
|
}
|
2016-07-27 01:46:34 +00:00
|
|
|
|
2016-09-13 00:06:47 +00:00
|
|
|
bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
|
|
|
|
SkSVGRenderContext localContext(ctx);
|
|
|
|
|
|
|
|
return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint);
|
|
|
|
}
|
|
|
|
|
2016-12-08 14:26:47 +00:00
|
|
|
SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
|
|
|
|
SkSVGRenderContext localContext(ctx);
|
2016-12-08 21:04:24 +00:00
|
|
|
if (!this->onPrepareToRender(&localContext)) {
|
|
|
|
return SkPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPath path = this->onAsPath(localContext);
|
|
|
|
|
|
|
|
if (const auto* clipPath = localContext.clipPath()) {
|
|
|
|
// There is a clip-path present on the current node.
|
|
|
|
Op(path, *clipPath, kIntersect_SkPathOp, &path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return path;
|
2016-12-08 14:26:47 +00:00
|
|
|
}
|
|
|
|
|
2016-08-08 18:38:55 +00:00
|
|
|
bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
|
2016-09-20 22:45:57 +00:00
|
|
|
ctx->applyPresentationAttributes(fPresentationAttributes,
|
|
|
|
this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);
|
2017-10-12 15:33:28 +00:00
|
|
|
|
|
|
|
// visibility:hidden disables rendering
|
|
|
|
const auto visibility = ctx->presentationContext().fInherited.fVisibility.get()->type();
|
|
|
|
return visibility != SkSVGVisibility::Type::kHidden;
|
2016-07-27 01:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
|
|
|
|
this->onSetAttribute(attr, v);
|
|
|
|
}
|
|
|
|
|
2016-12-08 14:26:47 +00:00
|
|
|
void SkSVGNode::setClipPath(const SkSVGClip& clip) {
|
|
|
|
fPresentationAttributes.fClipPath.set(clip);
|
|
|
|
}
|
|
|
|
|
2017-10-10 15:22:08 +00:00
|
|
|
void SkSVGNode::setClipRule(const SkSVGFillRule& clipRule) {
|
|
|
|
fPresentationAttributes.fClipRule.set(clipRule);
|
|
|
|
}
|
|
|
|
|
2016-08-12 20:17:11 +00:00
|
|
|
void SkSVGNode::setFill(const SkSVGPaint& svgPaint) {
|
|
|
|
fPresentationAttributes.fFill.set(svgPaint);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
|
|
|
|
fPresentationAttributes.fFillOpacity.set(
|
|
|
|
SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
|
|
|
|
}
|
|
|
|
|
2016-12-01 18:35:11 +00:00
|
|
|
void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) {
|
|
|
|
fPresentationAttributes.fFillRule.set(fillRule);
|
|
|
|
}
|
|
|
|
|
2016-08-15 19:45:11 +00:00
|
|
|
void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
|
|
|
|
fPresentationAttributes.fOpacity.set(
|
|
|
|
SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
|
|
|
|
}
|
|
|
|
|
2016-08-12 20:17:11 +00:00
|
|
|
void SkSVGNode::setStroke(const SkSVGPaint& svgPaint) {
|
|
|
|
fPresentationAttributes.fStroke.set(svgPaint);
|
|
|
|
}
|
|
|
|
|
2017-10-13 18:07:44 +00:00
|
|
|
void SkSVGNode::setStrokeDashArray(const SkSVGDashArray& dashArray) {
|
|
|
|
fPresentationAttributes.fStrokeDashArray.set(dashArray);
|
|
|
|
}
|
|
|
|
|
2017-10-13 22:18:32 +00:00
|
|
|
void SkSVGNode::setStrokeDashOffset(const SkSVGLength& dashOffset) {
|
|
|
|
fPresentationAttributes.fStrokeDashOffset.set(dashOffset);
|
|
|
|
}
|
|
|
|
|
2016-08-12 20:17:11 +00:00
|
|
|
void SkSVGNode::setStrokeOpacity(const SkSVGNumberType& opacity) {
|
|
|
|
fPresentationAttributes.fStrokeOpacity.set(
|
|
|
|
SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkSVGNode::setStrokeWidth(const SkSVGLength& strokeWidth) {
|
|
|
|
fPresentationAttributes.fStrokeWidth.set(strokeWidth);
|
|
|
|
}
|
|
|
|
|
2017-10-12 15:33:28 +00:00
|
|
|
void SkSVGNode::setVisibility(const SkSVGVisibility& visibility) {
|
|
|
|
fPresentationAttributes.fVisibility.set(visibility);
|
|
|
|
}
|
|
|
|
|
2016-07-27 01:46:34 +00:00
|
|
|
void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
|
|
|
|
switch (attr) {
|
2016-12-08 14:26:47 +00:00
|
|
|
case SkSVGAttribute::kClipPath:
|
|
|
|
if (const SkSVGClipValue* clip = v.as<SkSVGClipValue>()) {
|
|
|
|
this->setClipPath(*clip);
|
|
|
|
}
|
|
|
|
break;
|
2017-10-10 15:22:08 +00:00
|
|
|
case SkSVGAttribute::kClipRule:
|
|
|
|
if (const SkSVGFillRuleValue* clipRule = v.as<SkSVGFillRuleValue>()) {
|
|
|
|
this->setClipRule(*clipRule);
|
|
|
|
}
|
|
|
|
break;
|
2016-07-29 15:52:03 +00:00
|
|
|
case SkSVGAttribute::kFill:
|
2016-08-11 16:16:29 +00:00
|
|
|
if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
|
2016-08-12 20:17:11 +00:00
|
|
|
this->setFill(*paint);
|
2016-08-11 16:16:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkSVGAttribute::kFillOpacity:
|
|
|
|
if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
|
2016-08-12 20:17:11 +00:00
|
|
|
this->setFillOpacity(*opacity);
|
2016-07-27 01:46:34 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-12-01 18:35:11 +00:00
|
|
|
case SkSVGAttribute::kFillRule:
|
|
|
|
if (const SkSVGFillRuleValue* fillRule = v.as<SkSVGFillRuleValue>()) {
|
|
|
|
this->setFillRule(*fillRule);
|
|
|
|
}
|
|
|
|
break;
|
2016-08-15 19:45:11 +00:00
|
|
|
case SkSVGAttribute::kOpacity:
|
|
|
|
if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
|
|
|
|
this->setOpacity(*opacity);
|
|
|
|
}
|
|
|
|
break;
|
2016-07-29 15:52:03 +00:00
|
|
|
case SkSVGAttribute::kStroke:
|
2016-08-11 16:16:29 +00:00
|
|
|
if (const SkSVGPaintValue* paint = v.as<SkSVGPaintValue>()) {
|
2016-08-12 20:17:11 +00:00
|
|
|
this->setStroke(*paint);
|
2016-08-11 16:16:29 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-10-13 18:07:44 +00:00
|
|
|
case SkSVGAttribute::kStrokeDashArray:
|
|
|
|
if (const SkSVGDashArrayValue* dashArray = v.as<SkSVGDashArrayValue>()) {
|
|
|
|
this->setStrokeDashArray(*dashArray);
|
|
|
|
}
|
|
|
|
break;
|
2017-10-13 22:18:32 +00:00
|
|
|
case SkSVGAttribute::kStrokeDashOffset:
|
|
|
|
if (const SkSVGLengthValue* dashOffset= v.as<SkSVGLengthValue>()) {
|
|
|
|
this->setStrokeDashOffset(*dashOffset);
|
|
|
|
}
|
|
|
|
break;
|
2016-08-11 16:16:29 +00:00
|
|
|
case SkSVGAttribute::kStrokeOpacity:
|
|
|
|
if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
|
2016-08-12 20:17:11 +00:00
|
|
|
this->setStrokeOpacity(*opacity);
|
2016-08-11 16:16:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkSVGAttribute::kStrokeLineCap:
|
|
|
|
if (const SkSVGLineCapValue* lineCap = v.as<SkSVGLineCapValue>()) {
|
|
|
|
fPresentationAttributes.fStrokeLineCap.set(*lineCap);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkSVGAttribute::kStrokeLineJoin:
|
|
|
|
if (const SkSVGLineJoinValue* lineJoin = v.as<SkSVGLineJoinValue>()) {
|
|
|
|
fPresentationAttributes.fStrokeLineJoin.set(*lineJoin);
|
|
|
|
}
|
|
|
|
break;
|
2017-10-09 16:57:41 +00:00
|
|
|
case SkSVGAttribute::kStrokeMiterLimit:
|
|
|
|
if (const SkSVGNumberValue* miterLimit = v.as<SkSVGNumberValue>()) {
|
|
|
|
fPresentationAttributes.fStrokeMiterLimit.set(*miterLimit);
|
|
|
|
}
|
|
|
|
break;
|
2016-08-11 16:16:29 +00:00
|
|
|
case SkSVGAttribute::kStrokeWidth:
|
|
|
|
if (const SkSVGLengthValue* strokeWidth = v.as<SkSVGLengthValue>()) {
|
2016-08-12 20:17:11 +00:00
|
|
|
this->setStrokeWidth(*strokeWidth);
|
2016-07-27 01:46:34 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-10-12 15:33:28 +00:00
|
|
|
case SkSVGAttribute::kVisibility:
|
|
|
|
if (const SkSVGVisibilityValue* visibility = v.as<SkSVGVisibilityValue>()) {
|
|
|
|
this->setVisibility(*visibility);
|
|
|
|
}
|
|
|
|
break;
|
2016-07-27 01:46:34 +00:00
|
|
|
default:
|
2018-02-16 18:49:48 +00:00
|
|
|
#if defined(SK_VERBOSE_SVG_PARSING)
|
|
|
|
SkDebugf("attribute ID <%d> ignored for node <%d>\n", attr, fTag);
|
|
|
|
#endif
|
2016-07-27 01:46:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|