• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "gm.h"
9 #include "SkGradientShader.h"
10 
11 namespace skiagm {
12 
13 struct GradData {
14     int             fCount;
15     const SkColor*  fColors;
16     const SkScalar* fPos;
17 };
18 
19 static const SkColor gColors[] = {
20     SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
21 };
22 static const SkScalar gPos0[] = { 0, SK_Scalar1 };
23 static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
24 static const SkScalar gPos2[] = {
25     0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
26 };
27 
28 static const GradData gGradData[] = {
29     { 2, gColors, NULL },
30     { 2, gColors, gPos0 },
31     { 2, gColors, gPos1 },
32     { 5, gColors, NULL },
33     { 5, gColors, gPos2 }
34 };
35 
MakeLinear(const SkPoint pts[2],const GradData & data,SkShader::TileMode tm,SkUnitMapper * mapper)36 static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
37                             SkShader::TileMode tm, SkUnitMapper* mapper) {
38     return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
39                                           data.fCount, tm, mapper);
40 }
41 
MakeRadial(const SkPoint pts[2],const GradData & data,SkShader::TileMode tm,SkUnitMapper * mapper)42 static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
43                             SkShader::TileMode tm, SkUnitMapper* mapper) {
44     SkPoint center;
45     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
46                SkScalarAve(pts[0].fY, pts[1].fY));
47     return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
48                                           data.fPos, data.fCount, tm, mapper);
49 }
50 
MakeSweep(const SkPoint pts[2],const GradData & data,SkShader::TileMode tm,SkUnitMapper * mapper)51 static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
52                            SkShader::TileMode tm, SkUnitMapper* mapper) {
53     SkPoint center;
54     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
55                SkScalarAve(pts[0].fY, pts[1].fY));
56     return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
57                                          data.fPos, data.fCount, mapper);
58 }
59 
Make2Radial(const SkPoint pts[2],const GradData & data,SkShader::TileMode tm,SkUnitMapper * mapper)60 static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
61                              SkShader::TileMode tm, SkUnitMapper* mapper) {
62     SkPoint center0, center1;
63     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
64                 SkScalarAve(pts[0].fY, pts[1].fY));
65     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
66                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
67     return SkGradientShader::CreateTwoPointRadial(
68                                                   center1, (pts[1].fX - pts[0].fX) / 7,
69                                                   center0, (pts[1].fX - pts[0].fX) / 2,
70                                                   data.fColors, data.fPos, data.fCount, tm, mapper);
71 }
72 
73 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
74                                SkShader::TileMode tm, SkUnitMapper* mapper);
75 static const GradMaker gGradMakers[] = {
76     MakeLinear, MakeRadial, MakeSweep, Make2Radial
77 };
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 
81 class GradientsGM : public GM {
82 public:
GradientsGM()83 	GradientsGM() {
84         this->setBGColor(0xFFDDDDDD);
85     }
86 
87 protected:
onShortName()88     SkString onShortName() {
89         return SkString("gradients");
90     }
91 
onISize()92     virtual SkISize onISize() { return make_isize(640, 510); }
93 
onDraw(SkCanvas * canvas)94     virtual void onDraw(SkCanvas* canvas) {
95 
96         SkPoint pts[2] = {
97             { 0, 0 },
98             { SkIntToScalar(100), SkIntToScalar(100) }
99         };
100         SkShader::TileMode tm = SkShader::kClamp_TileMode;
101         SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
102         SkPaint paint;
103         paint.setAntiAlias(true);
104 
105         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
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++) {
109                 SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
110                 paint.setShader(shader);
111                 canvas->drawRect(r, paint);
112                 shader->unref();
113                 canvas->translate(0, SkIntToScalar(120));
114             }
115             canvas->restore();
116             canvas->translate(SkIntToScalar(120), 0);
117         }
118     }
119 
120 private:
121     typedef GM INHERITED;
122 };
123 
124 /*
125  Inspired by this <canvas> javascript, where we need to detect that we are not
126  solving a quadratic equation, but must instead solve a linear (since our X^2
127  coefficient is 0)
128 
129  ctx.fillStyle = '#f00';
130  ctx.fillRect(0, 0, 100, 50);
131 
132  var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
133  g.addColorStop(0, '#f00');
134  g.addColorStop(0.01, '#0f0');
135  g.addColorStop(0.99, '#0f0');
136  g.addColorStop(1, '#f00');
137  ctx.fillStyle = g;
138  ctx.fillRect(0, 0, 100, 50);
139  */
140 class GradientsDegenrate2PointGM : public GM {
141 public:
GradientsDegenrate2PointGM()142     GradientsDegenrate2PointGM() {}
143 
144 protected:
onShortName()145     SkString onShortName() {
146         return SkString("gradients_degenerate_2pt");
147     }
148 
onISize()149 	virtual SkISize onISize() { return make_isize(320, 320); }
150 
drawBG(SkCanvas * canvas)151     void drawBG(SkCanvas* canvas) {
152         canvas->drawColor(SK_ColorBLUE);
153     }
154 
onDraw(SkCanvas * canvas)155     virtual void onDraw(SkCanvas* canvas) {
156         this->drawBG(canvas);
157 
158         SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
159         SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
160         SkPoint c0;
161         c0.iset(-80, 25);
162         SkScalar r0 = SkIntToScalar(70);
163         SkPoint c1;
164         c1.iset(0, 25);
165         SkScalar r1 = SkIntToScalar(150);
166         SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
167                                                              pos, SK_ARRAY_COUNT(pos),
168                                                              SkShader::kClamp_TileMode);
169         SkPaint paint;
170         paint.setShader(s)->unref();
171         canvas->drawPaint(paint);
172     }
173 
174 private:
175     typedef GM INHERITED;
176 };
177 
178 /// Tests correctness of *optimized* codepaths in gradients.
179 
180 class ClampedGradientsGM : public GM {
181 public:
ClampedGradientsGM()182     ClampedGradientsGM() {}
183 
184 protected:
onShortName()185     SkString onShortName() { return SkString("clamped_gradients"); }
186 
onISize()187     virtual SkISize onISize() { return make_isize(640, 510); }
188 
drawBG(SkCanvas * canvas)189     void drawBG(SkCanvas* canvas) {
190         canvas->drawColor(0xFFDDDDDD);
191     }
192 
onDraw(SkCanvas * canvas)193     virtual void onDraw(SkCanvas* canvas) {
194         this->drawBG(canvas);
195 
196         SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
197         SkPaint paint;
198         paint.setAntiAlias(true);
199 
200         SkPoint center;
201         center.iset(0, 300);
202         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
203         SkShader* shader = SkGradientShader::CreateRadial(
204             SkPoint(center),
205             SkIntToScalar(200), gColors, NULL, 5,
206             SkShader::kClamp_TileMode, NULL);
207         paint.setShader(shader);
208         canvas->drawRect(r, paint);
209         shader->unref();
210     }
211 
212 private:
213     typedef GM INHERITED;
214 };
215 
216 /// Checks quality of large radial gradients, which may display
217 /// some banding.
218 
219 class RadialGradientGM : public GM {
220 public:
RadialGradientGM()221     RadialGradientGM() {}
222 
223 protected:
onShortName()224     SkString onShortName() { return SkString("radial_gradient"); }
onISize()225     virtual SkISize onISize() { return make_isize(1280, 1280); }
drawBG(SkCanvas * canvas)226     void drawBG(SkCanvas* canvas) {
227         canvas->drawColor(0xFF000000);
228     }
onDraw(SkCanvas * canvas)229     virtual void onDraw(SkCanvas* canvas) {
230         const SkISize dim = this->getISize();
231 
232         this->drawBG(canvas);
233 
234         SkPaint paint;
235         paint.setDither(true);
236         SkPoint center;
237         center.set(SkIntToScalar(dim.width())/2, SkIntToScalar(dim.height())/2);
238         SkScalar radius = SkIntToScalar(dim.width())/2;
239         const SkColor colors[] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
240         const SkScalar pos[] = { SkFloatToScalar(0.0),
241                              SkFloatToScalar(0.35),
242                              SkFloatToScalar(1.0) };
243         SkShader* shader =
244             SkGradientShader::CreateRadial(center, radius, colors,
245                                            pos, SK_ARRAY_COUNT(pos),
246                                            SkShader::kClamp_TileMode);
247         paint.setShader(shader)->unref();
248         SkRect r = {
249             0, 0, SkIntToScalar(dim.width()), SkIntToScalar(dim.height())
250         };
251         canvas->drawRect(r, paint);
252     }
253 private:
254     typedef GM INHERITED;
255 };
256 
257 
258 
259 ///////////////////////////////////////////////////////////////////////////////
260 
MyFactory(void *)261 static GM* MyFactory(void*) { return new GradientsGM; }
262 static GMRegistry reg(MyFactory);
263 
MyFactory2(void *)264 static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
265 static GMRegistry reg2(MyFactory2);
266 
MyFactory3(void *)267 static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
268 static GMRegistry reg3(MyFactory3);
269 
MyFactory4(void *)270 static GM* MyFactory4(void*) { return new RadialGradientGM; }
271 static GMRegistry reg4(MyFactory4);
272 }
273 
274