1/*
2 * Copyright 2011 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#include "gm.h"
8#include "SkCanvas.h"
9#include "SkGradientShader.h"
10#include "SkUnitMappers.h"
11
12namespace skiagm {
13
14static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) {
15    bm->setConfig(config, w, h);
16    bm->allocPixels();
17    bm->eraseColor(SK_ColorTRANSPARENT);
18
19    SkCanvas    canvas(*bm);
20    SkScalar    s = SkIntToScalar(SkMin32(w, h));
21    static const SkPoint     kPts0[] = { { 0, 0 }, { s, s } };
22    static const SkPoint     kPts1[] = { { s, 0 }, { 0, s } };
23    static const SkScalar    kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
24    static const SkColor kColors0[] = {0x40FF00FF, 0xF0FFFF00, 0x4000FFFF };
25    static const SkColor kColors1[] = {0xF0FF00FF, 0x80FFFF00, 0xF000FFFF };
26
27
28    SkPaint     paint;
29
30    SkUnitMapper*   um = NULL;
31
32    um = new SkCosineMapper;
33
34    SkAutoUnref au(um);
35
36    paint.setShader(SkGradientShader::CreateLinear(kPts0, kColors0, kPos,
37                    SK_ARRAY_COUNT(kColors0), SkShader::kClamp_TileMode, um))->unref();
38    canvas.drawPaint(paint);
39    paint.setShader(SkGradientShader::CreateLinear(kPts1, kColors1, kPos,
40                    SK_ARRAY_COUNT(kColors1), SkShader::kClamp_TileMode))->unref();
41    canvas.drawPaint(paint);
42}
43
44///////////////////////////////////////////////////////////////////////////////
45
46struct LabeledMatrix {
47    SkMatrix    fMatrix;
48    const char* fLabel;
49};
50
51class ShaderText2GM : public GM {
52public:
53    ShaderText2GM() {
54        this->setBGColor(0xFFDDDDDD);
55    }
56
57protected:
58
59    SkString onShortName() {
60        return SkString("shadertext2");
61    }
62
63    SkISize onISize() { return make_isize(1800, 900); }
64
65    virtual void onDraw(SkCanvas* canvas) {
66        static const char kText[] = "SKIA";
67        static const int kTextLen = SK_ARRAY_COUNT(kText) - 1;
68        static const int kPointSize = 55;
69
70        SkTDArray<LabeledMatrix> matrices;
71        matrices.append()->fMatrix.reset();
72        matrices.top().fLabel = "Identity";
73        matrices.append()->fMatrix.setScale(1.2f, 0.8f);
74        matrices.top().fLabel = "Scale";
75        matrices.append()->fMatrix.setRotate(10.f);
76        matrices.top().fLabel = "Rotate";
77        matrices.append()->fMatrix.reset();
78        matrices.top().fMatrix.setPerspX(-0.0015f);
79        matrices.top().fMatrix.setPerspY(+0.0015f);
80        matrices.top().fLabel = "Persp";
81
82        SkTDArray<LabeledMatrix> localMatrices;
83        localMatrices.append()->fMatrix.reset();
84        localMatrices.top().fLabel = "Identity";
85        localMatrices.append()->fMatrix.setScale(2.5f, 0.2f);
86        localMatrices.top().fLabel = "Scale";
87        localMatrices.append()->fMatrix.setRotate(45.f);
88        localMatrices.top().fLabel = "Rotate";
89        localMatrices.append()->fMatrix.reset();
90        localMatrices.top().fMatrix.setPerspX(-0.007f);
91        localMatrices.top().fMatrix.setPerspY(+0.008f);
92        localMatrices.top().fLabel = "Persp";
93
94        static SkBitmap bmp;
95        if (bmp.isNull()) {
96            makebm(&bmp, SkBitmap::kARGB_8888_Config, kPointSize / 2, kPointSize / 2);
97        }
98
99        SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(bmp,
100                                                                   SkShader::kMirror_TileMode,
101                                                                   SkShader::kRepeat_TileMode));
102        SkPaint fillPaint;
103        fillPaint.setAntiAlias(true);
104        fillPaint.setTextSize(SkIntToScalar(kPointSize));
105        fillPaint.setFilterBitmap(true);
106        fillPaint.setShader(shader);
107
108        SkPaint outlinePaint;
109        outlinePaint.setAntiAlias(true);
110        outlinePaint.setTextSize(SkIntToScalar(kPointSize));
111        outlinePaint.setStyle(SkPaint::kStroke_Style);
112        outlinePaint.setStrokeWidth(0.f);
113
114        SkScalar w = fillPaint.measureText(kText, kTextLen);
115        static SkScalar kPadY = 0.5f * kPointSize;
116        static SkScalar kPadX = 1.5f * kPointSize;
117
118        SkPaint strokePaint(fillPaint);
119        strokePaint.setStyle(SkPaint::kStroke_Style);
120        strokePaint.setStrokeWidth(kPointSize * 0.1f);
121
122        SkPaint labelPaint;
123        labelPaint.setColor(0xff000000);
124        labelPaint.setAntiAlias(true);
125        labelPaint.setTextSize(12.f);
126
127        canvas->translate(15.f, 15.f);
128        canvas->drawBitmap(bmp, 0, 0);
129        canvas->translate(0, bmp.height() + labelPaint.getTextSize() + 15.f);
130
131        static const char kLabelLabel[] = "localM / canvasM";
132        canvas->drawText(kLabelLabel, strlen(kLabelLabel), 0, 0, labelPaint);
133        canvas->translate(0, 15.f);
134
135        canvas->save();
136        SkScalar maxLabelW = 0;
137        canvas->translate(0, kPadY / 2 + kPointSize);
138        for (int lm = 0; lm < localMatrices.count(); ++lm) {
139            canvas->drawText(matrices[lm].fLabel, strlen(matrices[lm].fLabel),
140                             0, labelPaint.getTextSize() - 1, labelPaint);
141            SkScalar labelW = labelPaint.measureText(matrices[lm].fLabel,
142                                                     strlen(matrices[lm].fLabel));
143            maxLabelW = SkMaxScalar(maxLabelW, labelW);
144            canvas->translate(0.f, 2 * kPointSize + 2.5f * kPadY);
145        }
146        canvas->restore();
147
148        canvas->translate(maxLabelW + kPadX / 2.f, 0.f);
149
150        for (int s = 0; s < 2; ++s) {
151            SkPaint& paint = s ? strokePaint : fillPaint;
152
153            SkScalar columnH;
154            for (int m = 0; m < matrices.count(); ++m) {
155                columnH = 0;
156                canvas->save();
157                canvas->drawText(matrices[m].fLabel, strlen(matrices[m].fLabel),
158                                 0, labelPaint.getTextSize() - 1, labelPaint);
159                canvas->translate(0, kPadY / 2 + kPointSize);
160                columnH += kPadY / 2 + kPointSize;
161                for (int lm = 0; lm < localMatrices.count(); ++lm) {
162                    shader->setLocalMatrix(localMatrices[lm].fMatrix);
163
164                    canvas->save();
165                        canvas->concat(matrices[m].fMatrix);
166                        canvas->drawText(kText, kTextLen, 0, 0, paint);
167                        canvas->drawText(kText, kTextLen, 0, 0, outlinePaint);
168                    canvas->restore();
169
170                    SkPath path;
171                    path.arcTo(SkRect::MakeXYWH(-0.1f * w, 0.f,
172                                                1.2f * w, 2.f * kPointSize),
173                                                225.f, 359.f,
174                                                false);
175                    path.close();
176
177                    canvas->translate(0.f, kPointSize + kPadY);
178                    columnH += kPointSize + kPadY;
179
180                    canvas->save();
181                        canvas->concat(matrices[m].fMatrix);
182                        canvas->drawTextOnPath(kText, kTextLen, path, NULL, paint);
183                        canvas->drawTextOnPath(kText, kTextLen, path, NULL, outlinePaint);
184                    canvas->restore();
185                    SkPaint stroke;
186                    stroke.setStyle(SkPaint::kStroke_Style);
187                    canvas->translate(0.f, kPointSize + kPadY);
188                    columnH += kPointSize + kPadY;
189                }
190                canvas->restore();
191                canvas->translate(w + kPadX, 0.f);
192            }
193            if (0 == s) {
194                canvas->drawLine(0.f, -kPadY, 0.f, columnH + kPadY, outlinePaint);
195                canvas->translate(kPadX / 2, 0.f);
196                static const char kFillLabel[] = "Filled";
197                static const char kStrokeLabel[] = "Stroked";
198                SkScalar y = columnH + kPadY / 2;
199                SkScalar fillX = -outlinePaint.measureText(kFillLabel, strlen(kFillLabel)) - kPadX;
200                SkScalar strokeX = kPadX;
201                canvas->drawText(kFillLabel, strlen(kFillLabel), fillX, y, labelPaint);
202                canvas->drawText(kStrokeLabel, strlen(kStrokeLabel), strokeX, y, labelPaint);
203            }
204        }
205    }
206
207    virtual uint32_t onGetFlags() const SK_OVERRIDE {
208        // disable 565 for now, til mike fixes the debug assert
209        return this->INHERITED::onGetFlags() | kSkip565_Flag;
210    }
211
212private:
213    typedef GM INHERITED;
214};
215
216///////////////////////////////////////////////////////////////////////////////
217
218#ifndef SK_BUILD_FOR_ANDROID
219static GM* MyFactory(void*) { return new ShaderText2GM; }
220static GMRegistry reg(MyFactory);
221#endif
222}
223