Home | History | Annotate | Download | only in model
      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