1/*
2 * Copyright 2014 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
10#include "SkBitmap.h"
11#include "SkPaint.h"
12#include "SkPicture.h"
13#include "SkPictureRecorder.h"
14#include "SkShader.h"
15
16static struct {
17    SkShader::TileMode tmx;
18    SkShader::TileMode tmy;
19} kTileConfigs[] = {
20    { SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode },
21    { SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode  },
22    { SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode },
23};
24
25class PictureShaderGM : public skiagm::GM {
26public:
27    PictureShaderGM(SkScalar tileSize, SkScalar sceneSize)
28        : fTileSize(tileSize)
29        , fSceneSize(sceneSize) {
30
31        // Build the picture.
32        SkPictureRecorder recorder;
33        SkCanvas* pictureCanvas = recorder.beginRecording(SkScalarRoundToInt(tileSize),
34                                                          SkScalarRoundToInt(tileSize),
35                                                          NULL, 0);
36        this->drawTile(pictureCanvas);
37        fPicture.reset(recorder.endRecording());
38
39        // Build a reference bitmap.
40        fBitmap.allocN32Pixels(SkScalarRoundToInt(tileSize), SkScalarRoundToInt(tileSize));
41        fBitmap.eraseColor(SK_ColorTRANSPARENT);
42        SkCanvas bitmapCanvas(fBitmap);
43        this->drawTile(&bitmapCanvas);
44    }
45
46protected:
47    virtual uint32_t onGetFlags() const SK_OVERRIDE {
48        return kSkipTiled_Flag;
49    }
50
51    virtual SkString onShortName() SK_OVERRIDE {
52        return SkString("pictureshader");
53    }
54
55    virtual SkISize onISize() SK_OVERRIDE {
56        return SkISize::Make(1400, 1250);
57    }
58
59    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
60        this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0);
61        this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0);
62        this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1);
63        this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2);
64        this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0);
65        this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0);
66    }
67
68private:
69    void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale,
70                         unsigned tileMode) {
71        SkMatrix ctm, localMatrix;
72
73        ctm.setTranslate(pos.x(), pos.y());
74        ctm.preScale(scale, scale);
75        localMatrix.setScale(localScale, localScale);
76        this->drawScene(canvas, ctm, localMatrix, tileMode);
77
78        ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale);
79        ctm.preScale(scale, scale);
80        localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
81        localMatrix.preScale(localScale, localScale);
82        this->drawScene(canvas, ctm, localMatrix, tileMode);
83
84        ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale);
85        ctm.preScale(scale, scale);
86        localMatrix.setRotate(45);
87        localMatrix.preScale(localScale, localScale);
88        this->drawScene(canvas, ctm, localMatrix, tileMode);
89
90        ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale);
91        ctm.preScale(scale, scale);
92        localMatrix.setSkew(1, 0);
93        localMatrix.preScale(localScale, localScale);
94        this->drawScene(canvas, ctm, localMatrix, tileMode);
95
96        ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale);
97        ctm.preScale(scale, scale);
98        localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
99        localMatrix.preRotate(45);
100        localMatrix.preScale(localScale, localScale);
101        this->drawScene(canvas, ctm, localMatrix, tileMode);
102    }
103
104    void drawTile(SkCanvas* canvas) {
105        SkPaint paint;
106        paint.setColor(SK_ColorGREEN);
107        paint.setStyle(SkPaint::kFill_Style);
108        paint.setAntiAlias(true);
109
110        canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint);
111        canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2,
112                                          fTileSize / 2, fTileSize / 2), paint);
113
114        paint.setColor(SK_ColorRED);
115        canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3,
116                         fTileSize / 2, fTileSize * 2 / 3, paint);
117        canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2,
118                         fTileSize * 2 / 3, fTileSize / 2, paint);
119    }
120
121    void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix,
122                   unsigned tileMode) {
123        SkASSERT(tileMode < SK_ARRAY_COUNT(kTileConfigs));
124
125        SkPaint paint;
126        paint.setStyle(SkPaint::kFill_Style);
127        paint.setColor(SK_ColorLTGRAY);
128
129        canvas->save();
130        canvas->concat(matrix);
131        canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
132        canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint);
133
134        SkAutoTUnref<SkShader> pictureShader(SkShader::CreatePictureShader(
135                    fPicture,
136                    kTileConfigs[tileMode].tmx,
137                    kTileConfigs[tileMode].tmy,
138                    &localMatrix));
139        paint.setShader(pictureShader.get());
140        canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
141
142        canvas->translate(fSceneSize * 1.1f, 0);
143
144        SkAutoTUnref<SkShader> bitmapShader(SkShader::CreateBitmapShader(
145                    fBitmap,
146                    kTileConfigs[tileMode].tmx,
147                    kTileConfigs[tileMode].tmy,
148                    &localMatrix));
149        paint.setShader(bitmapShader.get());
150        canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
151
152        canvas->restore();
153    }
154
155    SkScalar    fTileSize;
156    SkScalar    fSceneSize;
157
158    SkAutoTUnref<SkPicture> fPicture;
159    SkBitmap fBitmap;
160
161    typedef GM INHERITED;
162};
163
164DEF_GM( return SkNEW_ARGS(PictureShaderGM, (50, 100)); )
165