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 13bool SkSVGSVG::onPrepareToRender(SkSVGRenderContext* ctx) const { 14 // 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().resolveRectForSVG(x, y, fWidth, fHeight); 19 auto contentMatrix = SkMatrix::Translate(viewPortRect.x(), viewPortRect.y()); 20 auto viewPort = SkSize::Make(viewPortRect.width(), viewPortRect.height()); 21 22 if (fViewBox.isValid()) { 23 const SkRect& viewBox = *fViewBox; 24 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 33 contentMatrix.preConcat(ComputeViewboxMatrix(viewBox, viewPortRect, fPreserveAspectRatio)); 34 } 35 36 if (!contentMatrix.isIdentity()) { 37 ctx->saveOnce(); 38 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 48void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) { 49 switch (attr) { 50 case SkSVGAttribute::kX: 51 if (const auto* x = v.as<SkSVGLengthValue>()) { 52 this->setX(*x); 53 } 54 break; 55 case SkSVGAttribute::kY: 56 if (const auto* y = v.as<SkSVGLengthValue>()) { 57 this->setY(*y); 58 } 59 break; 60 case SkSVGAttribute::kWidth: 61 if (const auto* w = v.as<SkSVGLengthValue>()) { 62 this->setWidth(*w); 63 } 64 break; 65 case SkSVGAttribute::kHeight: 66 if (const auto* h = v.as<SkSVGLengthValue>()) { 67 this->setHeight(*h); 68 } 69 break; 70 case SkSVGAttribute::kViewBox: 71 if (const auto* vb = v.as<SkSVGViewBoxValue>()) { 72 this->setViewBox(*vb); 73 } 74 break; 75 case SkSVGAttribute::kPreserveAspectRatio: 76 if (const auto* par = v.as<SkSVGPreserveAspectRatioValue>()) { 77 this->setPreserveAspectRatio(*par); 78 } 79 break; 80 default: 81 this->INHERITED::onSetAttribute(attr, v); 82 } 83} 84 85// https://www.w3.org/TR/SVG11/coords.html#IntrinsicSizing 86SkSize 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.resolveForSVG(fWidth, SkSVGLengthContext::LengthType::kHorizontal), 94 lctx.resolveForSVG(fHeight, SkSVGLengthContext::LengthType::kVertical)); 95} 96