blob: 49be3fcd870f181ef999d8dbe56c4f3443d4e529 [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"
19#include "include/private/SkFloatBits.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/private/SkTArray.h"
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000021
reedd1bd1d72014-12-31 20:07:01 -080022class ConicPathsGM : public skiagm::GM {
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000023protected:
24
mtklein36352bf2015-03-25 18:17:31 -070025 SkString onShortName() override {
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000026 return SkString("conicpaths");
27 }
28
mtklein36352bf2015-03-25 18:17:31 -070029 SkISize onISize() override {
reed40c85e42015-01-05 10:01:25 -080030 return SkISize::Make(920, 960);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000031 }
32
Mike Reed2243d772020-07-31 21:57:51 -040033 template <typename Proc> void append_path(Proc proc) {
34 SkPathBuilder b;
35 proc(&b);
36 fPaths.push_back(b.detach());
37 }
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000038
Mike Reed2243d772020-07-31 21:57:51 -040039 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);
47 });
48
49 this->append_path([](SkPathBuilder* hyperbola) {
reed40c85e42015-01-05 10:01:25 -080050 hyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080051 hyperbola->conicTo(0, 100, 100, 100, 2);
Mike Reed2243d772020-07-31 21:57:51 -040052 });
53
54 this->append_path([](SkPathBuilder* thinHyperbola) {
reed40c85e42015-01-05 10:01:25 -080055 thinHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080056 thinHyperbola->conicTo(100, 100, 5, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040057 });
58
59 this->append_path([](SkPathBuilder* veryThinHyperbola) {
reed40c85e42015-01-05 10:01:25 -080060 veryThinHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080061 veryThinHyperbola->conicTo(100, 100, 1, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040062 });
63
64 this->append_path([](SkPathBuilder* closedHyperbola) {
reed40c85e42015-01-05 10:01:25 -080065 closedHyperbola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080066 closedHyperbola->conicTo(100, 100, 0, 0, 2);
Mike Reed2243d772020-07-31 21:57:51 -040067 });
68
69 this->append_path([](SkPathBuilder* nearParabola) {
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +000070 // using 1 as weight defaults to using quadTo
reed40c85e42015-01-05 10:01:25 -080071 nearParabola->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080072 nearParabola->conicTo(0, 100, 100, 100, 0.999f);
Mike Reed2243d772020-07-31 21:57:51 -040073 });
74
75 this->append_path([](SkPathBuilder* thinEllipse) {
reed40c85e42015-01-05 10:01:25 -080076 thinEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080077 thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040078 });
79
80 this->append_path([](SkPathBuilder* veryThinEllipse) {
reed40c85e42015-01-05 10:01:25 -080081 veryThinEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080082 veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040083 });
84
85 this->append_path([](SkPathBuilder* closedEllipse) {
reed40c85e42015-01-05 10:01:25 -080086 closedEllipse->moveTo(0, 0);
reedd1bd1d72014-12-31 20:07:01 -080087 closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf);
Mike Reed2243d772020-07-31 21:57:51 -040088 });
egdaniel5a23a142015-02-25 06:41:47 -080089
Mike Reed2243d772020-07-31 21:57:51 -040090 {
91 SkPathBuilder b;
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();
egdaniel5a23a142015-02-25 06:41:47 -080099 }
100 }
101
102 void drawGiantCircle(SkCanvas* canvas) {
103 SkPaint paint;
104 canvas->drawPath(fGiantCircle, paint);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000105 }
106
mtklein36352bf2015-03-25 18:17:31 -0700107 void onDraw(SkCanvas* canvas) override {
reedd1bd1d72014-12-31 20:07:01 -0800108 const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000109
reedd1bd1d72014-12-31 20:07:01 -0800110 const SkScalar margin = 15;
111 canvas->translate(margin, margin);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000112
reed40c85e42015-01-05 10:01:25 -0800113 SkPaint paint;
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000114 for (int p = 0; p < fPaths.count(); ++p) {
reed40c85e42015-01-05 10:01:25 -0800115 canvas->save();
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000116 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphaValue); ++a) {
reed40c85e42015-01-05 10:01:25 -0800117 paint.setARGB(kAlphaValue[a], 0, 0, 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000118 for (int aa = 0; aa < 2; ++aa) {
reed40c85e42015-01-05 10:01:25 -0800119 paint.setAntiAlias(SkToBool(aa));
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000120 for (int fh = 0; fh < 2; ++fh) {
Mike Reed19630092020-05-18 21:25:44 -0400121 paint.setStroke(fh != 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000122
123 const SkRect& bounds = fPaths[p].getBounds();
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000124 canvas->save();
125 canvas->translate(-bounds.fLeft, -bounds.fTop);
126 canvas->drawPath(fPaths[p], paint);
127 canvas->restore();
128
reed40c85e42015-01-05 10:01:25 -0800129 canvas->translate(110, 0);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000130 }
131 }
132 }
reed40c85e42015-01-05 10:01:25 -0800133 canvas->restore();
134 canvas->translate(0, 110);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000135 }
136 canvas->restore();
egdaniel5a23a142015-02-25 06:41:47 -0800137
halcanary9d524f22016-03-29 09:03:52 -0700138 this->drawGiantCircle(canvas);
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000139 }
140
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000141private:
142 SkTArray<SkPath> fPaths;
egdaniel5a23a142015-02-25 06:41:47 -0800143 SkPath fGiantCircle;
John Stiles7571f9e2020-09-02 22:42:33 -0400144 using INHERITED = skiagm::GM;
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000145};
halcanary385fe4d2015-08-26 13:07:48 -0700146DEF_GM(return new ConicPathsGM;)
egdaniel@google.comdef9f6e2013-06-20 16:54:31 +0000147
148//////////////////////////////////////////////////////////////////////////////
149
caryclark2b39ffc2016-01-20 07:46:05 -0800150/* arc should be on top of circle */
151DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
152 canvas->translate(50, 100);
153 SkPoint c = { 1052.5390625f, 506.8760978034711f };
154 SkScalar radius = 1096.702150363923f;
155 SkPaint paint;
156 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400157 paint.setStroke(true);
Hal Canary23e474c2017-05-15 13:35:35 -0400158 canvas->drawCircle(c, radius, paint);
Mike Reedcfb130c2020-08-03 11:02:20 -0400159 SkPath path = SkPathBuilder().moveTo(288.88884710654133f, -280.26680862609f)
160 .arcTo({0, 0}, {-39.00216443306411f, 400.6058925796476f}, radius)
161 .detach();
caryclark2b39ffc2016-01-20 07:46:05 -0800162 paint.setColor(0xff007f00);
163 canvas->drawPath(path, paint);
164}
caryclark531191f2016-08-24 11:59:30 -0700165
Jim Van Verth6750e912016-12-19 14:45:19 -0500166/* circle should be antialiased */
167DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
168 canvas->translate(50, 100);
169 SkPoint c = { 1052.5390625f, 506.8760978034711f };
170 SkScalar radius = 1096.702150363923f;
171 SkPaint paint;
172 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400173 paint.setStroke(true);
Hal Canary23e474c2017-05-15 13:35:35 -0400174 canvas->drawCircle(c, radius, paint);
Jim Van Verth6750e912016-12-19 14:45:19 -0500175}
176
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400177/* ovals should not be blurry */
178DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
179 // Test EllipseOp
180 SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
181 SkPaint paint;
182 paint.setAntiAlias(true);
Mike Reed19630092020-05-18 21:25:44 -0400183 paint.setStroke(true);
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400184 paint.setStrokeWidth(100);
185 canvas->drawOval(r, paint);
186 r.offset(-15, -15);
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);
192
193 // Test DIEllipseOp
194 canvas->rotate(1.0f);
195 r.offset(55, 55);
196 paint.setColor(SK_ColorGRAY);
Mike Reed19630092020-05-18 21:25:44 -0400197 paint.setStroke(true);
Jim Van Verth20ae25c2019-03-29 08:50:41 -0400198 paint.setStrokeWidth(100);
199 canvas->drawOval(r, paint);
200 r.offset(-15, -15);
201 paint.setColor(SK_ColorLTGRAY);
202 paint.setStyle(SkPaint::kStrokeAndFill_Style);
203 paint.setStrokeWidth(1);
204 canvas->drawOval(r, paint);
205}
206
caryclark531191f2016-08-24 11:59:30 -0700207DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) {
Mike Reed2243d772020-07-31 21:57:51 -0400208 SkPathBuilder path;
caryclark531191f2016-08-24 11:59:30 -0700209 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
215
216 SkPaint paint;
217 paint.setAntiAlias(true);
218 canvas->translate(125, 125);
Mike Reed2243d772020-07-31 21:57:51 -0400219 canvas->drawPath(path.detach(), paint);
caryclark531191f2016-08-24 11:59:30 -0700220}