Add fixes & test for isConfigTexturable and isConfigRenderable
[platform/upstream/libSkiaSharp.git] / gm / gradients_no_texture.cpp
1 /*
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 "sk_tool_utils.h"
9 #include "SkGradientShader.h"
10
11 using namespace skiagm;
12
13 struct GradData {
14     int             fCount;
15     const SkColor*  fColors;
16     const SkScalar* fPos;
17 };
18
19 constexpr SkColor gColors[] = {
20     SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE,
21 };
22
23 constexpr GradData gGradData[] = {
24     { 1, gColors, nullptr },
25     { 2, gColors, nullptr },
26     { 3, gColors, nullptr },
27     { 4, gColors, nullptr },
28 };
29
30 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
31     return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm);
32 }
33
34 static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
35     SkPoint center;
36     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
37                SkScalarAve(pts[0].fY, pts[1].fY));
38     return SkGradientShader::MakeRadial(center, center.fX, data.fColors, data.fPos, data.fCount, tm);
39 }
40
41 static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode) {
42     SkPoint center;
43     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
44                SkScalarAve(pts[0].fY, pts[1].fY));
45     return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
46 }
47
48 static sk_sp<SkShader> Make2Radial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
49     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::MakeTwoPointConical(
55         center1, (pts[1].fX - pts[0].fX) / 7,
56         center0, (pts[1].fX - pts[0].fX) / 2,
57         data.fColors, data.fPos, data.fCount, tm);
58 }
59
60 static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
61     SkPoint center0, center1;
62     SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
63     SkScalar radius1 = (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::MakeTwoPointConical(center1, radius1,
67                                                    center0, radius0,
68                                                    data.fColors, data.fPos,
69                                                    data.fCount, tm);
70 }
71
72
73 typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm);
74
75 constexpr GradMaker gGradMakers[] = {
76     MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical,
77 };
78
79 ///////////////////////////////////////////////////////////////////////////////
80
81 class GradientsNoTextureGM : public GM {
82 public:
83     GradientsNoTextureGM(bool dither) : fDither(dither) {
84         this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
85     }
86
87 protected:
88
89     SkString onShortName() override {
90         return SkString(fDither ? "gradients_no_texture" : "gradients_no_texture_nodither");
91     }
92
93     SkISize onISize() override { return SkISize::Make(640, 615); }
94
95     void onDraw(SkCanvas* canvas) override {
96         constexpr SkPoint kPts[2] = { { 0, 0 },
97                                          { SkIntToScalar(50), SkIntToScalar(50) } };
98         constexpr SkShader::TileMode kTM = SkShader::kClamp_TileMode;
99         SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
100         SkPaint paint;
101         paint.setAntiAlias(true);
102         paint.setDither(fDither);
103
104         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
105         constexpr uint8_t kAlphas[] = { 0xff, 0x40 };
106         for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
107             for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
108                 canvas->save();
109                 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
110                     paint.setShader(gGradMakers[j](kPts, gGradData[i], kTM));
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
121 private:
122     bool fDither;
123
124     typedef GM INHERITED;
125 };
126
127 ///////////////////////////////////////////////////////////////////////////////
128
129 struct ColorPos {
130     SkColor*    fColors;
131     SkScalar*   fPos;
132     int         fCount;
133
134     ColorPos() : fColors(nullptr), fPos(nullptr), fCount(0) {}
135     ~ColorPos() {
136         delete[] fColors;
137         delete[] fPos;
138     }
139
140     void construct(const SkColor colors[], const SkScalar pos[], int count) {
141         fColors = new SkColor[count];
142         memcpy(fColors, colors, count * sizeof(SkColor));
143         if (pos) {
144             fPos = new SkScalar[count];
145             memcpy(fPos, pos, count * sizeof(SkScalar));
146             fPos[0] = 0;
147             fPos[count - 1] = 1;
148         }
149         fCount = count;
150     }
151 };
152
153 static void make0(ColorPos* rec) {
154 #if 0
155     From http://jsfiddle.net/3fe2a/
156
157 background-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%);
158 height: 30px;
159 #endif
160
161     const SkColor colors[] = {
162         0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
163         0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
164         0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
165     };
166     const double percent[] = {
167         1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
168         25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
169         33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
170         55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
171         71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
172         84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
173     };
174     const int N = SK_ARRAY_COUNT(percent);
175     SkScalar pos[N];
176     for (int i = 0; i < N; ++i) {
177         pos[i] = SkDoubleToScalar(percent[i] / 100);
178     }
179     rec->construct(colors, pos, N);
180 }
181
182 static void make1(ColorPos* rec) {
183     const SkColor colors[] = {
184         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
185         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
186         SK_ColorBLACK,
187     };
188     rec->construct(colors, nullptr, SK_ARRAY_COUNT(colors));
189 }
190
191 static void make2(ColorPos* rec) {
192     const SkColor colors[] = {
193         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
194         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
195         SK_ColorBLACK,
196     };
197     const int N = SK_ARRAY_COUNT(colors);
198     SkScalar pos[N];
199     for (int i = 0; i < N; ++i) {
200         pos[i] = SK_Scalar1 * i / (N - 1);
201     }
202     rec->construct(colors, pos, N);
203 }
204
205 static void make3(ColorPos* rec) {
206     const SkColor colors[] = {
207         SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLACK,
208     };
209     const SkScalar pos[] = {
210         0, 0, 0.5f, 0.5, 1, 1,
211     };
212     rec->construct(colors, pos, SK_ARRAY_COUNT(colors));
213 }
214
215 class GradientsManyColorsGM : public GM {
216     enum {
217         W = 800,
218     };
219     sk_sp<SkShader> fShader;
220
221     typedef void (*Proc)(ColorPos*);
222 public:
223     GradientsManyColorsGM(bool dither) : fDither(dither) {}
224
225 protected:
226
227     SkString onShortName() override {
228         return SkString(fDither ? "gradients_many" : "gradients_many_nodither");
229     }
230
231     SkISize onISize() override { return SkISize::Make(880, 400); }
232
233     void onDraw(SkCanvas* canvas) override {
234         const Proc procs[] = {
235             make0, make1, make2, make3,
236         };
237         const SkPoint pts[] = {
238             { 0, 0 },
239             { SkIntToScalar(W), 0 },
240         };
241         const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
242
243         SkPaint paint;
244         paint.setDither(fDither);
245
246         canvas->translate(40, 20);
247
248         for (int i = 0; i <= 8; ++i) {
249             SkScalar x = r.width() * i / 8;
250             canvas->drawLine(x, 0, x, 10000, paint);
251         }
252
253         // expand the drawing rect so we exercise clampping in the gradients
254         const SkRect drawR = r.makeOutset(20, 0);
255         for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
256             ColorPos rec;
257             procs[i](&rec);
258             paint.setShader(SkGradientShader::MakeLinear(pts, rec.fColors, rec.fPos, rec.fCount,
259                                                          SkShader::kClamp_TileMode));
260             canvas->drawRect(drawR, paint);
261
262             canvas->save();
263             canvas->translate(r.centerX(), r.height() + 4);
264             canvas->scale(-1, 1);
265             canvas->translate(-r.centerX(), 0);
266             canvas->drawRect(drawR, paint);
267             canvas->restore();
268
269             canvas->translate(0, r.height() + 2*r.height() + 8);
270         }
271     }
272
273 private:
274     bool fDither;
275
276     typedef GM INHERITED;
277 };
278
279 ///////////////////////////////////////////////////////////////////////////////
280
281 DEF_GM(return new GradientsNoTextureGM(true);)
282 DEF_GM(return new GradientsNoTextureGM(false);)
283 DEF_GM(return new GradientsManyColorsGM(true);)
284 DEF_GM(return new GradientsManyColorsGM(false);)