1/*
2 * Copyright 2012 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
8#include "gm.h"
9#include "SkCanvas.h"
10#include "SkShader.h"
11#include "SkStippleMaskFilter.h"
12
13namespace skiagm {
14
15/**
16 * Stress test the samplers by rendering a textured glyph with a mask and
17 * an AA clip
18 */
19class SamplerStressGM : public GM {
20public:
21    SamplerStressGM()
22    : fTextureCreated(false)
23    , fShader(NULL)
24    , fMaskFilter(NULL) {
25    }
26
27    virtual ~SamplerStressGM() {
28    }
29
30protected:
31    virtual uint32_t onGetFlags() const SK_OVERRIDE {
32        return kSkipTiled_Flag;
33    }
34
35    virtual SkString onShortName() {
36        return SkString("samplerstress");
37    }
38
39    virtual SkISize onISize() {
40        return SkISize::Make(640, 480);
41    }
42
43    /**
44     * Create a red & green stripes on black texture
45     */
46    void createTexture() {
47        if (fTextureCreated) {
48            return;
49        }
50
51        static const int xSize = 16;
52        static const int ySize = 16;
53
54        fTexture.allocN32Pixels(xSize, ySize);
55        SkPMColor* addr = fTexture.getAddr32(0, 0);
56
57        for (int y = 0; y < ySize; ++y) {
58            for (int x = 0; x < xSize; ++x) {
59                addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorBLACK);
60
61                if ((y % 5) == 0) {
62                    addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorRED);
63                }
64                if ((x % 7) == 0) {
65                    addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorGREEN);
66                }
67            }
68        }
69
70        fTextureCreated = true;
71    }
72
73    void createShader() {
74        if (NULL != fShader.get()) {
75            return;
76        }
77
78        createTexture();
79
80        fShader.reset(SkShader::CreateBitmapShader(fTexture,
81                                                   SkShader::kRepeat_TileMode,
82                                                   SkShader::kRepeat_TileMode));
83    }
84
85    void createMaskFilter() {
86        if (NULL != fMaskFilter.get()) {
87            return;
88        }
89
90        fMaskFilter.reset(SkStippleMaskFilter::Create());
91    }
92
93    virtual void onDraw(SkCanvas* canvas) {
94
95        createShader();
96        createMaskFilter();
97
98        canvas->save();
99
100        // draw a letter "M" with a green & red striped texture and a
101        // stipple mask with a round rect soft clip
102        SkPaint paint;
103        paint.setAntiAlias(true);
104        paint.setTextSize(72);
105        paint.setShader(fShader.get());
106        paint.setMaskFilter(fMaskFilter.get());
107
108        SkRect temp;
109        temp.set(SkIntToScalar(115),
110                 SkIntToScalar(75),
111                 SkIntToScalar(144),
112                 SkIntToScalar(110));
113
114        SkPath path;
115        path.addRoundRect(temp, SkIntToScalar(5), SkIntToScalar(5));
116
117        canvas->clipPath(path, SkRegion::kReplace_Op, true); // AA is on
118
119        canvas->drawText("M", 1,
120                         SkIntToScalar(100), SkIntToScalar(100),
121                         paint);
122
123        canvas->restore();
124
125        // Now draw stroked versions of the "M" and the round rect so we can
126        // see what is going on
127        SkPaint paint2;
128        paint2.setColor(SK_ColorBLACK);
129        paint2.setAntiAlias(true);
130        paint2.setTextSize(72);
131        paint2.setStyle(SkPaint::kStroke_Style);
132        paint2.setStrokeWidth(1);
133        canvas->drawText("M", 1,
134                         SkIntToScalar(100), SkIntToScalar(100),
135                         paint2);
136
137        paint2.setColor(SK_ColorGRAY);
138
139        canvas->drawPath(path, paint2);
140    }
141
142private:
143    SkBitmap      fTexture;
144    bool          fTextureCreated;
145    SkAutoTUnref<SkShader>     fShader;
146    SkAutoTUnref<SkMaskFilter> fMaskFilter;
147
148    typedef GM INHERITED;
149};
150
151//////////////////////////////////////////////////////////////////////////////
152
153static GM* MyFactory(void*) { return new SamplerStressGM; }
154static GMRegistry reg(MyFactory);
155
156}
157