blob: 8292578b341f4448af9c70a51ccc6c31c02c2e09 [file] [log] [blame]
fmalita6ceef3d2016-07-26 18:46:34 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
Florin Malitab3418102020-10-15 18:10:29 -04009#include "modules/svg/include/SkSVGRenderContext.h"
10#include "modules/svg/include/SkSVGSVG.h"
11#include "modules/svg/include/SkSVGValue.h"
fmalita6ceef3d2016-07-26 18:46:34 -070012
fmalita397a5172016-08-08 11:38:55 -070013bool SkSVGSVG::onPrepareToRender(SkSVGRenderContext* ctx) const {
Florin Malitacdeabca2021-01-20 13:21:20 -050014 // x/y are ignored for outermost svg elements
15 const auto x = fType == Type::kInner ? fX : SkSVGLength(0);
16 const auto y = fType == Type::kInner ? fY : SkSVGLength(0);
17
18 auto viewPortRect = ctx->lengthContext().resolveRect(x, y, fWidth, fHeight);
Mike Reed1f607332020-05-21 12:11:27 -040019 auto contentMatrix = SkMatrix::Translate(viewPortRect.x(), viewPortRect.y());
fmalita397a5172016-08-08 11:38:55 -070020 auto viewPort = SkSize::Make(viewPortRect.width(), viewPortRect.height());
21
22 if (fViewBox.isValid()) {
John Stilesa008b0f2020-08-16 08:48:02 -040023 const SkRect& viewBox = *fViewBox;
fmalita397a5172016-08-08 11:38:55 -070024
25 // An empty viewbox disables rendering.
26 if (viewBox.isEmpty()) {
27 return false;
28 }
29
30 // A viewBox overrides the intrinsic viewport.
31 viewPort = SkSize::Make(viewBox.width(), viewBox.height());
32
Tyler Denniston1f4cd072021-02-05 09:08:33 -050033 contentMatrix.preConcat(ComputeViewboxMatrix(viewBox, viewPortRect, fPreserveAspectRatio));
fmalita397a5172016-08-08 11:38:55 -070034 }
35
36 if (!contentMatrix.isIdentity()) {
Florin Malitab36be142017-10-11 14:11:16 -040037 ctx->saveOnce();
fmalita397a5172016-08-08 11:38:55 -070038 ctx->canvas()->concat(contentMatrix);
39 }
40
41 if (viewPort != ctx->lengthContext().viewPort()) {
42 ctx->writableLengthContext()->setViewPort(viewPort);
43 }
44
45 return this->INHERITED::onPrepareToRender(ctx);
46}
47
Florin Malitaf4403e72020-04-10 14:14:04 +000048void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
fmalitabffc2562016-08-03 10:21:11 -070049 switch (attr) {
50 case SkSVGAttribute::kX:
Florin Malitaf4403e72020-04-10 14:14:04 +000051 if (const auto* x = v.as<SkSVGLengthValue>()) {
fmalitabffc2562016-08-03 10:21:11 -070052 this->setX(*x);
53 }
54 break;
55 case SkSVGAttribute::kY:
Florin Malitaf4403e72020-04-10 14:14:04 +000056 if (const auto* y = v.as<SkSVGLengthValue>()) {
fmalitabffc2562016-08-03 10:21:11 -070057 this->setY(*y);
58 }
59 break;
60 case SkSVGAttribute::kWidth:
Florin Malitaf4403e72020-04-10 14:14:04 +000061 if (const auto* w = v.as<SkSVGLengthValue>()) {
fmalitabffc2562016-08-03 10:21:11 -070062 this->setWidth(*w);
63 }
64 break;
65 case SkSVGAttribute::kHeight:
Florin Malitaf4403e72020-04-10 14:14:04 +000066 if (const auto* h = v.as<SkSVGLengthValue>()) {
fmalitabffc2562016-08-03 10:21:11 -070067 this->setHeight(*h);
68 }
69 break;
fmalita397a5172016-08-08 11:38:55 -070070 case SkSVGAttribute::kViewBox:
Florin Malitaf4403e72020-04-10 14:14:04 +000071 if (const auto* vb = v.as<SkSVGViewBoxValue>()) {
fmalita397a5172016-08-08 11:38:55 -070072 this->setViewBox(*vb);
73 }
74 break;
Florin Malita385e7442020-10-21 16:55:46 -040075 case SkSVGAttribute::kPreserveAspectRatio:
76 if (const auto* par = v.as<SkSVGPreserveAspectRatioValue>()) {
77 this->setPreserveAspectRatio(*par);
78 }
79 break;
fmalitabffc2562016-08-03 10:21:11 -070080 default:
81 this->INHERITED::onSetAttribute(attr, v);
82 }
83}
fmalitae1baa7c2016-09-14 12:04:30 -070084
Florin Malitaf005c252020-04-08 10:10:53 -040085// https://www.w3.org/TR/SVG11/coords.html#IntrinsicSizing
fmalitae1baa7c2016-09-14 12:04:30 -070086SkSize SkSVGSVG::intrinsicSize(const SkSVGLengthContext& lctx) const {
87 // Percentage values do not provide an intrinsic size.
88 if (fWidth.unit() == SkSVGLength::Unit::kPercentage ||
89 fHeight.unit() == SkSVGLength::Unit::kPercentage) {
90 return SkSize::Make(0, 0);
91 }
92
93 return SkSize::Make(lctx.resolve(fWidth, SkSVGLengthContext::LengthType::kHorizontal),
94 lctx.resolve(fHeight, SkSVGLengthContext::LengthType::kVertical));
95}