• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 static 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 
25 class PictureShaderGM : public skiagm::GM {
26 public:
PictureShaderGM(SkScalar tileSize,SkScalar sceneSize)27     PictureShaderGM(SkScalar tileSize, SkScalar sceneSize)
28         : fTileSize(tileSize)
29         , fSceneSize(sceneSize) {
30     }
31 
32  protected:
onOnceBeforeDraw()33     void onOnceBeforeDraw() override {
34        // Build the picture.
35         SkPictureRecorder recorder;
36         SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, nullptr, 0);
37         this->drawTile(pictureCanvas);
38         fPicture.reset(recorder.endRecording());
39 
40         // Build a reference bitmap.
41         fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize));
42         fBitmap.eraseColor(SK_ColorTRANSPARENT);
43         SkCanvas bitmapCanvas(fBitmap);
44         this->drawTile(&bitmapCanvas);
45     }
46 
47 
onShortName()48     SkString onShortName() override {
49         return SkString("pictureshader");
50     }
51 
onISize()52     SkISize onISize() override {
53         return SkISize::Make(1400, 1450);
54     }
55 
onDraw(SkCanvas * canvas)56     void onDraw(SkCanvas* canvas) override {
57         this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0);
58         this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0);
59         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1);
60         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2);
61         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0);
62         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0);
63 
64         // One last custom row to exercise negative scaling
65         SkMatrix ctm, localMatrix;
66         ctm.setTranslate(fSceneSize * 2.1f, fSceneSize * 13.8f);
67         ctm.preScale(-1, -1);
68         localMatrix.setScale(2, 2);
69         this->drawScene(canvas, ctm, localMatrix, 0);
70 
71         ctm.setTranslate(fSceneSize * 2.4f, fSceneSize * 12.8f);
72         localMatrix.setScale(-1, -1);
73         this->drawScene(canvas, ctm, localMatrix, 0);
74 
75         ctm.setTranslate(fSceneSize * 4.8f, fSceneSize * 12.3f);
76         ctm.preScale(2, 2);
77         this->drawScene(canvas, ctm, localMatrix, 0);
78 
79         ctm.setTranslate(fSceneSize * 13.8f, fSceneSize * 14.3f);
80         ctm.preScale(-2, -2);
81         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
82         localMatrix.preRotate(45);
83         localMatrix.preScale(-2, -2);
84         this->drawScene(canvas, ctm, localMatrix, 0);
85     }
86 
87 private:
drawSceneColumn(SkCanvas * canvas,const SkPoint & pos,SkScalar scale,SkScalar localScale,unsigned tileMode)88     void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale,
89                          unsigned tileMode) {
90         SkMatrix ctm, localMatrix;
91 
92         ctm.setTranslate(pos.x(), pos.y());
93         ctm.preScale(scale, scale);
94         localMatrix.setScale(localScale, localScale);
95         this->drawScene(canvas, ctm, localMatrix, tileMode);
96 
97         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale);
98         ctm.preScale(scale, scale);
99         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
100         localMatrix.preScale(localScale, localScale);
101         this->drawScene(canvas, ctm, localMatrix, tileMode);
102 
103         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale);
104         ctm.preScale(scale, scale);
105         localMatrix.setRotate(45);
106         localMatrix.preScale(localScale, localScale);
107         this->drawScene(canvas, ctm, localMatrix, tileMode);
108 
109         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale);
110         ctm.preScale(scale, scale);
111         localMatrix.setSkew(1, 0);
112         localMatrix.preScale(localScale, localScale);
113         this->drawScene(canvas, ctm, localMatrix, tileMode);
114 
115         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale);
116         ctm.preScale(scale, scale);
117         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
118         localMatrix.preRotate(45);
119         localMatrix.preScale(localScale, localScale);
120         this->drawScene(canvas, ctm, localMatrix, tileMode);
121     }
122 
drawTile(SkCanvas * canvas)123     void drawTile(SkCanvas* canvas) {
124         SkPaint paint;
125         paint.setColor(SK_ColorGREEN);
126         paint.setStyle(SkPaint::kFill_Style);
127         paint.setAntiAlias(true);
128 
129         canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint);
130         canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2,
131                                           fTileSize / 2, fTileSize / 2), paint);
132 
133         paint.setColor(SK_ColorRED);
134         canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3,
135                          fTileSize / 2, fTileSize * 2 / 3, paint);
136         canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2,
137                          fTileSize * 2 / 3, fTileSize / 2, paint);
138     }
139 
drawScene(SkCanvas * canvas,const SkMatrix & matrix,const SkMatrix & localMatrix,unsigned tileMode)140     void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix,
141                    unsigned tileMode) {
142         SkASSERT(tileMode < SK_ARRAY_COUNT(kTileConfigs));
143 
144         SkPaint paint;
145         paint.setStyle(SkPaint::kFill_Style);
146         paint.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY));
147 
148         canvas->save();
149         canvas->concat(matrix);
150         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
151         canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint);
152 
153         SkAutoTUnref<SkShader> pictureShader(
154                 SkShader::CreatePictureShader(fPicture, kTileConfigs[tileMode].tmx,
155                                               kTileConfigs[tileMode].tmy, &localMatrix, nullptr));
156         paint.setShader(pictureShader.get());
157         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
158 
159         canvas->translate(fSceneSize * 1.1f, 0);
160 
161         SkAutoTUnref<SkShader> bitmapShader(SkShader::CreateBitmapShader(
162                     fBitmap,
163                     kTileConfigs[tileMode].tmx,
164                     kTileConfigs[tileMode].tmy,
165                     &localMatrix));
166         paint.setShader(bitmapShader.get());
167         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
168 
169         canvas->restore();
170     }
171 
172     SkScalar    fTileSize;
173     SkScalar    fSceneSize;
174 
175     SkAutoTUnref<SkPicture> fPicture;
176     SkBitmap fBitmap;
177 
178     typedef GM INHERITED;
179 };
180 
181 DEF_GM(return new PictureShaderGM(50, 100);)
182 
183 DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
184     // https://code.google.com/p/skia/issues/detail?id=3398
185     SkRect tile = SkRect::MakeWH(100, 100);
186 
187     SkPictureRecorder recorder;
188     SkCanvas* c = recorder.beginRecording(tile);
189 
190     SkRect r = tile;
191     r.inset(4, 4);
192     SkPaint p;
193     p.setColor(sk_tool_utils::color_to_565(0xFF303F9F));  // dark blue
194     c->drawRect(r, p);
195     p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9));  // light blue
196     p.setStrokeWidth(10);
197     c->drawLine(20, 20, 80, 80, p);
198 
199     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
200     SkAutoTUnref<SkShader> shader(
201             SkShader::CreatePictureShader(picture.get(), SkShader::kRepeat_TileMode,
202                                           SkShader::kRepeat_TileMode, nullptr, nullptr));
203 
204     p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A));  // green
205     canvas->drawPaint(p);
206 
207     canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
208     p.setColor(sk_tool_utils::color_to_565(0xFFB6B6B6));  // gray
209     canvas->drawPaint(p);
210     p.setShader(shader.get());
211 
212     canvas->drawPaint(p);
213 }
214