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