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 "experimental/svg/model/SkSVGEllipse.h"
9 #include "experimental/svg/model/SkSVGRenderContext.h"
10 #include "experimental/svg/model/SkSVGValue.h"
11 #include "include/core/SkCanvas.h"
12 
SkSVGEllipse()13 SkSVGEllipse::SkSVGEllipse() : INHERITED(SkSVGTag::kEllipse) {}
14 
setCx(const SkSVGLength & cx)15 void SkSVGEllipse::setCx(const SkSVGLength& cx) {
16     fCx = cx;
17 }
18 
setCy(const SkSVGLength & cy)19 void SkSVGEllipse::setCy(const SkSVGLength& cy) {
20     fCy = cy;
21 }
22 
setRx(const SkSVGLength & rx)23 void SkSVGEllipse::setRx(const SkSVGLength& rx) {
24     fRx = rx;
25 }
26 
setRy(const SkSVGLength & ry)27 void SkSVGEllipse::setRy(const SkSVGLength& ry) {
28     fRy = ry;
29 }
30 
onSetAttribute(SkSVGAttribute attr,const SkSVGValue & v)31 void SkSVGEllipse::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
32     switch (attr) {
33     case SkSVGAttribute::kCx:
34         if (const auto* cx = v.as<SkSVGLengthValue>()) {
35             this->setCx(*cx);
36         }
37         break;
38     case SkSVGAttribute::kCy:
39         if (const auto* cy = v.as<SkSVGLengthValue>()) {
40             this->setCy(*cy);
41         }
42         break;
43     case SkSVGAttribute::kRx:
44         if (const auto* rx = v.as<SkSVGLengthValue>()) {
45             this->setRx(*rx);
46         }
47         break;
48     case SkSVGAttribute::kRy:
49         if (const auto* ry = v.as<SkSVGLengthValue>()) {
50             this->setRy(*ry);
51         }
52         break;
53     default:
54         this->INHERITED::onSetAttribute(attr, v);
55     }
56 }
57 
resolve(const SkSVGLengthContext & lctx) const58 SkRect SkSVGEllipse::resolve(const SkSVGLengthContext& lctx) const {
59     const auto cx = lctx.resolve(fCx, SkSVGLengthContext::LengthType::kHorizontal);
60     const auto cy = lctx.resolve(fCy, SkSVGLengthContext::LengthType::kVertical);
61     const auto rx = lctx.resolve(fRx, SkSVGLengthContext::LengthType::kHorizontal);
62     const auto ry = lctx.resolve(fRy, SkSVGLengthContext::LengthType::kVertical);
63 
64     return (rx > 0 && ry > 0)
65         ? SkRect::MakeXYWH(cx - rx, cy - ry, rx * 2, ry * 2)
66         : SkRect::MakeEmpty();
67 }
68 
onDraw(SkCanvas * canvas,const SkSVGLengthContext & lctx,const SkPaint & paint,SkPathFillType) const69 void SkSVGEllipse::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
70                           const SkPaint& paint, SkPathFillType) const {
71     canvas->drawOval(this->resolve(lctx), paint);
72 }
73 
onAsPath(const SkSVGRenderContext & ctx) const74 SkPath SkSVGEllipse::onAsPath(const SkSVGRenderContext& ctx) const {
75     SkPath path;
76     path.addOval(this->resolve(ctx.lengthContext()));
77     this->mapToParent(&path);
78 
79     return path;
80 }
81