blob: 11c27baecae01f7a377a4984c36759d00cff5793 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
reed3d9005c2015-04-23 10:30:27 -07007
reed@android.com42309d42009-06-22 02:06:35 +00008#include "gm.h"
9#include "SkGradientShader.h"
fmalitabc590c02016-02-22 09:12:33 -080010#include "SkLinearGradient.h"
reed@android.com42309d42009-06-22 02:06:35 +000011
12namespace skiagm {
13
14struct GradData {
15 int fCount;
16 const SkColor* fColors;
17 const SkScalar* fPos;
18};
19
20static const SkColor gColors[] = {
21 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
22};
23static const SkScalar gPos0[] = { 0, SK_Scalar1 };
24static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
25static const SkScalar gPos2[] = {
26 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
27};
28
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +000029static const SkScalar gPosClamp[] = {0.0f, 0.0f, 1.0f, 1.0f};
30static const SkColor gColorClamp[] = {
31 SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLUE
32};
33
reed@android.com42309d42009-06-22 02:06:35 +000034static const GradData gGradData[] = {
halcanary96fcdcc2015-08-27 07:41:13 -070035 { 2, gColors, nullptr },
reed@android.com42309d42009-06-22 02:06:35 +000036 { 2, gColors, gPos0 },
37 { 2, gColors, gPos1 },
halcanary96fcdcc2015-08-27 07:41:13 -070038 { 5, gColors, nullptr },
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +000039 { 5, gColors, gPos2 },
40 { 4, gColorClamp, gPosClamp }
reed@android.com42309d42009-06-22 02:06:35 +000041};
42
reed1a9b9642016-03-13 14:13:58 -070043static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data,
44 SkShader::TileMode tm, const SkMatrix& localMatrix) {
45 return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm, 0,
46 &localMatrix);
reed@android.com42309d42009-06-22 02:06:35 +000047}
reed@google.comf3c1cc92010-12-23 16:45:33 +000048
reed1a9b9642016-03-13 14:13:58 -070049static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data,
50 SkShader::TileMode tm, const SkMatrix& localMatrix) {
reed@android.com42309d42009-06-22 02:06:35 +000051 SkPoint center;
52 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
53 SkScalarAve(pts[0].fY, pts[1].fY));
reed1a9b9642016-03-13 14:13:58 -070054 return SkGradientShader::MakeRadial(center, center.fX, data.fColors, data.fPos, data.fCount,
55 tm, 0, &localMatrix);
reed@android.com42309d42009-06-22 02:06:35 +000056}
57
reed1a9b9642016-03-13 14:13:58 -070058static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data,
59 SkShader::TileMode, const SkMatrix& localMatrix) {
reed@android.com42309d42009-06-22 02:06:35 +000060 SkPoint center;
61 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
62 SkScalarAve(pts[0].fY, pts[1].fY));
reed1a9b9642016-03-13 14:13:58 -070063 return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount,
64 0, &localMatrix);
reed@android.com42309d42009-06-22 02:06:35 +000065}
66
reed1a9b9642016-03-13 14:13:58 -070067static sk_sp<SkShader> Make2Radial(const SkPoint pts[2], const GradData& data,
68 SkShader::TileMode tm, const SkMatrix& localMatrix) {
reed@google.comf3c1cc92010-12-23 16:45:33 +000069 SkPoint center0, center1;
70 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
71 SkScalarAve(pts[0].fY, pts[1].fY));
72 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
73 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
reed1a9b9642016-03-13 14:13:58 -070074 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
75 center0, (pts[1].fX - pts[0].fX) / 2,
76 data.fColors, data.fPos, data.fCount, tm,
77 0, &localMatrix);
reed@google.comf3c1cc92010-12-23 16:45:33 +000078}
79
reed1a9b9642016-03-13 14:13:58 -070080static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000081 SkShader::TileMode tm, const SkMatrix& localMatrix) {
rileya@google.com5cf2c282012-07-09 14:42:16 +000082 SkPoint center0, center1;
reed80ea19c2015-05-12 10:37:34 -070083 SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
84 SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
rileya@google.com5cf2c282012-07-09 14:42:16 +000085 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
86 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
reed1a9b9642016-03-13 14:13:58 -070087 return SkGradientShader::MakeTwoPointConical(center1, radius1, center0, radius0,
88 data.fColors, data.fPos,
89 data.fCount, tm, 0, &localMatrix);
rileya@google.com5cf2c282012-07-09 14:42:16 +000090}
91
reed1a9b9642016-03-13 14:13:58 -070092typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data,
93 SkShader::TileMode tm, const SkMatrix& localMatrix);
reed@android.com42309d42009-06-22 02:06:35 +000094static const GradMaker gGradMakers[] = {
rileya@google.com5cf2c282012-07-09 14:42:16 +000095 MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical
reed@android.com42309d42009-06-22 02:06:35 +000096};
97
98///////////////////////////////////////////////////////////////////////////////
99
100class GradientsGM : public GM {
101public:
fmalita063675b2015-10-12 10:41:48 -0700102 GradientsGM(bool dither) : fDither(dither) {
caryclark65cdba62015-06-15 06:51:08 -0700103 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
bsalomon@google.com48dd1a22011-10-31 14:18:20 +0000104 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000105
reed@android.com42309d42009-06-22 02:06:35 +0000106protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000107
reed@android.com42309d42009-06-22 02:06:35 +0000108 SkString onShortName() {
fmalita063675b2015-10-12 10:41:48 -0700109 return SkString(fDither ? "gradients" : "gradients_nodither");
reed@android.com42309d42009-06-22 02:06:35 +0000110 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000111
edisonn@google.com1da3a802013-09-19 17:55:49 +0000112 virtual SkISize onISize() { return SkISize::Make(840, 815); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000113
reed@android.com42309d42009-06-22 02:06:35 +0000114 virtual void onDraw(SkCanvas* canvas) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000115
reed@android.com42309d42009-06-22 02:06:35 +0000116 SkPoint pts[2] = {
117 { 0, 0 },
118 { SkIntToScalar(100), SkIntToScalar(100) }
119 };
120 SkShader::TileMode tm = SkShader::kClamp_TileMode;
121 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
122 SkPaint paint;
123 paint.setAntiAlias(true);
fmalita063675b2015-10-12 10:41:48 -0700124 paint.setDither(fDither);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000125
reed@android.com42309d42009-06-22 02:06:35 +0000126 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
127 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
128 canvas->save();
129 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000130 SkMatrix scale = SkMatrix::I();
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +0000131
132 if (i == 5) { // if the clamp case
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +0000133 scale.setScale(0.5f, 0.5f);
134 scale.postTranslate(25.f, 25.f);
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +0000135 }
skia.committer@gmail.comd55e3572013-08-08 07:01:20 +0000136
reed1a9b9642016-03-13 14:13:58 -0700137 paint.setShader(gGradMakers[j](pts, gGradData[i], tm, scale));
reed@android.com42309d42009-06-22 02:06:35 +0000138 canvas->drawRect(r, paint);
reed@android.com42309d42009-06-22 02:06:35 +0000139 canvas->translate(0, SkIntToScalar(120));
140 }
141 canvas->restore();
142 canvas->translate(SkIntToScalar(120), 0);
143 }
144 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000145
fmalita063675b2015-10-12 10:41:48 -0700146protected:
147 bool fDither;
148
reed@android.com42309d42009-06-22 02:06:35 +0000149private:
150 typedef GM INHERITED;
151};
fmalita063675b2015-10-12 10:41:48 -0700152DEF_GM( return new GradientsGM(true); )
153DEF_GM( return new GradientsGM(false); )
reed@android.com42309d42009-06-22 02:06:35 +0000154
rileya@google.com5cf2c282012-07-09 14:42:16 +0000155// Based on the original gradient slide, but with perspective applied to the
156// gradient shaders' local matrices
157class GradientsLocalPerspectiveGM : public GM {
158public:
fmalita063675b2015-10-12 10:41:48 -0700159 GradientsLocalPerspectiveGM(bool dither) : fDither(dither) {
caryclark65cdba62015-06-15 06:51:08 -0700160 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
rileya@google.com5cf2c282012-07-09 14:42:16 +0000161 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162
rileya@google.com5cf2c282012-07-09 14:42:16 +0000163protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000164
rileya@google.com5cf2c282012-07-09 14:42:16 +0000165 SkString onShortName() {
fmalita063675b2015-10-12 10:41:48 -0700166 return SkString(fDither ? "gradients_local_perspective" :
167 "gradients_local_perspective_nodither");
rileya@google.com5cf2c282012-07-09 14:42:16 +0000168 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000169
edisonn@google.com1da3a802013-09-19 17:55:49 +0000170 virtual SkISize onISize() { return SkISize::Make(840, 815); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171
rileya@google.com5cf2c282012-07-09 14:42:16 +0000172 virtual void onDraw(SkCanvas* canvas) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173
rileya@google.com5cf2c282012-07-09 14:42:16 +0000174 SkPoint pts[2] = {
175 { 0, 0 },
176 { SkIntToScalar(100), SkIntToScalar(100) }
177 };
178 SkShader::TileMode tm = SkShader::kClamp_TileMode;
179 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
180 SkPaint paint;
181 paint.setAntiAlias(true);
fmalita063675b2015-10-12 10:41:48 -0700182 paint.setDither(fDither);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000183
rileya@google.com5cf2c282012-07-09 14:42:16 +0000184 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
185 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
186 canvas->save();
187 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
rileya@google.com5cf2c282012-07-09 14:42:16 +0000188 // apply an increasing y perspective as we move to the right
189 SkMatrix perspective;
190 perspective.setIdentity();
reed80ea19c2015-05-12 10:37:34 -0700191 perspective.setPerspY(SkIntToScalar(i+1) / 500);
192 perspective.setSkewX(SkIntToScalar(i+1) / 10);
commit-bot@chromium.org8ba1ad32013-08-07 15:22:13 +0000193
reed1a9b9642016-03-13 14:13:58 -0700194 paint.setShader(gGradMakers[j](pts, gGradData[i], tm, perspective));
rileya@google.com5cf2c282012-07-09 14:42:16 +0000195 canvas->drawRect(r, paint);
rileya@google.com5cf2c282012-07-09 14:42:16 +0000196 canvas->translate(0, SkIntToScalar(120));
197 }
198 canvas->restore();
199 canvas->translate(SkIntToScalar(120), 0);
200 }
201 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000202
rileya@google.com5cf2c282012-07-09 14:42:16 +0000203private:
fmalita063675b2015-10-12 10:41:48 -0700204 bool fDither;
205
rileya@google.com5cf2c282012-07-09 14:42:16 +0000206 typedef GM INHERITED;
207};
fmalita063675b2015-10-12 10:41:48 -0700208DEF_GM( return new GradientsLocalPerspectiveGM(true); )
209DEF_GM( return new GradientsLocalPerspectiveGM(false); )
rileya@google.com5cf2c282012-07-09 14:42:16 +0000210
211// Based on the original gradient slide, but with perspective applied to
212// the view matrix
213class GradientsViewPerspectiveGM : public GradientsGM {
fmalita063675b2015-10-12 10:41:48 -0700214public:
215 GradientsViewPerspectiveGM(bool dither) : INHERITED(dither) { }
216
rileya@google.com5cf2c282012-07-09 14:42:16 +0000217protected:
218 SkString onShortName() {
fmalita063675b2015-10-12 10:41:48 -0700219 return SkString(fDither ? "gradients_view_perspective" :
220 "gradients_view_perspective_nodither");
rileya@google.com5cf2c282012-07-09 14:42:16 +0000221 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000222
edisonn@google.com1da3a802013-09-19 17:55:49 +0000223 virtual SkISize onISize() { return SkISize::Make(840, 500); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000224
rileya@google.com5cf2c282012-07-09 14:42:16 +0000225 virtual void onDraw(SkCanvas* canvas) {
226 SkMatrix perspective;
227 perspective.setIdentity();
reed80ea19c2015-05-12 10:37:34 -0700228 perspective.setPerspY(0.001f);
229 perspective.setSkewX(SkIntToScalar(8) / 25);
scroggo@google.com837d31a2012-08-15 18:42:45 +0000230 canvas->concat(perspective);
rileya@google.com5cf2c282012-07-09 14:42:16 +0000231 INHERITED::onDraw(canvas);
232 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000233
rileya@google.com5cf2c282012-07-09 14:42:16 +0000234private:
235 typedef GradientsGM INHERITED;
236};
fmalita063675b2015-10-12 10:41:48 -0700237DEF_GM( return new GradientsViewPerspectiveGM(true); )
238DEF_GM( return new GradientsViewPerspectiveGM(false); )
rileya@google.com5cf2c282012-07-09 14:42:16 +0000239
reed@google.comac864a92011-06-27 18:11:17 +0000240/*
241 Inspired by this <canvas> javascript, where we need to detect that we are not
242 solving a quadratic equation, but must instead solve a linear (since our X^2
243 coefficient is 0)
244
245 ctx.fillStyle = '#f00';
246 ctx.fillRect(0, 0, 100, 50);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000247
reed@google.comac864a92011-06-27 18:11:17 +0000248 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
249 g.addColorStop(0, '#f00');
250 g.addColorStop(0.01, '#0f0');
251 g.addColorStop(0.99, '#0f0');
252 g.addColorStop(1, '#f00');
253 ctx.fillStyle = g;
254 ctx.fillRect(0, 0, 100, 50);
255 */
256class GradientsDegenrate2PointGM : public GM {
257public:
fmalita063675b2015-10-12 10:41:48 -0700258 GradientsDegenrate2PointGM(bool dither) : fDither(dither) {}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000259
reed@google.comac864a92011-06-27 18:11:17 +0000260protected:
261 SkString onShortName() {
fmalita063675b2015-10-12 10:41:48 -0700262 return SkString(fDither ? "gradients_degenerate_2pt" : "gradients_degenerate_2pt_nodither");
reed@google.comac864a92011-06-27 18:11:17 +0000263 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000264
edisonn@google.com1da3a802013-09-19 17:55:49 +0000265 virtual SkISize onISize() { return SkISize::Make(320, 320); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000266
reed@google.comac864a92011-06-27 18:11:17 +0000267 void drawBG(SkCanvas* canvas) {
268 canvas->drawColor(SK_ColorBLUE);
269 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000270
reed@google.comac864a92011-06-27 18:11:17 +0000271 virtual void onDraw(SkCanvas* canvas) {
272 this->drawBG(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000273
reed@google.comac864a92011-06-27 18:11:17 +0000274 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000275 SkScalar pos[] = { 0, 0.01f, 0.99f, SK_Scalar1 };
epoger@google.com59f3abf2011-07-21 15:50:33 +0000276 SkPoint c0;
277 c0.iset(-80, 25);
278 SkScalar r0 = SkIntToScalar(70);
279 SkPoint c1;
280 c1.iset(0, 25);
281 SkScalar r1 = SkIntToScalar(150);
reed9283d202016-03-13 13:01:57 -0700282 SkPaint paint;
reed1a9b9642016-03-13 14:13:58 -0700283 paint.setShader(SkGradientShader::MakeTwoPointConical(c0, r0, c1, r1, colors,
284 pos, SK_ARRAY_COUNT(pos),
285 SkShader::kClamp_TileMode));
fmalita063675b2015-10-12 10:41:48 -0700286 paint.setDither(fDither);
reed@google.comac864a92011-06-27 18:11:17 +0000287 canvas->drawPaint(paint);
288 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000289
reed@google.comac864a92011-06-27 18:11:17 +0000290private:
fmalita063675b2015-10-12 10:41:48 -0700291 bool fDither;
292
reed@google.comac864a92011-06-27 18:11:17 +0000293 typedef GM INHERITED;
294};
fmalita063675b2015-10-12 10:41:48 -0700295DEF_GM( return new GradientsDegenrate2PointGM(true); )
296DEF_GM( return new GradientsDegenrate2PointGM(false); )
reed@google.comac864a92011-06-27 18:11:17 +0000297
caryclarkcb100712016-02-26 05:59:40 -0800298/* bug.skia.org/517
299<canvas id="canvas"></canvas>
300<script>
301var c = document.getElementById("canvas");
302var ctx = c.getContext("2d");
303ctx.fillStyle = '#ff0';
304ctx.fillRect(0, 0, 100, 50);
305
306var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
307g.addColorStop(0, '#0f0');
308g.addColorStop(0.003, '#f00'); // 0.004 makes this work
309g.addColorStop(1, '#ff0');
310ctx.fillStyle = g;
311ctx.fillRect(0, 0, 100, 50);
312</script>
313*/
314
315// should draw only green
316DEF_SIMPLE_GM(small_color_stop, canvas, 100, 150) {
317 SkColor colors[] = { SK_ColorGREEN, SK_ColorRED, SK_ColorYELLOW };
318 SkScalar pos[] = { 0, 0.003f, SK_Scalar1 }; // 0.004f makes this work
319 SkPoint c0 = { 200, 25 };
320 SkScalar r0 = 20;
321 SkPoint c1 = { 200, 25 };
322 SkScalar r1 = 10;
reed1a9b9642016-03-13 14:13:58 -0700323
caryclarkcb100712016-02-26 05:59:40 -0800324 SkPaint paint;
325 paint.setColor(SK_ColorYELLOW);
326 canvas->drawRect(SkRect::MakeWH(100, 150), paint);
reed1a9b9642016-03-13 14:13:58 -0700327 paint.setShader(SkGradientShader::MakeTwoPointConical(c0, r0, c1, r1, colors, pos,
328 SK_ARRAY_COUNT(pos),
329 SkShader::kClamp_TileMode));
caryclarkcb100712016-02-26 05:59:40 -0800330 canvas->drawRect(SkRect::MakeWH(100, 150), paint);
331}
332
333
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000334/// Tests correctness of *optimized* codepaths in gradients.
335
336class ClampedGradientsGM : public GM {
337public:
fmalita063675b2015-10-12 10:41:48 -0700338 ClampedGradientsGM(bool dither) : fDither(dither) {}
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000339
340protected:
fmalita063675b2015-10-12 10:41:48 -0700341 SkString onShortName() {
342 return SkString(fDither ? "clamped_gradients" : "clamped_gradients_nodither");
343 }
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000344
edisonn@google.com1da3a802013-09-19 17:55:49 +0000345 virtual SkISize onISize() { return SkISize::Make(640, 510); }
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000346
347 void drawBG(SkCanvas* canvas) {
caryclark12596012015-07-29 05:27:47 -0700348 canvas->drawColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000349 }
350
351 virtual void onDraw(SkCanvas* canvas) {
352 this->drawBG(canvas);
353
354 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
355 SkPaint paint;
fmalita063675b2015-10-12 10:41:48 -0700356 paint.setDither(fDither);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000357 paint.setAntiAlias(true);
358
359 SkPoint center;
360 center.iset(0, 300);
361 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
reed1a9b9642016-03-13 14:13:58 -0700362 paint.setShader(SkGradientShader::MakeRadial(
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000363 SkPoint(center),
halcanary96fcdcc2015-08-27 07:41:13 -0700364 SkIntToScalar(200), gColors, nullptr, 5,
reed1a9b9642016-03-13 14:13:58 -0700365 SkShader::kClamp_TileMode));
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000366 canvas->drawRect(r, paint);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000367 }
368
369private:
fmalita063675b2015-10-12 10:41:48 -0700370 bool fDither;
371
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000372 typedef GM INHERITED;
373};
fmalita063675b2015-10-12 10:41:48 -0700374DEF_GM( return new ClampedGradientsGM(true); )
375DEF_GM( return new ClampedGradientsGM(false); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000376
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000377/// Checks quality of large radial gradients, which may display
378/// some banding.
379
380class RadialGradientGM : public GM {
381public:
382 RadialGradientGM() {}
383
384protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000385
mtklein36352bf2015-03-25 18:17:31 -0700386 SkString onShortName() override { return SkString("radial_gradient"); }
387 SkISize onISize() override { return SkISize::Make(1280, 1280); }
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000388 void drawBG(SkCanvas* canvas) {
389 canvas->drawColor(0xFF000000);
390 }
mtklein36352bf2015-03-25 18:17:31 -0700391 void onDraw(SkCanvas* canvas) override {
reed@google.combb0948f2012-01-31 14:44:13 +0000392 const SkISize dim = this->getISize();
393
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000394 this->drawBG(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000395
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000396 SkPaint paint;
397 paint.setDither(true);
398 SkPoint center;
reed@google.combb0948f2012-01-31 14:44:13 +0000399 center.set(SkIntToScalar(dim.width())/2, SkIntToScalar(dim.height())/2);
400 SkScalar radius = SkIntToScalar(dim.width())/2;
401 const SkColor colors[] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000402 const SkScalar pos[] = { 0.0f,
403 0.35f,
404 1.0f };
reed1a9b9642016-03-13 14:13:58 -0700405 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, pos,
406 SK_ARRAY_COUNT(pos),
407 SkShader::kClamp_TileMode));
reed@google.combb0948f2012-01-31 14:44:13 +0000408 SkRect r = {
409 0, 0, SkIntToScalar(dim.width()), SkIntToScalar(dim.height())
410 };
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000411 canvas->drawRect(r, paint);
412 }
413private:
414 typedef GM INHERITED;
415};
reed3d9005c2015-04-23 10:30:27 -0700416DEF_GM( return new RadialGradientGM; )
tomhudson@google.comb18e58c2012-01-30 20:00:13 +0000417
mtklein@google.com361a72f2013-08-19 18:43:34 +0000418class RadialGradient2GM : public GM {
419public:
fmalita063675b2015-10-12 10:41:48 -0700420 RadialGradient2GM(bool dither) : fDither(dither) {}
mtklein@google.com361a72f2013-08-19 18:43:34 +0000421
422protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000423
fmalita063675b2015-10-12 10:41:48 -0700424 SkString onShortName() override {
425 return SkString(fDither ? "radial_gradient2" : "radial_gradient2_nodither");
426 }
427
mtklein36352bf2015-03-25 18:17:31 -0700428 SkISize onISize() override { return SkISize::Make(800, 400); }
mtklein@google.com361a72f2013-08-19 18:43:34 +0000429 void drawBG(SkCanvas* canvas) {
430 canvas->drawColor(0xFF000000);
431 }
432
433 // Reproduces the example given in bug 7671058.
mtklein36352bf2015-03-25 18:17:31 -0700434 void onDraw(SkCanvas* canvas) override {
mtklein@google.com361a72f2013-08-19 18:43:34 +0000435 SkPaint paint1, paint2, paint3;
436 paint1.setStyle(SkPaint::kFill_Style);
437 paint2.setStyle(SkPaint::kFill_Style);
438 paint3.setStyle(SkPaint::kFill_Style);
439
440 const SkColor sweep_colors[] =
441 { 0xFFFF0000, 0xFFFFFF00, 0xFF00FF00, 0xFF00FFFF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF0000 };
442 const SkColor colors1[] = { 0xFFFFFFFF, 0x00000000 };
443 const SkColor colors2[] = { 0xFF000000, 0x00000000 };
444
445 const SkScalar cx = 200, cy = 200, radius = 150;
446 SkPoint center;
447 center.set(cx, cy);
448
mtklein@google.com3ef7eea2013-09-16 13:02:52 +0000449 // We can either interpolate endpoints and premultiply each point (default, more precision),
450 // or premultiply the endpoints first, avoiding the need to premultiply each point (cheap).
451 const uint32_t flags[] = { 0, SkGradientShader::kInterpolateColorsInPremul_Flag };
mtklein@google.com361a72f2013-08-19 18:43:34 +0000452
mtklein@google.com3ef7eea2013-09-16 13:02:52 +0000453 for (size_t i = 0; i < SK_ARRAY_COUNT(flags); i++) {
reed1a9b9642016-03-13 14:13:58 -0700454 paint1.setShader(SkGradientShader::MakeSweep(cx, cy, sweep_colors,
455 nullptr, SK_ARRAY_COUNT(sweep_colors),
456 flags[i], nullptr));
457 paint2.setShader(SkGradientShader::MakeRadial(center, radius, colors1,
458 nullptr, SK_ARRAY_COUNT(colors1),
459 SkShader::kClamp_TileMode,
460 flags[i], nullptr));
461 paint3.setShader(SkGradientShader::MakeRadial(center, radius, colors2,
462 nullptr, SK_ARRAY_COUNT(colors2),
463 SkShader::kClamp_TileMode,
464 flags[i], nullptr));
fmalita063675b2015-10-12 10:41:48 -0700465 paint1.setDither(fDither);
fmalita063675b2015-10-12 10:41:48 -0700466 paint2.setDither(fDither);
fmalita063675b2015-10-12 10:41:48 -0700467 paint3.setDither(fDither);
mtklein@google.com3ef7eea2013-09-16 13:02:52 +0000468
469 canvas->drawCircle(cx, cy, radius, paint1);
470 canvas->drawCircle(cx, cy, radius, paint3);
471 canvas->drawCircle(cx, cy, radius, paint2);
472
473 canvas->translate(400, 0);
474 }
mtklein@google.com361a72f2013-08-19 18:43:34 +0000475 }
476
477private:
fmalita063675b2015-10-12 10:41:48 -0700478 bool fDither;
479
mtklein@google.com361a72f2013-08-19 18:43:34 +0000480 typedef GM INHERITED;
481};
fmalita063675b2015-10-12 10:41:48 -0700482DEF_GM( return new RadialGradient2GM(true); )
483DEF_GM( return new RadialGradient2GM(false); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000484
reed3d9005c2015-04-23 10:30:27 -0700485// Shallow radial (shows banding on raster)
486class RadialGradient3GM : public GM {
fmalita063675b2015-10-12 10:41:48 -0700487public:
488 RadialGradient3GM(bool dither) : fDither(dither) { }
reed@android.com42309d42009-06-22 02:06:35 +0000489
reed3d9005c2015-04-23 10:30:27 -0700490protected:
fmalita063675b2015-10-12 10:41:48 -0700491 SkString onShortName() override {
492 return SkString(fDither ? "radial_gradient3" : "radial_gradient3_nodither");
493 }
reed@android.com42309d42009-06-22 02:06:35 +0000494
reed3d9005c2015-04-23 10:30:27 -0700495 SkISize onISize() override { return SkISize::Make(500, 500); }
reed@google.comac864a92011-06-27 18:11:17 +0000496
reed3d9005c2015-04-23 10:30:27 -0700497 bool runAsBench() const override { return true; }
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000498
reed3d9005c2015-04-23 10:30:27 -0700499 void onOnceBeforeDraw() override {
500 const SkPoint center = { 0, 0 };
501 const SkScalar kRadius = 3000;
502 const SkColor gColors[] = { 0xFFFFFFFF, 0xFF000000 };
reed1a9b9642016-03-13 14:13:58 -0700503 fShader = SkGradientShader::MakeRadial(center, kRadius, gColors, nullptr, 2,
504 SkShader::kClamp_TileMode);
reed3d9005c2015-04-23 10:30:27 -0700505 }
rileya@google.com5cf2c282012-07-09 14:42:16 +0000506
reed3d9005c2015-04-23 10:30:27 -0700507 void onDraw(SkCanvas* canvas) override {
508 SkPaint paint;
509 paint.setShader(fShader);
fmalita063675b2015-10-12 10:41:48 -0700510 paint.setDither(fDither);
reed3d9005c2015-04-23 10:30:27 -0700511 canvas->drawRect(SkRect::MakeWH(500, 500), paint);
512 }
halcanary9d524f22016-03-29 09:03:52 -0700513
reed3d9005c2015-04-23 10:30:27 -0700514private:
reed1a9b9642016-03-13 14:13:58 -0700515 sk_sp<SkShader> fShader;
fmalita063675b2015-10-12 10:41:48 -0700516 bool fDither;
517
reed3d9005c2015-04-23 10:30:27 -0700518 typedef GM INHERITED;
519};
fmalita063675b2015-10-12 10:41:48 -0700520DEF_GM( return new RadialGradient3GM(true); )
521DEF_GM( return new RadialGradient3GM(false); )
rileya@google.com5cf2c282012-07-09 14:42:16 +0000522
caryclark1864bfa2015-07-30 06:41:39 -0700523class RadialGradient4GM : public GM {
fmalita063675b2015-10-12 10:41:48 -0700524public:
525 RadialGradient4GM(bool dither) : fDither(dither) { }
caryclark1864bfa2015-07-30 06:41:39 -0700526
527protected:
fmalita063675b2015-10-12 10:41:48 -0700528 SkString onShortName() override {
529 return SkString(fDither ? "radial_gradient4" : "radial_gradient4_nodither");
530 }
caryclark1864bfa2015-07-30 06:41:39 -0700531
532 SkISize onISize() override { return SkISize::Make(500, 500); }
533
534 void onOnceBeforeDraw() override {
535 const SkPoint center = { 250, 250 };
536 const SkScalar kRadius = 250;
537 const SkColor colors[] = { SK_ColorRED, SK_ColorRED, SK_ColorWHITE, SK_ColorWHITE,
538 SK_ColorRED };
539 const SkScalar pos[] = { 0, .4f, .4f, .8f, .8f, 1 };
reed1a9b9642016-03-13 14:13:58 -0700540 fShader = SkGradientShader::MakeRadial(center, kRadius, colors, pos,
541 SK_ARRAY_COUNT(gColors), SkShader::kClamp_TileMode);
caryclark1864bfa2015-07-30 06:41:39 -0700542 }
543
544 void onDraw(SkCanvas* canvas) override {
545 SkPaint paint;
546 paint.setAntiAlias(true);
fmalita063675b2015-10-12 10:41:48 -0700547 paint.setDither(fDither);
caryclark1864bfa2015-07-30 06:41:39 -0700548 paint.setShader(fShader);
549 canvas->drawRect(SkRect::MakeWH(500, 500), paint);
550 }
halcanary9d524f22016-03-29 09:03:52 -0700551
caryclark1864bfa2015-07-30 06:41:39 -0700552private:
reed1a9b9642016-03-13 14:13:58 -0700553 sk_sp<SkShader> fShader;
fmalita063675b2015-10-12 10:41:48 -0700554 bool fDither;
555
caryclark1864bfa2015-07-30 06:41:39 -0700556 typedef GM INHERITED;
557};
fmalita063675b2015-10-12 10:41:48 -0700558DEF_GM( return new RadialGradient4GM(true); )
559DEF_GM( return new RadialGradient4GM(false); )
caryclark1864bfa2015-07-30 06:41:39 -0700560
caryclark159fa572015-07-30 12:35:48 -0700561class LinearGradientGM : public GM {
fmalita063675b2015-10-12 10:41:48 -0700562public:
563 LinearGradientGM(bool dither) : fDither(dither) { }
caryclark159fa572015-07-30 12:35:48 -0700564
565protected:
fmalita063675b2015-10-12 10:41:48 -0700566 SkString onShortName() override {
567 return SkString(fDither ? "linear_gradient" : "linear_gradient_nodither");
568 }
569
caryclark159fa572015-07-30 12:35:48 -0700570 const SkScalar kWidthBump = 30.f;
571 const SkScalar kHeight = 5.f;
572 const SkScalar kMinWidth = 540.f;
573
574 SkISize onISize() override { return SkISize::Make(500, 500); }
575
576 void onOnceBeforeDraw() override {
577 SkPoint pts[2] = { {0, 0}, {0, 0} };
578 const SkColor colors[] = { SK_ColorWHITE, SK_ColorWHITE, 0xFF008200, 0xFF008200,
579 SK_ColorWHITE, SK_ColorWHITE };
580 const SkScalar unitPos[] = { 0, 50, 70, 500, 540 };
581 SkScalar pos[6];
582 pos[5] = 1;
583 for (int index = 0; index < (int) SK_ARRAY_COUNT(fShader); ++index) {
584 pts[1].fX = 500.f + index * kWidthBump;
585 for (int inner = 0; inner < (int) SK_ARRAY_COUNT(unitPos); ++inner) {
586 pos[inner] = unitPos[inner] / (kMinWidth + index * kWidthBump);
587 }
reed1a9b9642016-03-13 14:13:58 -0700588 fShader[index] = SkGradientShader::MakeLinear(pts, colors, pos,
589 SK_ARRAY_COUNT(gColors), SkShader::kClamp_TileMode);
caryclark159fa572015-07-30 12:35:48 -0700590 }
591 }
592
593 void onDraw(SkCanvas* canvas) override {
594 SkPaint paint;
595 paint.setAntiAlias(true);
fmalita063675b2015-10-12 10:41:48 -0700596 paint.setDither(fDither);
caryclark159fa572015-07-30 12:35:48 -0700597 for (int index = 0; index < (int) SK_ARRAY_COUNT(fShader); ++index) {
598 paint.setShader(fShader[index]);
599 canvas->drawRect(SkRect::MakeLTRB(0, index * kHeight, kMinWidth + index * kWidthBump,
600 (index + 1) * kHeight), paint);
601 }
602 }
halcanary9d524f22016-03-29 09:03:52 -0700603
caryclark159fa572015-07-30 12:35:48 -0700604private:
reed1a9b9642016-03-13 14:13:58 -0700605 sk_sp<SkShader> fShader[100];
fmalita063675b2015-10-12 10:41:48 -0700606 bool fDither;
607
caryclark159fa572015-07-30 12:35:48 -0700608 typedef GM INHERITED;
609};
fmalita063675b2015-10-12 10:41:48 -0700610DEF_GM( return new LinearGradientGM(true); )
611DEF_GM( return new LinearGradientGM(false); )
caryclark159fa572015-07-30 12:35:48 -0700612
fmalita8b78bd62015-11-20 13:58:24 -0800613class LinearGradientTinyGM : public GM {
fmalitabc590c02016-02-22 09:12:33 -0800614public:
615 LinearGradientTinyGM(uint32_t flags, const char* suffix = nullptr)
616 : fName("linear_gradient_tiny")
617 , fFlags(flags) {
618 fName.append(suffix);
619 }
620
fmalita8b78bd62015-11-20 13:58:24 -0800621protected:
622 SkString onShortName() override {
fmalitabc590c02016-02-22 09:12:33 -0800623 return fName;
fmalita8b78bd62015-11-20 13:58:24 -0800624 }
625
626 SkISize onISize() override {
627 return SkISize::Make(600, 500);
628 }
629
630 void onDraw(SkCanvas* canvas) override {
631 const SkScalar kRectSize = 100;
632 const unsigned kStopCount = 3;
633 const SkColor colors[kStopCount] = { SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN };
634 const struct {
635 SkPoint pts[2];
636 SkScalar pos[kStopCount];
637 } configs[] = {
reedde3aac82015-11-22 13:00:04 -0800638 { { SkPoint::Make(0, 0), SkPoint::Make(10, 0) }, { 0, 0.999999f, 1 }},
639 { { SkPoint::Make(0, 0), SkPoint::Make(10, 0) }, { 0, 0.000001f, 1 }},
640 { { SkPoint::Make(0, 0), SkPoint::Make(10, 0) }, { 0, 0.999999999f, 1 }},
641 { { SkPoint::Make(0, 0), SkPoint::Make(10, 0) }, { 0, 0.000000001f, 1 }},
fmalita8b78bd62015-11-20 13:58:24 -0800642
reedde3aac82015-11-22 13:00:04 -0800643 { { SkPoint::Make(0, 0), SkPoint::Make(0, 10) }, { 0, 0.999999f, 1 }},
644 { { SkPoint::Make(0, 0), SkPoint::Make(0, 10) }, { 0, 0.000001f, 1 }},
645 { { SkPoint::Make(0, 0), SkPoint::Make(0, 10) }, { 0, 0.999999999f, 1 }},
646 { { SkPoint::Make(0, 0), SkPoint::Make(0, 10) }, { 0, 0.000000001f, 1 }},
647
648 { { SkPoint::Make(0, 0), SkPoint::Make(0.00001f, 0) }, { 0, 0.5f, 1 }},
649 { { SkPoint::Make(9.99999f, 0), SkPoint::Make(10, 0) }, { 0, 0.5f, 1 }},
650 { { SkPoint::Make(0, 0), SkPoint::Make(0, 0.00001f) }, { 0, 0.5f, 1 }},
651 { { SkPoint::Make(0, 9.99999f), SkPoint::Make(0, 10) }, { 0, 0.5f, 1 }},
fmalita8b78bd62015-11-20 13:58:24 -0800652 };
653
654 SkPaint paint;
655 for (unsigned i = 0; i < SK_ARRAY_COUNT(configs); ++i) {
656 SkAutoCanvasRestore acr(canvas, true);
reed1a9b9642016-03-13 14:13:58 -0700657 paint.setShader(SkGradientShader::MakeLinear(configs[i].pts, colors, configs[i].pos,
658 kStopCount, SkShader::kClamp_TileMode,
659 fFlags, nullptr));
fmalita8b78bd62015-11-20 13:58:24 -0800660 canvas->translate(kRectSize * ((i % 4) * 1.5f + 0.25f),
661 kRectSize * ((i / 4) * 1.5f + 0.25f));
662
fmalita8b78bd62015-11-20 13:58:24 -0800663 canvas->drawRect(SkRect::MakeWH(kRectSize, kRectSize), paint);
664 }
665 }
666
667private:
668 typedef GM INHERITED;
fmalita8b78bd62015-11-20 13:58:24 -0800669
fmalitabc590c02016-02-22 09:12:33 -0800670 SkString fName;
671 uint32_t fFlags;
672};
673DEF_GM( return new LinearGradientTinyGM(0); )
674DEF_GM( return new LinearGradientTinyGM(SkLinearGradient::kForce4fContext_PrivateFlag, "_4f"); )
reed@android.com42309d42009-06-22 02:06:35 +0000675}
reedd4eaa252016-01-22 10:35:26 -0800676
677///////////////////////////////////////////////////////////////////////////////////////////////////
678
679struct GradRun {
680 SkColor fColors[4];
681 SkScalar fPos[4];
682 int fCount;
683};
684
685#define SIZE 121
686
reed1a9b9642016-03-13 14:13:58 -0700687static sk_sp<SkShader> make_linear(const GradRun& run, SkShader::TileMode mode) {
reedd4eaa252016-01-22 10:35:26 -0800688 const SkPoint pts[] { { 30, 30 }, { SIZE - 30, SIZE - 30 } };
reed1a9b9642016-03-13 14:13:58 -0700689 return SkGradientShader::MakeLinear(pts, run.fColors, run.fPos, run.fCount, mode);
reedd4eaa252016-01-22 10:35:26 -0800690}
691
reed1a9b9642016-03-13 14:13:58 -0700692static sk_sp<SkShader> make_radial(const GradRun& run, SkShader::TileMode mode) {
reedd4eaa252016-01-22 10:35:26 -0800693 const SkScalar half = SIZE * 0.5f;
reed1a9b9642016-03-13 14:13:58 -0700694 return SkGradientShader::MakeRadial({half,half}, half - 10, run.fColors, run.fPos,
695 run.fCount, mode);
reedd4eaa252016-01-22 10:35:26 -0800696}
697
reed1a9b9642016-03-13 14:13:58 -0700698static sk_sp<SkShader> make_conical(const GradRun& run, SkShader::TileMode mode) {
reedd4eaa252016-01-22 10:35:26 -0800699 const SkScalar half = SIZE * 0.5f;
700 const SkPoint center { half, half };
reed1a9b9642016-03-13 14:13:58 -0700701 return SkGradientShader::MakeTwoPointConical(center, 20, center, half - 10,
702 run.fColors, run.fPos, run.fCount, mode);
reedd4eaa252016-01-22 10:35:26 -0800703}
704
reed1a9b9642016-03-13 14:13:58 -0700705static sk_sp<SkShader> make_sweep(const GradRun& run, SkShader::TileMode) {
reedd4eaa252016-01-22 10:35:26 -0800706 const SkScalar half = SIZE * 0.5f;
reed1a9b9642016-03-13 14:13:58 -0700707 return SkGradientShader::MakeSweep(half, half, run.fColors, run.fPos, run.fCount);
reedd4eaa252016-01-22 10:35:26 -0800708}
709
710/*
711 * Exercise duplicate color-stops, at the ends, and in the middle
712 *
713 * At the time of this writing, only Linear correctly deals with duplicates at the ends,
714 * and then only correctly on CPU backend.
715 */
716DEF_SIMPLE_GM(gradients_dup_color_stops, canvas, 704, 564) {
717 const SkColor preColor = 0xFFFF0000; // clamp color before start
718 const SkColor postColor = 0xFF0000FF; // clamp color after end
719 const SkColor color0 = 0xFF000000;
720 const SkColor color1 = 0xFF00FF00;
721 const SkColor badColor = 0xFF3388BB; // should never be seen, fills out fixed-size array
722
723 const GradRun runs[] = {
724 { { color0, color1, badColor, badColor },
725 { 0, 1, -1, -1 },
726 2,
727 },
728 { { preColor, color0, color1, badColor },
729 { 0, 0, 1, -1 },
730 3,
731 },
732 { { color0, color1, postColor, badColor },
733 { 0, 1, 1, -1 },
734 3,
735 },
736 { { preColor, color0, color1, postColor },
737 { 0, 0, 1, 1 },
738 4,
739 },
740 { { color0, color0, color1, color1 },
741 { 0, 0.5f, 0.5f, 1 },
742 4,
743 },
744 };
reed1a9b9642016-03-13 14:13:58 -0700745 sk_sp<SkShader> (*factories[])(const GradRun&, SkShader::TileMode) {
reedd4eaa252016-01-22 10:35:26 -0800746 make_linear, make_radial, make_conical, make_sweep
747 };
748
749 const SkRect rect = SkRect::MakeWH(SIZE, SIZE);
750 const SkScalar dx = SIZE + 20;
751 const SkScalar dy = SIZE + 20;
752 const SkShader::TileMode mode = SkShader::kClamp_TileMode;
753
754 SkPaint paint;
755 canvas->translate(10, 10 - dy);
756 for (auto factory : factories) {
757 canvas->translate(0, dy);
758 SkAutoCanvasRestore acr(canvas, true);
759 for (const auto& run : runs) {
reed1a9b9642016-03-13 14:13:58 -0700760 paint.setShader(factory(run, mode));
reedd4eaa252016-01-22 10:35:26 -0800761 canvas->drawRect(rect, paint);
762 canvas->translate(dx, 0);
763 }
764 }
765}
fmalitabc590c02016-02-22 09:12:33 -0800766
767static void draw_many_stops(SkCanvas* canvas, uint32_t flags) {
768 const unsigned kStopCount = 200;
769 const SkPoint pts[] = { {50, 50}, {450, 465}};
770
771 SkColor colors[kStopCount];
772 for (unsigned i = 0; i < kStopCount; i++) {
773 switch (i % 5) {
774 case 0: colors[i] = SK_ColorRED; break;
775 case 1: colors[i] = SK_ColorGREEN; break;
776 case 2: colors[i] = SK_ColorGREEN; break;
777 case 3: colors[i] = SK_ColorBLUE; break;
778 case 4: colors[i] = SK_ColorRED; break;
779 }
780 }
781
reed9283d202016-03-13 13:01:57 -0700782 SkPaint p;
reed1a9b9642016-03-13 14:13:58 -0700783 p.setShader(SkGradientShader::MakeLinear(
784 pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, flags, nullptr));
reed9283d202016-03-13 13:01:57 -0700785
fmalitabc590c02016-02-22 09:12:33 -0800786 canvas->drawRect(SkRect::MakeXYWH(0, 0, 500, 500), p);
787}
788
789DEF_SIMPLE_GM(gradient_many_stops, canvas, 500, 500) {
790 draw_many_stops(canvas, 0);
791}
792
793DEF_SIMPLE_GM(gradient_many_stops_4f, canvas, 500, 500) {
794 draw_many_stops(canvas, SkLinearGradient::kForce4fContext_PrivateFlag);
795}