blob: 2e75c9ed79fcdd844c75dcd78fe73dc54d4ce383 [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.org3339ac52014-05-22 02:55:59 +000029static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
30 SkShader::TileMode tm, SkUnitMapper* mapper) {
31 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
32 data.fCount, tm, mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000033}
34
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000035static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
36 SkShader::TileMode tm, SkUnitMapper* mapper) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000037 SkPoint center;
38 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
39 SkScalarAve(pts[0].fY, pts[1].fY));
40 return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000041 data.fPos, data.fCount, tm, mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000042}
43
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000044static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
45 SkShader::TileMode, SkUnitMapper* mapper) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000046 SkPoint center;
47 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
48 SkScalarAve(pts[0].fY, pts[1].fY));
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000049 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
50 data.fPos, data.fCount, mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000051}
52
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000053static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
54 SkShader::TileMode tm, SkUnitMapper* mapper) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000055 SkPoint center0, center1;
56 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
57 SkScalarAve(pts[0].fY, pts[1].fY));
58 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
59 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
60 return SkGradientShader::CreateTwoPointRadial(
61 center1, (pts[1].fX - pts[0].fX) / 7,
62 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000063 data.fColors, data.fPos, data.fCount, tm, mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000064}
65
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000066static SkShader* Make2Conical(const SkPoint pts[2], const GradData& data,
67 SkShader::TileMode tm, SkUnitMapper* mapper) {
bsalomon@google.com82d12232013-09-09 15:36:26 +000068 SkPoint center0, center1;
69 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
70 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
71 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
72 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
73 return SkGradientShader::CreateTwoPointConical(center1, radius1,
74 center0, radius0,
75 data.fColors, data.fPos,
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000076 data.fCount, tm, mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000077}
78
79
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +000080typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
81 SkShader::TileMode tm, SkUnitMapper* mapper);
bsalomon@google.com82d12232013-09-09 15:36:26 +000082static const GradMaker gGradMakers[] = {
83 MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical,
84};
85
86///////////////////////////////////////////////////////////////////////////////
87
88class GradientsNoTextureGM : public GM {
89public:
90 GradientsNoTextureGM() {
91 this->setBGColor(0xFFDDDDDD);
92 }
93
94protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000095 virtual uint32_t onGetFlags() const SK_OVERRIDE {
96 return kSkipTiled_Flag;
97 }
98
bsalomon@google.com82d12232013-09-09 15:36:26 +000099 SkString onShortName() SK_OVERRIDE { return SkString("gradients_no_texture"); }
100 virtual SkISize onISize() SK_OVERRIDE { return make_isize(640, 615); }
101
102 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
103 static const SkPoint kPts[2] = { { 0, 0 },
104 { SkIntToScalar(50), SkIntToScalar(50) } };
105 static const SkShader::TileMode kTM = SkShader::kClamp_TileMode;
106 SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
107 SkPaint paint;
108 paint.setAntiAlias(true);
109
110 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
111 static const uint8_t kAlphas[] = { 0xff, 0x40 };
112 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
113 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
114 canvas->save();
115 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
commit-bot@chromium.org3339ac52014-05-22 02:55:59 +0000116 SkShader* shader = gGradMakers[j](kPts, gGradData[i], kTM, NULL);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000117 paint.setShader(shader)->unref();
118 paint.setAlpha(kAlphas[a]);
119 canvas->drawRect(kRect, paint);
120 canvas->translate(0, SkIntToScalar(kRect.height() + 20));
121 }
122 canvas->restore();
123 canvas->translate(SkIntToScalar(kRect.width() + 20), 0);
124 }
125 }
126 }
127
128private:
129 typedef GM INHERITED;
130};
131
132///////////////////////////////////////////////////////////////////////////////
133
reed@google.com7b8999b2014-04-18 17:55:37 +0000134struct ColorPos {
135 SkColor* fColors;
136 SkScalar* fPos;
137 int fCount;
138
139 ColorPos() : fColors(NULL), fPos(NULL), fCount(0) {}
140 ~ColorPos() {
bsalomon@google.comc25cec52014-04-21 15:30:45 +0000141 SkDELETE_ARRAY(fColors);
142 SkDELETE_ARRAY(fPos);
reed@google.com7b8999b2014-04-18 17:55:37 +0000143 }
144
145 void construct(const SkColor colors[], const SkScalar pos[], int count) {
146 fColors = SkNEW_ARRAY(SkColor, count);
147 memcpy(fColors, colors, count * sizeof(SkColor));
148 if (pos) {
149 fPos = SkNEW_ARRAY(SkScalar, count);
150 memcpy(fPos, pos, count * sizeof(SkScalar));
151 fPos[0] = 0;
152 fPos[count - 1] = 1;
153 }
154 fCount = count;
155 }
156};
157
158static void make0(ColorPos* rec) {
159#if 0
160 From http://jsfiddle.net/3fe2a/
161
162background-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%);
163height: 30px;
164#endif
165
166 const SkColor colors[] = {
167 0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
168 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
169 0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
170 };
171 const double percent[] = {
172 1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
173 25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
174 33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
175 55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
176 71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
177 84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
178 };
179 const int N = SK_ARRAY_COUNT(percent);
180 SkScalar pos[N];
181 for (int i = 0; i < N; ++i) {
182 pos[i] = SkDoubleToScalar(percent[i] / 100);
183 }
184 rec->construct(colors, pos, N);
185}
186
187static void make1(ColorPos* rec) {
188 const SkColor colors[] = {
189 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
190 SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
191 SK_ColorBLACK,
192 };
193 rec->construct(colors, NULL, SK_ARRAY_COUNT(colors));
194}
195
196static void make2(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 };
202 const int N = SK_ARRAY_COUNT(colors);
203 SkScalar pos[N];
204 for (int i = 0; i < N; ++i) {
205 pos[i] = SK_Scalar1 * i / (N - 1);
206 }
207 rec->construct(colors, pos, N);
208}
209
210class GradientsManyColorsGM : public GM {
211 enum {
212 W = 800,
213 };
214 SkAutoTUnref<SkShader> fShader;
215
216 typedef void (*Proc)(ColorPos*);
217public:
218 GradientsManyColorsGM() {}
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000219
reed@google.com7b8999b2014-04-18 17:55:37 +0000220protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000221 virtual uint32_t onGetFlags() const SK_OVERRIDE {
222 return kSkipTiled_Flag;
223 }
224
reed@google.com7b8999b2014-04-18 17:55:37 +0000225 SkString onShortName() SK_OVERRIDE { return SkString("gradients_many"); }
226 virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(850, 100); }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000227
reed@google.com7b8999b2014-04-18 17:55:37 +0000228 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
229 const Proc procs[] = {
230 make0, make1, make2,
231 };
232 const SkPoint pts[] = {
233 { 0, 0 },
234 { SkIntToScalar(W), 0 },
235 };
236 const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
237
238 SkPaint paint;
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000239
reed@google.com7b8999b2014-04-18 17:55:37 +0000240 canvas->translate(20, 20);
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000241
reed@google.com7b8999b2014-04-18 17:55:37 +0000242 for (int i = 0; i <= 8; ++i) {
243 SkScalar x = r.width() * i / 8;
244 canvas->drawLine(x, 0, x, 10000, paint);
245 }
246
247 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
248 ColorPos rec;
249 procs[i](&rec);
250 SkShader* s = SkGradientShader::CreateLinear(pts, rec.fColors, rec.fPos, rec.fCount,
251 SkShader::kClamp_TileMode);
252 paint.setShader(s)->unref();
253 canvas->drawRect(r, paint);
254 canvas->translate(0, r.height() + 20);
255 }
256 }
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000257
reed@google.com7b8999b2014-04-18 17:55:37 +0000258private:
259 typedef GM INHERITED;
260};
261
262///////////////////////////////////////////////////////////////////////////////
263
bsalomon@google.com82d12232013-09-09 15:36:26 +0000264DEF_GM( return SkNEW(GradientsNoTextureGM));
reed@google.com7b8999b2014-04-18 17:55:37 +0000265DEF_GM( return SkNEW(GradientsManyColorsGM));