blob: 7aeccb78d167dba78bbe0f7044834638f634d1df [file] [log] [blame]
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +00001/*
2 * Copyright 2013 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkPaint.h"
Mike Reed2243d772020-07-31 21:57:51 -040012#include "include/core/SkPathBuilder.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#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"
Kevin Lubickdc6cc022023-01-13 11:24:27 -050019#include "include/private/base/SkFloatBits.h"
20#include "include/private/base/SkTArray.h"
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000021
Herb Derbyec96c212023-03-06 10:31:22 -050022using namespace skia_private;
23
reedd1bd1d72014-12-31 20:07:01 -080024class ConicPathsGM : public skiagm::GM {
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000025protected:
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000026 SkString getName() const override { return SkString("conicpaths"); }
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000027
Leandro Lovisolo8f023882023-08-15 21:13:52 +000028 SkISize getISize() override { return SkISize::Make(920, 960); }
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000029
Mike Reed2243d772020-07-31 21:57:51 -040030 template <typename Proc> void append_path(Proc proc) {
31 SkPathBuilder b;
32 proc(&b);
33 fPaths.push_back(b.detach());
34 }
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000035
Mike Reed2243d772020-07-31 21:57:51 -040036 void onOnceBeforeDraw() override {
37 this->append_path([](SkPathBuilder* conicCircle) {
38 const SkScalar w = SkScalarSqrt(2)/2;
39 conicCircle->moveTo(0, 0);
40 conicCircle->conicTo(0, 50, 50, 50, w);
41 conicCircle->rConicTo(50, 0, 50, -50, w);
42 conicCircle->rConicTo(0, -50, -50, -50, w);
43 conicCircle->rConicTo(-50, 0, -50, 50, w);
44 });
45
46 this->append_path([](SkPathBuilder* hyperbola) {
reed40c85e42015-01-05 10:01:25 -080047 hyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080048 hyperbola->conicTo(0, 100, 100, 100, 2);
Mike Reed2243d772020-07-31 21:57:51 -040049 });
50
51 this->append_path([](SkPathBuilder* thinHyperbola) {
reed40c85e42015-01-05 10:01:25 -080052 thinHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080053 thinHyperbola->conicTo(100, 100, 5, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040054 });
55
56 this->append_path([](SkPathBuilder* veryThinHyperbola) {
reed40c85e42015-01-05 10:01:25 -080057 veryThinHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080058 veryThinHyperbola->conicTo(100, 100, 1, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040059 });
60
61 this->append_path([](SkPathBuilder* closedHyperbola) {
reed40c85e42015-01-05 10:01:25 -080062 closedHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080063 closedHyperbola->conicTo(100, 100, 0, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040064 });
65
66 this->append_path([](SkPathBuilder* nearParabola) {
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000067 // using 1 as weight defaults to using quadTo
reed40c85e42015-01-05 10:01:25 -080068 nearParabola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080069 nearParabola->conicTo(0, 100, 100, 100, 0.999f);
Mike Reed2243d772020-07-31 21:57:51 -040070 });
71
72 this->append_path([](SkPathBuilder* thinEllipse) {
reed40c85e42015-01-05 10:01:25 -080073 thinEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080074 thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040075 });
76
77 this->append_path([](SkPathBuilder* veryThinEllipse) {
reed40c85e42015-01-05 10:01:25 -080078 veryThinEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080079 veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040080 });
81
82 this->append_path([](SkPathBuilder* closedEllipse) {
reed40c85e42015-01-05 10:01:25 -080083 closedEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080084 closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040085 });
egdaniel5a23a142015-02-25 06:41:47 -080086
Mike Reed2243d772020-07-31 21:57:51 -040087 {
88 SkPathBuilder b;
89 const SkScalar w = SkScalarSqrt(2)/2;
90 b.moveTo(2.1e+11f, -1.05e+11f);
91 b.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w);
92 b.conicTo(0, 0, 0, -1.05e+11f, w);
93 b.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w);
94 b.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w);
95 fGiantCircle = b.detach();
egdaniel5a23a142015-02-25 06:41:47 -080096 }
97 }
98
99 void drawGiantCircle(SkCanvas* canvas) {
100 SkPaint paint;
101 canvas->drawPath(fGiantCircle, paint);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000102 }
103
mtklein36352bf2015-03-25 18:17:31 -0700104 void onDraw(SkCanvas* canvas) override {
reedd1bd1d72014-12-31 20:07:01 -0800105 const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000106
reedd1bd1d72014-12-31 20:07:01 -0800107 const SkScalar margin = 15;
108 canvas->translate(margin, margin);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000109
reed40c85e42015-01-05 10:01:25 -0800110 SkPaint paint;
Herb Derbyffacce52022-11-09 10:51:34 -0500111 for (int p = 0; p < fPaths.size(); ++p) {
reed40c85e42015-01-05 10:01:25 -0800112 canvas->save();
Herb Derbyc37b3862022-06-21 09:49:17 -0400113 for (size_t a = 0; a < std::size(kAlphaValue); ++a) {
reed40c85e42015-01-05 10:01:25 -0800114 paint.setARGB(kAlphaValue[a], 0, 0, 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000115 for (int aa = 0; aa < 2; ++aa) {
reed40c85e42015-01-05 10:01:25 -0800116 paint.setAntiAlias(SkToBool(aa));
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000117 for (int fh = 0; fh < 2; ++fh) {
Mike Reed19630092020-05-18 21:25:44 -0400118 paint.setStroke(fh != 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000119
120 const SkRect& bounds = fPaths[p].getBounds();
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000121 canvas->save();
122 canvas->translate(-bounds.fLeft, -bounds.fTop);
123 canvas->drawPath(fPaths[p], paint);
124 canvas->restore();
125
reed40c85e42015-01-05 10:01:25 -0800126 canvas->translate(110, 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000127 }
128 }
129 }
reed40c85e42015-01-05 10:01:25 -0800130 canvas->restore();
131 canvas->translate(0, 110);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000132 }
133 canvas->restore();
egdaniel5a23a142015-02-25 06:41:47 -0800134
halcanary9d524f22016-03-29 09:03:52 -0700135 this->drawGiantCircle(canvas);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000136 }
137
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000138private:
Herb Derbyec96c212023-03-06 10:31:22 -0500139 TArray<SkPath> fPaths;
egdaniel5a23a142015-02-25 06:41:47 -0800140 SkPath fGiantCircle;
John Stiles7571f9e2020-09-02 22:42:33 -0400141 using INHERITED = skiagm::GM;
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000142};
halcanary385fe4d2015-08-26 13:07:48 -0700143DEF_GM(return new ConicPathsGM;)
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000144
145//////////////////////////////////////////////////////////////////////////////
146
caryclark2b39ffc2016-01-20 07:46:05 -0800147/* arc should be on top of circle */
148DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
149 canvas->translate(50, 100);
150 SkPoint c = { 1052.5390625f, 506.8760978034711f };
151 SkScalar radius = 1096.702150363923f;
152 SkPaint paint;
153 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400154 paint.setStroke(true);
Hal Canary23e474c2017-05-15 13:35:35 -0400155 canvas->drawCircle(c, radius, paint);
Mike Reedcfb130c2020-08-03 11:02:20 -0400156 SkPath path = SkPathBuilder().moveTo(288.88884710654133f, -280.26680862609f)
157 .arcTo({0, 0}, {-39.00216443306411f, 400.6058925796476f}, radius)
158 .detach();
caryclark2b39ffc2016-01-20 07:46:05 -0800159 paint.setColor(0xff007f00);
160 canvas->drawPath(path, paint);
161}
caryclark531191f2016-08-24 11:59:30 -0700162
Jim Van Verth6750e912016-12-19 14:45:19 -0500163/* circle should be antialiased */
164DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
165 canvas->translate(50, 100);
166 SkPoint c = { 1052.5390625f, 506.8760978034711f };
167 SkScalar radius = 1096.702150363923f;
168 SkPaint paint;
169 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400170 paint.setStroke(true);
Hal Canary23e474c2017-05-15 13:35:35 -0400171 canvas->drawCircle(c, radius, paint);
Jim Van Verth6750e912016-12-19 14:45:19 -0500172}
173
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400174/* ovals should not be blurry */
175DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
176 // Test EllipseOp
177 SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
178 SkPaint paint;
179 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400180 paint.setStroke(true);
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400181 paint.setStrokeWidth(100);
182 canvas->drawOval(r, paint);
183 r.offset(-15, -15);
184 paint.setColor(SK_ColorDKGRAY);
185 // we use stroke and fill to avoid falling into the SimpleFill path
186 paint.setStyle(SkPaint::kStrokeAndFill_Style);
187 paint.setStrokeWidth(1);
188 canvas->drawOval(r, paint);
189
190 // Test DIEllipseOp
191 canvas->rotate(1.0f);
192 r.offset(55, 55);
193 paint.setColor(SK_ColorGRAY);
Mike Reed19630092020-05-18 21:25:44 -0400194 paint.setStroke(true);
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400195 paint.setStrokeWidth(100);
196 canvas->drawOval(r, paint);
197 r.offset(-15, -15);
198 paint.setColor(SK_ColorLTGRAY);
199 paint.setStyle(SkPaint::kStrokeAndFill_Style);
200 paint.setStrokeWidth(1);
201 canvas->drawOval(r, paint);
202}
203
caryclark531191f2016-08-24 11:59:30 -0700204DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) {
Mike Reed2243d772020-07-31 21:57:51 -0400205 SkPathBuilder path;
caryclark531191f2016-08-24 11:59:30 -0700206 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
207 path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000)); // 103.923f, -60
208 path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006)); // 103.923f, -60
209 path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c),
210 SkBits2Float(0x42f00001), SkBits2Float(0x00000000),
211 SkBits2Float(0x3f7746ea)); // 120, -32.1539f, 120, 0, 0.965926f
212
213 SkPaint paint;
214 paint.setAntiAlias(true);
215 canvas->translate(125, 125);
Mike Reed2243d772020-07-31 21:57:51 -0400216 canvas->drawPath(path.detach(), paint);
caryclark531191f2016-08-24 11:59:30 -0700217}