2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPathBuilder.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkScalar.h"
16 #include "include/core/SkSize.h"
17 #include "include/core/SkString.h"
18 #include "include/core/SkTypes.h"
19 #include "include/private/SkFloatBits.h"
20 #include "include/private/SkTArray.h"
22 class ConicPathsGM : public skiagm::GM {
25 SkString onShortName() override {
26 return SkString("conicpaths");
29 SkISize onISize() override {
30 return SkISize::Make(920, 960);
33 template <typename Proc> void append_path(Proc proc) {
36 fPaths.push_back(b.detach());
39 void onOnceBeforeDraw() override {
40 this->append_path([](SkPathBuilder* conicCircle) {
41 const SkScalar w = SkScalarSqrt(2)/2;
42 conicCircle->moveTo(0, 0);
43 conicCircle->conicTo(0, 50, 50, 50, w);
44 conicCircle->rConicTo(50, 0, 50, -50, w);
45 conicCircle->rConicTo(0, -50, -50, -50, w);
46 conicCircle->rConicTo(-50, 0, -50, 50, w);
49 this->append_path([](SkPathBuilder* hyperbola) {
50 hyperbola->moveTo(0, 0);
51 hyperbola->conicTo(0, 100, 100, 100, 2);
54 this->append_path([](SkPathBuilder* thinHyperbola) {
55 thinHyperbola->moveTo(0, 0);
56 thinHyperbola->conicTo(100, 100, 5, 0, 2);
59 this->append_path([](SkPathBuilder* veryThinHyperbola) {
60 veryThinHyperbola->moveTo(0, 0);
61 veryThinHyperbola->conicTo(100, 100, 1, 0, 2);
64 this->append_path([](SkPathBuilder* closedHyperbola) {
65 closedHyperbola->moveTo(0, 0);
66 closedHyperbola->conicTo(100, 100, 0, 0, 2);
69 this->append_path([](SkPathBuilder* nearParabola) {
70 // using 1 as weight defaults to using quadTo
71 nearParabola->moveTo(0, 0);
72 nearParabola->conicTo(0, 100, 100, 100, 0.999f);
75 this->append_path([](SkPathBuilder* thinEllipse) {
76 thinEllipse->moveTo(0, 0);
77 thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf);
80 this->append_path([](SkPathBuilder* veryThinEllipse) {
81 veryThinEllipse->moveTo(0, 0);
82 veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf);
85 this->append_path([](SkPathBuilder* closedEllipse) {
86 closedEllipse->moveTo(0, 0);
87 closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf);
92 const SkScalar w = SkScalarSqrt(2)/2;
93 b.moveTo(2.1e+11f, -1.05e+11f);
94 b.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w);
95 b.conicTo(0, 0, 0, -1.05e+11f, w);
96 b.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w);
97 b.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w);
98 fGiantCircle = b.detach();
102 void drawGiantCircle(SkCanvas* canvas) {
104 canvas->drawPath(fGiantCircle, paint);
107 void onDraw(SkCanvas* canvas) override {
108 const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };
110 const SkScalar margin = 15;
111 canvas->translate(margin, margin);
114 for (int p = 0; p < fPaths.count(); ++p) {
116 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphaValue); ++a) {
117 paint.setARGB(kAlphaValue[a], 0, 0, 0);
118 for (int aa = 0; aa < 2; ++aa) {
119 paint.setAntiAlias(SkToBool(aa));
120 for (int fh = 0; fh < 2; ++fh) {
121 paint.setStroke(fh != 0);
123 const SkRect& bounds = fPaths[p].getBounds();
125 canvas->translate(-bounds.fLeft, -bounds.fTop);
126 canvas->drawPath(fPaths[p], paint);
129 canvas->translate(110, 0);
134 canvas->translate(0, 110);
138 this->drawGiantCircle(canvas);
142 SkTArray<SkPath> fPaths;
144 using INHERITED = skiagm::GM;
146 DEF_GM(return new ConicPathsGM;)
148 //////////////////////////////////////////////////////////////////////////////
150 /* arc should be on top of circle */
151 DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
152 canvas->translate(50, 100);
153 SkPoint c = { 1052.5390625f, 506.8760978034711f };
154 SkScalar radius = 1096.702150363923f;
156 paint.setAntiAlias(true);
157 paint.setStroke(true);
158 canvas->drawCircle(c, radius, paint);
159 SkPath path = SkPathBuilder().moveTo(288.88884710654133f, -280.26680862609f)
160 .arcTo({0, 0}, {-39.00216443306411f, 400.6058925796476f}, radius)
162 paint.setColor(0xff007f00);
163 canvas->drawPath(path, paint);
166 /* circle should be antialiased */
167 DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
168 canvas->translate(50, 100);
169 SkPoint c = { 1052.5390625f, 506.8760978034711f };
170 SkScalar radius = 1096.702150363923f;
172 paint.setAntiAlias(true);
173 paint.setStroke(true);
174 canvas->drawCircle(c, radius, paint);
177 /* ovals should not be blurry */
178 DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
180 SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
182 paint.setAntiAlias(true);
183 paint.setStroke(true);
184 paint.setStrokeWidth(100);
185 canvas->drawOval(r, paint);
187 paint.setColor(SK_ColorDKGRAY);
188 // we use stroke and fill to avoid falling into the SimpleFill path
189 paint.setStyle(SkPaint::kStrokeAndFill_Style);
190 paint.setStrokeWidth(1);
191 canvas->drawOval(r, paint);
194 canvas->rotate(1.0f);
196 paint.setColor(SK_ColorGRAY);
197 paint.setStroke(true);
198 paint.setStrokeWidth(100);
199 canvas->drawOval(r, paint);
201 paint.setColor(SK_ColorLTGRAY);
202 paint.setStyle(SkPaint::kStrokeAndFill_Style);
203 paint.setStrokeWidth(1);
204 canvas->drawOval(r, paint);
207 DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) {
209 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
210 path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000)); // 103.923f, -60
211 path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006)); // 103.923f, -60
212 path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c),
213 SkBits2Float(0x42f00001), SkBits2Float(0x00000000),
214 SkBits2Float(0x3f7746ea)); // 120, -32.1539f, 120, 0, 0.965926f
217 paint.setAntiAlias(true);
218 canvas->translate(125, 125);
219 canvas->drawPath(path.detach(), paint);