• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkCanvas.h"
9 #include "modules/svg/include/SkSVGRenderContext.h"
10 #include "modules/svg/include/SkSVGSVG.h"
11 #include "modules/svg/include/SkSVGValue.h"
12 
renderNode(const SkSVGRenderContext & ctx,const SkSVGIRI & iri) const13 void SkSVGSVG::renderNode(const SkSVGRenderContext& ctx, const SkSVGIRI& iri) const {
14     SkSVGRenderContext localContext(ctx, this);
15     SkSVGRenderContext::BorrowedNode node = localContext.findNodeById(iri);
16     if (!node) {
17         return;
18     }
19 
20     if (this->onPrepareToRender(&localContext)) {
21         if (this == node.get()) {
22             this->onRender(ctx);
23         } else {
24             node->render(localContext);
25         }
26     }
27 }
28 
onPrepareToRender(SkSVGRenderContext * ctx) const29 bool SkSVGSVG::onPrepareToRender(SkSVGRenderContext* ctx) const {
30     // x/y are ignored for outermost svg elements
31     const auto x = fType == Type::kInner ? fX : SkSVGLength(0);
32     const auto y = fType == Type::kInner ? fY : SkSVGLength(0);
33 
34     auto viewPortRect  = ctx->lengthContext().resolveRect(x, y, fWidth, fHeight);
35     auto contentMatrix = SkMatrix::Translate(viewPortRect.x(), viewPortRect.y());
36     auto viewPort      = SkSize::Make(viewPortRect.width(), viewPortRect.height());
37 
38     if (fViewBox.isValid()) {
39         const SkRect& viewBox = *fViewBox;
40 
41         // An empty viewbox disables rendering.
42         if (viewBox.isEmpty()) {
43             return false;
44         }
45 
46         // A viewBox overrides the intrinsic viewport.
47         viewPort = SkSize::Make(viewBox.width(), viewBox.height());
48 
49         contentMatrix.preConcat(ComputeViewboxMatrix(viewBox, viewPortRect, fPreserveAspectRatio));
50     }
51 
52     if (!contentMatrix.isIdentity()) {
53         ctx->saveOnce();
54         ctx->canvas()->concat(contentMatrix);
55     }
56 
57     if (viewPort != ctx->lengthContext().viewPort()) {
58         ctx->writableLengthContext()->setViewPort(viewPort);
59     }
60 
61     return this->INHERITED::onPrepareToRender(ctx);
62 }
63 
onSetAttribute(SkSVGAttribute attr,const SkSVGValue & v)64 void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
65     switch (attr) {
66     case SkSVGAttribute::kX:
67         if (const auto* x = v.as<SkSVGLengthValue>()) {
68             this->setX(*x);
69         }
70         break;
71     case SkSVGAttribute::kY:
72         if (const auto* y = v.as<SkSVGLengthValue>()) {
73             this->setY(*y);
74         }
75         break;
76     case SkSVGAttribute::kWidth:
77         if (const auto* w = v.as<SkSVGLengthValue>()) {
78             this->setWidth(*w);
79         }
80         break;
81     case SkSVGAttribute::kHeight:
82         if (const auto* h = v.as<SkSVGLengthValue>()) {
83             this->setHeight(*h);
84         }
85         break;
86     case SkSVGAttribute::kViewBox:
87         if (const auto* vb = v.as<SkSVGViewBoxValue>()) {
88             this->setViewBox(*vb);
89         }
90         break;
91     case SkSVGAttribute::kPreserveAspectRatio:
92         if (const auto* par = v.as<SkSVGPreserveAspectRatioValue>()) {
93             this->setPreserveAspectRatio(*par);
94         }
95         break;
96     default:
97         this->INHERITED::onSetAttribute(attr, v);
98     }
99 }
100 
101 // https://www.w3.org/TR/SVG11/coords.html#IntrinsicSizing
intrinsicSize(const SkSVGLengthContext & lctx) const102 SkSize SkSVGSVG::intrinsicSize(const SkSVGLengthContext& lctx) const {
103     // Percentage values do not provide an intrinsic size.
104     if (fWidth.unit() == SkSVGLength::Unit::kPercentage ||
105         fHeight.unit() == SkSVGLength::Unit::kPercentage) {
106         return SkSize::Make(0, 0);
107     }
108 
109     return SkSize::Make(lctx.resolve(fWidth, SkSVGLengthContext::LengthType::kHorizontal),
110                         lctx.resolve(fHeight, SkSVGLengthContext::LengthType::kVertical));
111 }
112