blob: 32412b967f15012f468f735cc46816a6f1dfe176 [file] [log] [blame]
bsalomon@google.com82d12232013-09-09 15:36:26 +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 */
Ben Wagner7fde8e12019-05-01 17:28:53 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkPaint.h"
12#include "include/core/SkPoint.h"
13#include "include/core/SkRect.h"
14#include "include/core/SkRefCnt.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkShader.h"
17#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTileMode.h"
20#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "include/effects/SkGradientShader.h"
bsalomon@google.com82d12232013-09-09 15:36:26 +000022
Ben Wagner7fde8e12019-05-01 17:28:53 -040023#include <string.h>
24
bsalomon@google.com82d12232013-09-09 15:36:26 +000025using namespace skiagm;
26
27struct GradData {
28 int fCount;
29 const SkColor* fColors;
30 const SkScalar* fPos;
31};
32
mtkleindbfd7ab2016-09-01 11:24:54 -070033constexpr SkColor gColors[] = {
bsalomon@google.com82d12232013-09-09 15:36:26 +000034 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE,
35};
36
mtkleindbfd7ab2016-09-01 11:24:54 -070037constexpr GradData gGradData[] = {
halcanary96fcdcc2015-08-27 07:41:13 -070038 { 1, gColors, nullptr },
39 { 2, gColors, nullptr },
40 { 3, gColors, nullptr },
41 { 4, gColors, nullptr },
bsalomon@google.com82d12232013-09-09 15:36:26 +000042};
43
Mike Reedfae8fce2019-04-03 10:27:45 -040044static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data, SkTileMode tm) {
reed1a9b9642016-03-13 14:13:58 -070045 return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000046}
47
Mike Reedfae8fce2019-04-03 10:27:45 -040048static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data, SkTileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000049 SkPoint center;
50 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
51 SkScalarAve(pts[0].fY, pts[1].fY));
reed1a9b9642016-03-13 14:13:58 -070052 return SkGradientShader::MakeRadial(center, center.fX, data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000053}
54
Mike Reedfae8fce2019-04-03 10:27:45 -040055static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data, SkTileMode) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000056 SkPoint center;
57 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
58 SkScalarAve(pts[0].fY, pts[1].fY));
reed1a9b9642016-03-13 14:13:58 -070059 return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
bsalomon@google.com82d12232013-09-09 15:36:26 +000060}
61
Mike Reedfae8fce2019-04-03 10:27:45 -040062static sk_sp<SkShader> Make2Radial(const SkPoint pts[2], const GradData& data, SkTileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000063 SkPoint center0, center1;
64 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
65 SkScalarAve(pts[0].fY, pts[1].fY));
66 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
67 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
reed1a9b9642016-03-13 14:13:58 -070068 return SkGradientShader::MakeTwoPointConical(
bsalomon@google.com82d12232013-09-09 15:36:26 +000069 center1, (pts[1].fX - pts[0].fX) / 7,
70 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000071 data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000072}
73
Mike Reedfae8fce2019-04-03 10:27:45 -040074static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data, SkTileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000075 SkPoint center0, center1;
reed80ea19c2015-05-12 10:37:34 -070076 SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
77 SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
bsalomon@google.com82d12232013-09-09 15:36:26 +000078 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
79 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
reed1a9b9642016-03-13 14:13:58 -070080 return SkGradientShader::MakeTwoPointConical(center1, radius1,
bsalomon@google.com82d12232013-09-09 15:36:26 +000081 center0, radius0,
82 data.fColors, data.fPos,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000083 data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000084}
85
86
Mike Reedfae8fce2019-04-03 10:27:45 -040087typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data, SkTileMode tm);
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000088
mtkleindbfd7ab2016-09-01 11:24:54 -070089constexpr GradMaker gGradMakers[] = {
bsalomon@google.com82d12232013-09-09 15:36:26 +000090 MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical,
91};
92
93///////////////////////////////////////////////////////////////////////////////
94
95class GradientsNoTextureGM : public GM {
96public:
fmalita063675b2015-10-12 10:41:48 -070097 GradientsNoTextureGM(bool dither) : fDither(dither) {
Mike Kleind46dce32018-08-16 10:17:03 -040098 this->setBGColor(0xFFDDDDDD);
bsalomon@google.com82d12232013-09-09 15:36:26 +000099 }
100
101protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000102
fmalita063675b2015-10-12 10:41:48 -0700103 SkString onShortName() override {
104 return SkString(fDither ? "gradients_no_texture" : "gradients_no_texture_nodither");
105 }
106
mtklein36352bf2015-03-25 18:17:31 -0700107 SkISize onISize() override { return SkISize::Make(640, 615); }
bsalomon@google.com82d12232013-09-09 15:36:26 +0000108
mtklein36352bf2015-03-25 18:17:31 -0700109 void onDraw(SkCanvas* canvas) override {
mtkleindbfd7ab2016-09-01 11:24:54 -0700110 constexpr SkPoint kPts[2] = { { 0, 0 },
bsalomon@google.com82d12232013-09-09 15:36:26 +0000111 { SkIntToScalar(50), SkIntToScalar(50) } };
Mike Reedfae8fce2019-04-03 10:27:45 -0400112 constexpr SkTileMode kTM = SkTileMode::kClamp;
bsalomon@google.com82d12232013-09-09 15:36:26 +0000113 SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
114 SkPaint paint;
115 paint.setAntiAlias(true);
fmalita063675b2015-10-12 10:41:48 -0700116 paint.setDither(fDither);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000117
118 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
mtkleindbfd7ab2016-09-01 11:24:54 -0700119 constexpr uint8_t kAlphas[] = { 0xff, 0x40 };
bsalomon@google.com82d12232013-09-09 15:36:26 +0000120 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
121 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
122 canvas->save();
123 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
reed1a9b9642016-03-13 14:13:58 -0700124 paint.setShader(gGradMakers[j](kPts, gGradData[i], kTM));
bsalomon@google.com82d12232013-09-09 15:36:26 +0000125 paint.setAlpha(kAlphas[a]);
126 canvas->drawRect(kRect, paint);
127 canvas->translate(0, SkIntToScalar(kRect.height() + 20));
128 }
129 canvas->restore();
130 canvas->translate(SkIntToScalar(kRect.width() + 20), 0);
131 }
132 }
133 }
134
135private:
fmalita063675b2015-10-12 10:41:48 -0700136 bool fDither;
137
bsalomon@google.com82d12232013-09-09 15:36:26 +0000138 typedef GM INHERITED;
139};
140
141///////////////////////////////////////////////////////////////////////////////
142
reed@google.com7b8999b2014-04-18 17:55:37 +0000143struct ColorPos {
144 SkColor* fColors;
145 SkScalar* fPos;
146 int fCount;
147
halcanary96fcdcc2015-08-27 07:41:13 -0700148 ColorPos() : fColors(nullptr), fPos(nullptr), fCount(0) {}
reed@google.com7b8999b2014-04-18 17:55:37 +0000149 ~ColorPos() {
halcanary385fe4d2015-08-26 13:07:48 -0700150 delete[] fColors;
151 delete[] fPos;
reed@google.com7b8999b2014-04-18 17:55:37 +0000152 }
153
154 void construct(const SkColor colors[], const SkScalar pos[], int count) {
halcanary385fe4d2015-08-26 13:07:48 -0700155 fColors = new SkColor[count];
reed@google.com7b8999b2014-04-18 17:55:37 +0000156 memcpy(fColors, colors, count * sizeof(SkColor));
157 if (pos) {
halcanary385fe4d2015-08-26 13:07:48 -0700158 fPos = new SkScalar[count];
reed@google.com7b8999b2014-04-18 17:55:37 +0000159 memcpy(fPos, pos, count * sizeof(SkScalar));
160 fPos[0] = 0;
161 fPos[count - 1] = 1;
162 }
163 fCount = count;
164 }
165};
166
167static void make0(ColorPos* rec) {
168#if 0
169 From http://jsfiddle.net/3fe2a/
170
171background-image: -webkit-linear-gradient(left, #22d1cd 1%, #22d1cd 0.9510157507590116%, #df4b37 2.9510157507590113%, #df4b37 23.695886056604927%, #22d1cd 25.695886056604927%, #22d1cd 25.39321881940624%, #e6de36 27.39321881940624%, #e6de36 31.849399922570655%, #3267ff 33.849399922570655%, #3267ff 44.57735802921938%, #9d47d1 46.57735802921938%, #9d47d1 53.27185850805876%, #3267ff 55.27185850805876%, #3267ff 61.95718972227316%, #5cdd9d 63.95718972227316%, #5cdd9d 69.89166004442%, #3267ff 71.89166004442%, #3267ff 74.45795382765857%, #9d47d1 76.45795382765857%, #9d47d1 82.78364610713776%, #3267ff 84.78364610713776%, #3267ff 94.52743647737229%, #e3d082 96.52743647737229%, #e3d082 96.03934633331295%);
172height: 30px;
173#endif
174
175 const SkColor colors[] = {
176 0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
177 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
178 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
179 };
180 const double percent[] = {
181 1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
182 25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
183 33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
184 55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
185 71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
186 84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
187 };
188 const int N = SK_ARRAY_COUNT(percent);
189 SkScalar pos[N];
190 for (int i = 0; i < N; ++i) {
191 pos[i] = SkDoubleToScalar(percent[i] / 100);
192 }
193 rec->construct(colors, pos, N);
194}
195
196static void make1(ColorPos* rec) {
197 const SkColor colors[] = {
198 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
199 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
200 SK_ColorBLACK,
201 };
halcanary96fcdcc2015-08-27 07:41:13 -0700202 rec->construct(colors, nullptr, SK_ARRAY_COUNT(colors));
reed@google.com7b8999b2014-04-18 17:55:37 +0000203}
204
205static void make2(ColorPos* rec) {
206 const SkColor colors[] = {
207 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
208 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
209 SK_ColorBLACK,
210 };
211 const int N = SK_ARRAY_COUNT(colors);
212 SkScalar pos[N];
213 for (int i = 0; i < N; ++i) {
214 pos[i] = SK_Scalar1 * i / (N - 1);
215 }
216 rec->construct(colors, pos, N);
217}
218
reed6b90df62015-11-13 06:23:54 -0800219static void make3(ColorPos* rec) {
220 const SkColor colors[] = {
221 SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLACK,
222 };
223 const SkScalar pos[] = {
224 0, 0, 0.5f, 0.5, 1, 1,
225 };
226 rec->construct(colors, pos, SK_ARRAY_COUNT(colors));
227}
228
reed@google.com7b8999b2014-04-18 17:55:37 +0000229class GradientsManyColorsGM : public GM {
230 enum {
231 W = 800,
232 };
Hal Canarycefc4312016-11-04 16:26:16 -0400233 sk_sp<SkShader> fShader;
reed@google.com7b8999b2014-04-18 17:55:37 +0000234
235 typedef void (*Proc)(ColorPos*);
236public:
fmalita063675b2015-10-12 10:41:48 -0700237 GradientsManyColorsGM(bool dither) : fDither(dither) {}
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000238
reed@google.com7b8999b2014-04-18 17:55:37 +0000239protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000240
fmalita063675b2015-10-12 10:41:48 -0700241 SkString onShortName() override {
242 return SkString(fDither ? "gradients_many" : "gradients_many_nodither");
243 }
244
reed6b90df62015-11-13 06:23:54 -0800245 SkISize onISize() override { return SkISize::Make(880, 400); }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000246
mtklein36352bf2015-03-25 18:17:31 -0700247 void onDraw(SkCanvas* canvas) override {
reed@google.com7b8999b2014-04-18 17:55:37 +0000248 const Proc procs[] = {
reed6b90df62015-11-13 06:23:54 -0800249 make0, make1, make2, make3,
reed@google.com7b8999b2014-04-18 17:55:37 +0000250 };
251 const SkPoint pts[] = {
252 { 0, 0 },
253 { SkIntToScalar(W), 0 },
254 };
255 const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
256
257 SkPaint paint;
fmalita063675b2015-10-12 10:41:48 -0700258 paint.setDither(fDither);
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000259
reed6b90df62015-11-13 06:23:54 -0800260 canvas->translate(40, 20);
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000261
reed@google.com7b8999b2014-04-18 17:55:37 +0000262 for (int i = 0; i <= 8; ++i) {
263 SkScalar x = r.width() * i / 8;
264 canvas->drawLine(x, 0, x, 10000, paint);
265 }
266
reed6b90df62015-11-13 06:23:54 -0800267 // expand the drawing rect so we exercise clampping in the gradients
268 const SkRect drawR = r.makeOutset(20, 0);
reed@google.com7b8999b2014-04-18 17:55:37 +0000269 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
270 ColorPos rec;
271 procs[i](&rec);
reed1a9b9642016-03-13 14:13:58 -0700272 paint.setShader(SkGradientShader::MakeLinear(pts, rec.fColors, rec.fPos, rec.fCount,
Mike Reedfae8fce2019-04-03 10:27:45 -0400273 SkTileMode::kClamp));
reed6b90df62015-11-13 06:23:54 -0800274 canvas->drawRect(drawR, paint);
275
276 canvas->save();
277 canvas->translate(r.centerX(), r.height() + 4);
278 canvas->scale(-1, 1);
279 canvas->translate(-r.centerX(), 0);
280 canvas->drawRect(drawR, paint);
281 canvas->restore();
282
283 canvas->translate(0, r.height() + 2*r.height() + 8);
reed@google.com7b8999b2014-04-18 17:55:37 +0000284 }
285 }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000286
reed@google.com7b8999b2014-04-18 17:55:37 +0000287private:
fmalita063675b2015-10-12 10:41:48 -0700288 bool fDither;
289
reed@google.com7b8999b2014-04-18 17:55:37 +0000290 typedef GM INHERITED;
291};
292
293///////////////////////////////////////////////////////////////////////////////
294
fmalita063675b2015-10-12 10:41:48 -0700295DEF_GM(return new GradientsNoTextureGM(true);)
296DEF_GM(return new GradientsNoTextureGM(false);)
297DEF_GM(return new GradientsManyColorsGM(true);)
298DEF_GM(return new GradientsManyColorsGM(false);)