blob: e706ac634f597cbb13df2a55938b6651d27a81a1 [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.org83f23d82014-05-22 12:27:41 +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.org83f23d82014-05-22 12:27:41 +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.org83f23d82014-05-22 12:27:41 +000038 data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000039}
40
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +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.org83f23d82014-05-22 12:27:41 +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.org83f23d82014-05-22 12:27:41 +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));
reed71a6cbf2015-05-04 08:32:51 -070054 return SkGradientShader::CreateTwoPointConical(
bsalomon@google.com82d12232013-09-09 15:36:26 +000055 center1, (pts[1].fX - pts[0].fX) / 7,
56 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000057 data.fColors, data.fPos, data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000058}
59
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +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;
reed80ea19c2015-05-12 10:37:34 -070062 SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
63 SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
bsalomon@google.com82d12232013-09-09 15:36:26 +000064 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.org83f23d82014-05-22 12:27:41 +000069 data.fCount, tm);
bsalomon@google.com82d12232013-09-09 15:36:26 +000070}
71
72
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +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() {
caryclark65cdba62015-06-15 06:51:08 -070084 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
bsalomon@google.com82d12232013-09-09 15:36:26 +000085 }
86
87protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000088
mtklein36352bf2015-03-25 18:17:31 -070089 SkString onShortName() override { return SkString("gradients_no_texture"); }
90 SkISize onISize() override { return SkISize::Make(640, 615); }
bsalomon@google.com82d12232013-09-09 15:36:26 +000091
mtklein36352bf2015-03-25 18:17:31 -070092 void onDraw(SkCanvas* canvas) override {
bsalomon@google.com82d12232013-09-09 15:36:26 +000093 static const SkPoint kPts[2] = { { 0, 0 },
94 { SkIntToScalar(50), SkIntToScalar(50) } };
95 static const SkShader::TileMode kTM = SkShader::kClamp_TileMode;
96 SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
97 SkPaint paint;
98 paint.setAntiAlias(true);
99
100 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
101 static const uint8_t kAlphas[] = { 0xff, 0x40 };
102 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
103 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
104 canvas->save();
105 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000106 SkShader* shader = gGradMakers[j](kPts, gGradData[i], kTM);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000107 paint.setShader(shader)->unref();
108 paint.setAlpha(kAlphas[a]);
109 canvas->drawRect(kRect, paint);
110 canvas->translate(0, SkIntToScalar(kRect.height() + 20));
111 }
112 canvas->restore();
113 canvas->translate(SkIntToScalar(kRect.width() + 20), 0);
114 }
115 }
116 }
117
118private:
119 typedef GM INHERITED;
120};
121
122///////////////////////////////////////////////////////////////////////////////
123
reed@google.com7b8999b2014-04-18 17:55:37 +0000124struct ColorPos {
125 SkColor* fColors;
126 SkScalar* fPos;
127 int fCount;
128
129 ColorPos() : fColors(NULL), fPos(NULL), fCount(0) {}
130 ~ColorPos() {
bsalomon@google.comc25cec52014-04-21 15:30:45 +0000131 SkDELETE_ARRAY(fColors);
132 SkDELETE_ARRAY(fPos);
reed@google.com7b8999b2014-04-18 17:55:37 +0000133 }
134
135 void construct(const SkColor colors[], const SkScalar pos[], int count) {
136 fColors = SkNEW_ARRAY(SkColor, count);
137 memcpy(fColors, colors, count * sizeof(SkColor));
138 if (pos) {
139 fPos = SkNEW_ARRAY(SkScalar, count);
140 memcpy(fPos, pos, count * sizeof(SkScalar));
141 fPos[0] = 0;
142 fPos[count - 1] = 1;
143 }
144 fCount = count;
145 }
146};
147
148static void make0(ColorPos* rec) {
149#if 0
150 From http://jsfiddle.net/3fe2a/
151
152background-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%);
153height: 30px;
154#endif
155
156 const SkColor colors[] = {
157 0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
158 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
159 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
160 };
161 const double percent[] = {
162 1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
163 25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
164 33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
165 55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
166 71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
167 84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
168 };
169 const int N = SK_ARRAY_COUNT(percent);
170 SkScalar pos[N];
171 for (int i = 0; i < N; ++i) {
172 pos[i] = SkDoubleToScalar(percent[i] / 100);
173 }
174 rec->construct(colors, pos, N);
175}
176
177static void make1(ColorPos* rec) {
178 const SkColor colors[] = {
179 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
180 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
181 SK_ColorBLACK,
182 };
183 rec->construct(colors, NULL, SK_ARRAY_COUNT(colors));
184}
185
186static void make2(ColorPos* rec) {
187 const SkColor colors[] = {
188 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
189 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
190 SK_ColorBLACK,
191 };
192 const int N = SK_ARRAY_COUNT(colors);
193 SkScalar pos[N];
194 for (int i = 0; i < N; ++i) {
195 pos[i] = SK_Scalar1 * i / (N - 1);
196 }
197 rec->construct(colors, pos, N);
198}
199
200class GradientsManyColorsGM : public GM {
201 enum {
202 W = 800,
203 };
204 SkAutoTUnref<SkShader> fShader;
205
206 typedef void (*Proc)(ColorPos*);
207public:
208 GradientsManyColorsGM() {}
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000209
reed@google.com7b8999b2014-04-18 17:55:37 +0000210protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000211
mtklein36352bf2015-03-25 18:17:31 -0700212 SkString onShortName() override { return SkString("gradients_many"); }
213 SkISize onISize() override { return SkISize::Make(850, 100); }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000214
mtklein36352bf2015-03-25 18:17:31 -0700215 void onDraw(SkCanvas* canvas) override {
reed@google.com7b8999b2014-04-18 17:55:37 +0000216 const Proc procs[] = {
217 make0, make1, make2,
218 };
219 const SkPoint pts[] = {
220 { 0, 0 },
221 { SkIntToScalar(W), 0 },
222 };
223 const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
224
225 SkPaint paint;
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000226
reed@google.com7b8999b2014-04-18 17:55:37 +0000227 canvas->translate(20, 20);
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000228
reed@google.com7b8999b2014-04-18 17:55:37 +0000229 for (int i = 0; i <= 8; ++i) {
230 SkScalar x = r.width() * i / 8;
231 canvas->drawLine(x, 0, x, 10000, paint);
232 }
233
234 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
235 ColorPos rec;
236 procs[i](&rec);
237 SkShader* s = SkGradientShader::CreateLinear(pts, rec.fColors, rec.fPos, rec.fCount,
238 SkShader::kClamp_TileMode);
239 paint.setShader(s)->unref();
240 canvas->drawRect(r, paint);
241 canvas->translate(0, r.height() + 20);
242 }
243 }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000244
reed@google.com7b8999b2014-04-18 17:55:37 +0000245private:
246 typedef GM INHERITED;
247};
248
249///////////////////////////////////////////////////////////////////////////////
250
bsalomon@google.com82d12232013-09-09 15:36:26 +0000251DEF_GM( return SkNEW(GradientsNoTextureGM));
reed@google.com7b8999b2014-04-18 17:55:37 +0000252DEF_GM( return SkNEW(GradientsManyColorsGM));