1/* 2 * Copyright 2017 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 "modules/svg/include/SkSVGUse.h" 9 10#include "include/core/SkCanvas.h" 11#include "modules/svg/include/SkSVGRenderContext.h" 12#include "modules/svg/include/SkSVGValue.h" 13 14SkSVGUse::SkSVGUse() : INHERITED(SkSVGTag::kUse) {} 15 16void SkSVGUse::appendChild(sk_sp<SkSVGNode>) { 17 SkDebugf("cannot append child nodes to this element.\n"); 18} 19 20bool SkSVGUse::parseAndSetAttribute(const char* n, const char* v) { 21 return INHERITED::parseAndSetAttribute(n, v) || 22 this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", n, v)) || 23 this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", n, v)) || 24 this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>("xlink:href", n, v)); 25} 26 27bool SkSVGUse::onPrepareToRender(SkSVGRenderContext* ctx) const { 28 if (fHref.iri().isEmpty() || !INHERITED::onPrepareToRender(ctx)) { 29 return false; 30 } 31 32 if (fX.value() || fY.value()) { 33 // Restored when the local SkSVGRenderContext leaves scope. 34 ctx->saveOnce(); 35 ctx->canvas()->translate(fX.value(), fY.value()); 36 } 37 38 // TODO: width/height override for <svg> targets. 39 40 return true; 41} 42 43void SkSVGUse::onRender(const SkSVGRenderContext& ctx) const { 44 const auto ref = ctx.findNodeById(fHref); 45 if (!ref) { 46 return; 47 } 48 49 ref->render(ctx); 50} 51 52SkPath SkSVGUse::onAsPath(const SkSVGRenderContext& ctx) const { 53 const auto ref = ctx.findNodeById(fHref); 54 if (!ref) { 55 return SkPath(); 56 } 57 58 return ref->asPath(ctx); 59} 60 61SkRect SkSVGUse::onObjectBoundingBox(const SkSVGRenderContext& ctx) const { 62 const auto ref = ctx.findNodeById(fHref); 63 if (!ref) { 64 return SkRect::MakeEmpty(); 65 } 66 67 const SkSVGLengthContext& lctx = ctx.lengthContext(); 68 const SkScalar x = lctx.resolve(fX, SkSVGLengthContext::LengthType::kHorizontal); 69 const SkScalar y = lctx.resolve(fY, SkSVGLengthContext::LengthType::kVertical); 70 71 SkRect bounds = ref->objectBoundingBox(ctx); 72 bounds.offset(x, y); 73 74 return bounds; 75} 76