/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "experimental/svg/model/SkSVGRenderContext.h" #include "experimental/svg/model/SkSVGSVG.h" #include "experimental/svg/model/SkSVGValue.h" #include "include/core/SkCanvas.h" SkSVGSVG::SkSVGSVG() : INHERITED(SkSVGTag::kSvg) { } bool SkSVGSVG::onPrepareToRender(SkSVGRenderContext* ctx) const { auto viewPortRect = ctx->lengthContext().resolveRect(fX, fY, fWidth, fHeight); auto contentMatrix = SkMatrix::Translate(viewPortRect.x(), viewPortRect.y()); auto viewPort = SkSize::Make(viewPortRect.width(), viewPortRect.height()); if (fViewBox.isValid()) { const SkRect& viewBox = *fViewBox.get(); // An empty viewbox disables rendering. if (viewBox.isEmpty()) { return false; } // A viewBox overrides the intrinsic viewport. viewPort = SkSize::Make(viewBox.width(), viewBox.height()); contentMatrix.preConcat( SkMatrix::MakeRectToRect(viewBox, viewPortRect, SkMatrix::kFill_ScaleToFit)); } if (!contentMatrix.isIdentity()) { ctx->saveOnce(); ctx->canvas()->concat(contentMatrix); } if (viewPort != ctx->lengthContext().viewPort()) { ctx->writableLengthContext()->setViewPort(viewPort); } return this->INHERITED::onPrepareToRender(ctx); } void SkSVGSVG::setX(const SkSVGLength& x) { fX = x; } void SkSVGSVG::setY(const SkSVGLength& y) { fY = y; } void SkSVGSVG::setWidth(const SkSVGLength& w) { fWidth = w; } void SkSVGSVG::setHeight(const SkSVGLength& h) { fHeight = h; } void SkSVGSVG::setViewBox(const SkSVGViewBoxType& vb) { fViewBox.set(vb); } void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) { switch (attr) { case SkSVGAttribute::kX: if (const auto* x = v.as()) { this->setX(*x); } break; case SkSVGAttribute::kY: if (const auto* y = v.as()) { this->setY(*y); } break; case SkSVGAttribute::kWidth: if (const auto* w = v.as()) { this->setWidth(*w); } break; case SkSVGAttribute::kHeight: if (const auto* h = v.as()) { this->setHeight(*h); } break; case SkSVGAttribute::kViewBox: if (const auto* vb = v.as()) { this->setViewBox(*vb); } break; default: this->INHERITED::onSetAttribute(attr, v); } } // https://www.w3.org/TR/SVG11/coords.html#IntrinsicSizing SkSize SkSVGSVG::intrinsicSize(const SkSVGLengthContext& lctx) const { // Percentage values do not provide an intrinsic size. if (fWidth.unit() == SkSVGLength::Unit::kPercentage || fHeight.unit() == SkSVGLength::Unit::kPercentage) { return SkSize::Make(0, 0); } return SkSize::Make(lctx.resolve(fWidth, SkSVGLengthContext::LengthType::kHorizontal), lctx.resolve(fHeight, SkSVGLengthContext::LengthType::kVertical)); }