• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkSVGUse()14 SkSVGUse::SkSVGUse() : INHERITED(SkSVGTag::kUse) {}
15 
appendChild(sk_sp<SkSVGNode>)16 void SkSVGUse::appendChild(sk_sp<SkSVGNode>) {
17     SkDebugf("cannot append child nodes to this element.\n");
18 }
19 
parseAndSetAttribute(const char * n,const char * v)20 bool 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 
onPrepareToRender(SkSVGRenderContext * ctx) const27 bool 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 
onRender(const SkSVGRenderContext & ctx) const43 void 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 
onAsPath(const SkSVGRenderContext & ctx) const52 SkPath 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 
onObjectBoundingBox(const SkSVGRenderContext & ctx) const61 SkRect 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