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