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