• 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)28     PictureShaderGM(SkScalar tileSize, SkScalar sceneSize)
29         : fTileSize(tileSize)
30         , fSceneSize(sceneSize) {
31     }
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 SkString("pictureshader");
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_tool_utils::color_to_565(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         paint.setShader(SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx,
155                                                     kTileConfigs[tileMode].tmy, &localMatrix,
156                                                     nullptr));
157         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
158 
159         canvas->translate(fSceneSize * 1.1f, 0);
160 
161         paint.setShader(SkShader::MakeBitmapShader(fBitmap,
162                                                    kTileConfigs[tileMode].tmx,
163                                                    kTileConfigs[tileMode].tmy,
164                                                    &localMatrix));
165         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
166 
167         canvas->restore();
168     }
169 
170     SkScalar    fTileSize;
171     SkScalar    fSceneSize;
172 
173     sk_sp<SkPicture> fPicture;
174     SkBitmap fBitmap;
175 
176     typedef GM INHERITED;
177 };
178 
179 DEF_GM(return new PictureShaderGM(50, 100);)
180 
181 DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
182     // https://code.google.com/p/skia/issues/detail?id=3398
183     SkRect tile = SkRect::MakeWH(100, 100);
184 
185     SkPictureRecorder recorder;
186     SkCanvas* c = recorder.beginRecording(tile);
187 
188     SkRect r = tile;
189     r.inset(4, 4);
190     SkPaint p;
191     p.setColor(sk_tool_utils::color_to_565(0xFF303F9F));  // dark blue
192     c->drawRect(r, p);
193     p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9));  // light blue
194     p.setStrokeWidth(10);
195     c->drawLine(20, 20, 80, 80, p);
196 
197     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
198 
199     p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A));  // green
200     canvas->drawPaint(p);
201 
202     canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
203     p.setColor(sk_tool_utils::color_to_565(0xFFB6B6B6));  // gray
204     canvas->drawPaint(p);
205 
206     p.setShader(SkShader::MakePictureShader(std::move(picture), SkShader::kRepeat_TileMode,
207                                             SkShader::kRepeat_TileMode,
208                                             nullptr, nullptr));
209     canvas->drawPaint(p);
210 }
211