1#include "gm.h"
2#include "SkCanvas.h"
3#include "SkGradientShader.h"
4#include "SkUnitMappers.h"
5
6namespace skiagm {
7
8static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) {
9    bm->setConfig(config, w, h);
10    bm->allocPixels();
11    bm->eraseColor(0);
12
13    SkCanvas    canvas(*bm);
14    SkScalar    s = SkIntToScalar(SkMin32(w, h));
15    SkPoint     pts[] = { { 0, 0 }, { s, s } };
16    SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
17    SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
18    SkPaint     paint;
19
20    SkUnitMapper*   um = NULL;
21
22    um = new SkCosineMapper;
23
24    SkAutoUnref au(um);
25
26    paint.setDither(true);
27    paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
28                SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, um))->unref();
29    canvas.drawPaint(paint);
30}
31
32SkShader* MakeBitmapShader(SkShader::TileMode tx, SkShader::TileMode ty,
33                           int w, int h) {
34    static SkBitmap bmp;
35    if (bmp.isNull()) {
36        makebm(&bmp, SkBitmap::kARGB_8888_Config, w/2, h/4);
37    }
38    return SkShader::CreateBitmapShader(bmp, tx, ty);
39}
40
41///////////////////////////////////////////////////////////////////////////////
42
43struct GradData {
44    int             fCount;
45    const SkColor*  fColors;
46    const SkScalar* fPos;
47};
48
49static const SkColor gColors[] = {
50    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
51};
52
53static const GradData gGradData[] = {
54    { 2, gColors, NULL },
55    { 5, gColors, NULL },
56};
57
58static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
59                            SkShader::TileMode tm, SkUnitMapper* mapper) {
60    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
61                                          data.fCount, tm, mapper);
62}
63
64static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
65                            SkShader::TileMode tm, SkUnitMapper* mapper) {
66    SkPoint center;
67    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
68               SkScalarAve(pts[0].fY, pts[1].fY));
69    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
70                                          data.fPos, data.fCount, tm, mapper);
71}
72
73static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
74                           SkShader::TileMode tm, SkUnitMapper* mapper) {
75    SkPoint center;
76    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
77               SkScalarAve(pts[0].fY, pts[1].fY));
78    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
79                                         data.fPos, data.fCount, mapper);
80}
81
82static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
83                           SkShader::TileMode tm, SkUnitMapper* mapper) {
84    SkPoint center0, center1;
85    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
86                SkScalarAve(pts[0].fY, pts[1].fY));
87    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
88                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
89    return SkGradientShader::CreateTwoPointRadial(
90                            center1, (pts[1].fX - pts[0].fX) / 7,
91                            center0, (pts[1].fX - pts[0].fX) / 2,
92                            data.fColors, data.fPos, data.fCount, tm, mapper);
93}
94
95typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
96                     SkShader::TileMode tm, SkUnitMapper* mapper);
97static const GradMaker gGradMakers[] = {
98    MakeLinear, MakeRadial, MakeSweep, Make2Radial
99};
100
101///////////////////////////////////////////////////////////////////////////////
102
103class ShaderTextGM : public GM {
104public:
105	ShaderTextGM() {}
106
107protected:
108
109    SkString onShortName() {
110        return SkString("shadertext");
111    }
112
113	SkISize onISize() { return make_isize(950, 500); }
114
115    void drawBG(SkCanvas* canvas) {
116        canvas->drawColor(0xFFDDDDDD);
117    }
118
119    virtual void onDraw(SkCanvas* canvas) {
120        this->drawBG(canvas);
121
122        const char text[] = "Shaded Text";
123        const int textLen = SK_ARRAY_COUNT(text) - 1;
124        const int pointSize = 48;
125
126        int w = pointSize * textLen;
127        int h = pointSize;
128
129        SkPoint pts[2] = {
130            { 0, 0 },
131            { SkIntToScalar(w), SkIntToScalar(h) }
132        };
133        SkScalar textBase = SkIntToScalar(h/2);
134
135        SkShader::TileMode tileModes[] = {
136            SkShader::kClamp_TileMode,
137            SkShader::kRepeat_TileMode,
138            SkShader::kMirror_TileMode
139        };
140
141        static const int gradCount = SK_ARRAY_COUNT(gGradData) *
142                                     SK_ARRAY_COUNT(gGradMakers);
143        static const int bmpCount = SK_ARRAY_COUNT(tileModes) *
144                                    SK_ARRAY_COUNT(tileModes);
145        SkShader* shaders[gradCount + bmpCount];
146
147        int shdIdx = 0;
148        for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) {
149            for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) {
150                shaders[shdIdx++] = gGradMakers[m](pts,
151                                                   gGradData[d],
152                                                   SkShader::kClamp_TileMode,
153                                                   NULL);
154            }
155        }
156        for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) {
157            for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) {
158                shaders[shdIdx++] = MakeBitmapShader(tileModes[tx],
159                                                     tileModes[ty],
160                                                     w/8, h);
161            }
162        }
163
164        SkPaint paint;
165        paint.setDither(true);
166        paint.setAntiAlias(true);
167        paint.setTextSize(SkIntToScalar(pointSize));
168
169        canvas->save();
170        canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
171
172        static const int testsPerCol = 8;
173        static const int rowHeight = 60;
174        static const int colWidth = 300;
175        canvas->save();
176        for (size_t s = 0; s < SK_ARRAY_COUNT(shaders); s++) {
177            canvas->save();
178            canvas->translate(SkIntToScalar((s / testsPerCol) * colWidth),
179                              SkIntToScalar((s % testsPerCol) * rowHeight));
180                              paint.setShader(shaders[s])->ref();
181            canvas->drawText(text, textLen, 0, textBase, paint);
182            canvas->restore();
183        }
184        canvas->restore();
185    }
186
187private:
188    typedef GM INHERITED;
189};
190
191///////////////////////////////////////////////////////////////////////////////
192
193static GM* MyFactory(void*) { return new ShaderTextGM; }
194static GMRegistry reg(MyFactory);
195
196}
197