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