blob: fcbba45ae70136188e3bffb0a243c3297581b10d [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 */
7#include "gm.h"
8#include "SkGradientShader.h"
9
10using namespace skiagm;
11
12struct GradData {
13 int fCount;
14 const SkColor* fColors;
15 const SkScalar* fPos;
16};
17
18static const SkColor gColors[] = {
19 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE,
20};
21
22static const GradData gGradData[] = {
23 { 1, gColors, NULL },
24 { 2, gColors, NULL },
25 { 3, gColors, NULL },
26 { 4, gColors, NULL },
27};
28
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000029static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
30 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000031}
32
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000033static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000034 SkPoint center;
35 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
36 SkScalarAve(pts[0].fY, pts[1].fY));
37 return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000038 data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000039}
40
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000041static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000042 SkPoint center;
43 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
44 SkScalarAve(pts[0].fY, pts[1].fY));
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000045 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
bsalomon@google.com82d12232013-09-09 15:36:26 +000046}
47
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000048static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000049 SkPoint center0, center1;
50 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
51 SkScalarAve(pts[0].fY, pts[1].fY));
52 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
53 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
54 return SkGradientShader::CreateTwoPointRadial(
55 center1, (pts[1].fX - pts[0].fX) / 7,
56 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000057 data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000058}
59
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000060static SkShader* Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000061 SkPoint center0, center1;
62 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
63 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
64 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
65 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
66 return SkGradientShader::CreateTwoPointConical(center1, radius1,
67 center0, radius0,
68 data.fColors, data.fPos,
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000069 data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000070}
71
72
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +000073typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm);
74
bsalomon@google.com82d12232013-09-09 15:36:26 +000075static const GradMaker gGradMakers[] = {
76 MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical,
77};
78
79///////////////////////////////////////////////////////////////////////////////
80
81class GradientsNoTextureGM : public GM {
82public:
83 GradientsNoTextureGM() {
84 this->setBGColor(0xFFDDDDDD);
85 }
86
87protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000088 virtual uint32_t onGetFlags() const SK_OVERRIDE {
89 return kSkipTiled_Flag;
90 }
91
bsalomon@google.com82d12232013-09-09 15:36:26 +000092 SkString onShortName() SK_OVERRIDE { return SkString("gradients_no_texture"); }
93 virtual SkISize onISize() SK_OVERRIDE { return make_isize(640, 615); }
94
95 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
96 static const SkPoint kPts[2] = { { 0, 0 },
97 { SkIntToScalar(50), SkIntToScalar(50) } };
98 static const SkShader::TileMode kTM = SkShader::kClamp_TileMode;
99 SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
100 SkPaint paint;
101 paint.setAntiAlias(true);
102
103 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
104 static const uint8_t kAlphas[] = { 0xff, 0x40 };
105 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
106 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
107 canvas->save();
108 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
commit-bot@chromium.org4b8f8022014-05-21 19:56:46 +0000109 SkShader* shader = gGradMakers[j](kPts, gGradData[i], kTM);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000110 paint.setShader(shader)->unref();
111 paint.setAlpha(kAlphas[a]);
112 canvas->drawRect(kRect, paint);
113 canvas->translate(0, SkIntToScalar(kRect.height() + 20));
114 }
115 canvas->restore();
116 canvas->translate(SkIntToScalar(kRect.width() + 20), 0);
117 }
118 }
119 }
120
121private:
122 typedef GM INHERITED;
123};
124
125///////////////////////////////////////////////////////////////////////////////
126
reed@google.com7b8999b2014-04-18 17:55:37 +0000127struct ColorPos {
128 SkColor* fColors;
129 SkScalar* fPos;
130 int fCount;
131
132 ColorPos() : fColors(NULL), fPos(NULL), fCount(0) {}
133 ~ColorPos() {
bsalomon@google.comc25cec52014-04-21 15:30:45 +0000134 SkDELETE_ARRAY(fColors);
135 SkDELETE_ARRAY(fPos);
reed@google.com7b8999b2014-04-18 17:55:37 +0000136 }
137
138 void construct(const SkColor colors[], const SkScalar pos[], int count) {
139 fColors = SkNEW_ARRAY(SkColor, count);
140 memcpy(fColors, colors, count * sizeof(SkColor));
141 if (pos) {
142 fPos = SkNEW_ARRAY(SkScalar, count);
143 memcpy(fPos, pos, count * sizeof(SkScalar));
144 fPos[0] = 0;
145 fPos[count - 1] = 1;
146 }
147 fCount = count;
148 }
149};
150
151static void make0(ColorPos* rec) {
152#if 0
153 From http://jsfiddle.net/3fe2a/
154
155background-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%);
156height: 30px;
157#endif
158
159 const SkColor colors[] = {
160 0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
161 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
162 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
163 };
164 const double percent[] = {
165 1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
166 25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
167 33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
168 55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
169 71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
170 84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
171 };
172 const int N = SK_ARRAY_COUNT(percent);
173 SkScalar pos[N];
174 for (int i = 0; i < N; ++i) {
175 pos[i] = SkDoubleToScalar(percent[i] / 100);
176 }
177 rec->construct(colors, pos, N);
178}
179
180static void make1(ColorPos* rec) {
181 const SkColor colors[] = {
182 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
183 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
184 SK_ColorBLACK,
185 };
186 rec->construct(colors, NULL, SK_ARRAY_COUNT(colors));
187}
188
189static void make2(ColorPos* rec) {
190 const SkColor colors[] = {
191 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
192 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
193 SK_ColorBLACK,
194 };
195 const int N = SK_ARRAY_COUNT(colors);
196 SkScalar pos[N];
197 for (int i = 0; i < N; ++i) {
198 pos[i] = SK_Scalar1 * i / (N - 1);
199 }
200 rec->construct(colors, pos, N);
201}
202
203class GradientsManyColorsGM : public GM {
204 enum {
205 W = 800,
206 };
207 SkAutoTUnref<SkShader> fShader;
208
209 typedef void (*Proc)(ColorPos*);
210public:
211 GradientsManyColorsGM() {}
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000212
reed@google.com7b8999b2014-04-18 17:55:37 +0000213protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000214 virtual uint32_t onGetFlags() const SK_OVERRIDE {
215 return kSkipTiled_Flag;
216 }
217
reed@google.com7b8999b2014-04-18 17:55:37 +0000218 SkString onShortName() SK_OVERRIDE { return SkString("gradients_many"); }
219 virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(850, 100); }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000220
reed@google.com7b8999b2014-04-18 17:55:37 +0000221 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
222 const Proc procs[] = {
223 make0, make1, make2,
224 };
225 const SkPoint pts[] = {
226 { 0, 0 },
227 { SkIntToScalar(W), 0 },
228 };
229 const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
230
231 SkPaint paint;
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000232
reed@google.com7b8999b2014-04-18 17:55:37 +0000233 canvas->translate(20, 20);
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000234
reed@google.com7b8999b2014-04-18 17:55:37 +0000235 for (int i = 0; i <= 8; ++i) {
236 SkScalar x = r.width() * i / 8;
237 canvas->drawLine(x, 0, x, 10000, paint);
238 }
239
240 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
241 ColorPos rec;
242 procs[i](&rec);
243 SkShader* s = SkGradientShader::CreateLinear(pts, rec.fColors, rec.fPos, rec.fCount,
244 SkShader::kClamp_TileMode);
245 paint.setShader(s)->unref();
246 canvas->drawRect(r, paint);
247 canvas->translate(0, r.height() + 20);
248 }
249 }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000250
reed@google.com7b8999b2014-04-18 17:55:37 +0000251private:
252 typedef GM INHERITED;
253};
254
255///////////////////////////////////////////////////////////////////////////////
256
bsalomon@google.com82d12232013-09-09 15:36:26 +0000257DEF_GM( return SkNEW(GradientsNoTextureGM));
reed@google.com7b8999b2014-04-18 17:55:37 +0000258DEF_GM( return SkNEW(GradientsManyColorsGM));