blob: ae715ced6ebcd5ccf98413fddb085e10f3dc3d96 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com42309d42009-06-22 02:06:35 +00008#include "gm.h"
9#include "SkGradientShader.h"
10
11namespace skiagm {
12
13struct GradData {
14 int fCount;
15 const SkColor* fColors;
16 const SkScalar* fPos;
17};
18
19static const SkColor gColors[] = {
20 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
21};
22static const SkScalar gPos0[] = { 0, SK_Scalar1 };
23static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
24static const SkScalar gPos2[] = {
25 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
26};
27
28static 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
36static 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}
reed@google.comf3c1cc92010-12-23 16:45:33 +000041
reed@android.com42309d42009-06-22 02:06:35 +000042static 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
51static 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
reed@google.comf3c1cc92010-12-23 16:45:33 +000060static 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
reed@android.com42309d42009-06-22 02:06:35 +000073typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
reed@google.comf3c1cc92010-12-23 16:45:33 +000074 SkShader::TileMode tm, SkUnitMapper* mapper);
reed@android.com42309d42009-06-22 02:06:35 +000075static const GradMaker gGradMakers[] = {
reed@google.comf3c1cc92010-12-23 16:45:33 +000076 MakeLinear, MakeRadial, MakeSweep, Make2Radial
reed@android.com42309d42009-06-22 02:06:35 +000077};
78
79///////////////////////////////////////////////////////////////////////////////
80
81class GradientsGM : public GM {
82public:
83 GradientsGM() {}
84
85protected:
86 SkString onShortName() {
87 return SkString("gradients");
88 }
89
reed@google.comac864a92011-06-27 18:11:17 +000090 virtual SkISize onISize() { return make_isize(640, 510); }
reed@android.com42309d42009-06-22 02:06:35 +000091
92 void drawBG(SkCanvas* canvas) {
93 canvas->drawColor(0xFFDDDDDD);
94 }
95
96 virtual void onDraw(SkCanvas* canvas) {
97 this->drawBG(canvas);
98
99 SkPoint pts[2] = {
100 { 0, 0 },
101 { SkIntToScalar(100), SkIntToScalar(100) }
102 };
103 SkShader::TileMode tm = SkShader::kClamp_TileMode;
104 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
105 SkPaint paint;
106 paint.setAntiAlias(true);
107
108 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
109 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
110 canvas->save();
111 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
112 SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
113 paint.setShader(shader);
114 canvas->drawRect(r, paint);
115 shader->unref();
116 canvas->translate(0, SkIntToScalar(120));
117 }
118 canvas->restore();
119 canvas->translate(SkIntToScalar(120), 0);
120 }
121 }
122
123private:
124 typedef GM INHERITED;
125};
126
reed@google.comac864a92011-06-27 18:11:17 +0000127/*
128 Inspired by this <canvas> javascript, where we need to detect that we are not
129 solving a quadratic equation, but must instead solve a linear (since our X^2
130 coefficient is 0)
131
132 ctx.fillStyle = '#f00';
133 ctx.fillRect(0, 0, 100, 50);
134
135 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
136 g.addColorStop(0, '#f00');
137 g.addColorStop(0.01, '#0f0');
138 g.addColorStop(0.99, '#0f0');
139 g.addColorStop(1, '#f00');
140 ctx.fillStyle = g;
141 ctx.fillRect(0, 0, 100, 50);
142 */
143class GradientsDegenrate2PointGM : public GM {
144public:
145 GradientsDegenrate2PointGM() {}
146
147protected:
148 SkString onShortName() {
149 return SkString("gradients_degenerate_2pt");
150 }
151
152 virtual SkISize onISize() { return make_isize(320, 320); }
153
154 void drawBG(SkCanvas* canvas) {
155 canvas->drawColor(SK_ColorBLUE);
156 }
157
158 virtual void onDraw(SkCanvas* canvas) {
159 this->drawBG(canvas);
160
161 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
162 SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
epoger@google.com59f3abf2011-07-21 15:50:33 +0000163 SkPoint c0;
164 c0.iset(-80, 25);
165 SkScalar r0 = SkIntToScalar(70);
166 SkPoint c1;
167 c1.iset(0, 25);
168 SkScalar r1 = SkIntToScalar(150);
reed@google.comac864a92011-06-27 18:11:17 +0000169 SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
170 pos, SK_ARRAY_COUNT(pos),
171 SkShader::kClamp_TileMode);
172 SkPaint paint;
173 paint.setShader(s)->unref();
174 canvas->drawPaint(paint);
175 }
176
177private:
178 typedef GM INHERITED;
179};
180
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000181/// Tests correctness of *optimized* codepaths in gradients.
182
183class ClampedGradientsGM : public GM {
184public:
185 ClampedGradientsGM() {}
186
187protected:
188 SkString onShortName() { return SkString("clamped_gradients"); }
189
190 virtual SkISize onISize() { return make_isize(640, 510); }
191
192 void drawBG(SkCanvas* canvas) {
193 canvas->drawColor(0xFFDDDDDD);
194 }
195
196 virtual void onDraw(SkCanvas* canvas) {
197 this->drawBG(canvas);
198
199 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
200 SkPaint paint;
201 paint.setAntiAlias(true);
202
203 SkPoint center;
204 center.iset(0, 300);
205 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
206 SkShader* shader = SkGradientShader::CreateRadial(
207 SkPoint(center),
bungeman@google.com01744a42011-10-06 19:37:39 +0000208 SkIntToScalar(200), gColors, NULL, 5,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000209 SkShader::kClamp_TileMode, NULL);
210 paint.setShader(shader);
211 canvas->drawRect(r, paint);
212 shader->unref();
213 }
214
215private:
216 typedef GM INHERITED;
217};
218
219
reed@android.com42309d42009-06-22 02:06:35 +0000220///////////////////////////////////////////////////////////////////////////////
221
222static GM* MyFactory(void*) { return new GradientsGM; }
223static GMRegistry reg(MyFactory);
224
reed@google.comac864a92011-06-27 18:11:17 +0000225static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
226static GMRegistry reg2(MyFactory2);
227
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000228static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
229static GMRegistry reg3(MyFactory3);
230
reed@android.com42309d42009-06-22 02:06:35 +0000231}
232