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