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