xref: /aosp_15_r20/external/skia/gm/pictureshader.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPictureRecorder.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker static struct {
30*c8dee2aaSAndroid Build Coastguard Worker     SkTileMode tmx;
31*c8dee2aaSAndroid Build Coastguard Worker     SkTileMode tmy;
32*c8dee2aaSAndroid Build Coastguard Worker } kTileConfigs[] = {
33*c8dee2aaSAndroid Build Coastguard Worker     { SkTileMode::kRepeat, SkTileMode::kRepeat },
34*c8dee2aaSAndroid Build Coastguard Worker     { SkTileMode::kRepeat, SkTileMode::kClamp  },
35*c8dee2aaSAndroid Build Coastguard Worker     { SkTileMode::kMirror, SkTileMode::kRepeat },
36*c8dee2aaSAndroid Build Coastguard Worker };
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker class PictureShaderGM : public skiagm::GM {
39*c8dee2aaSAndroid Build Coastguard Worker public:
PictureShaderGM(SkScalar tileSize,SkScalar sceneSize,bool useLocalMatrixWrapper=false,float alpha=1)40*c8dee2aaSAndroid Build Coastguard Worker     PictureShaderGM(SkScalar tileSize, SkScalar sceneSize, bool useLocalMatrixWrapper = false,
41*c8dee2aaSAndroid Build Coastguard Worker                     float alpha = 1)
42*c8dee2aaSAndroid Build Coastguard Worker         : fTileSize(tileSize)
43*c8dee2aaSAndroid Build Coastguard Worker         , fSceneSize(sceneSize)
44*c8dee2aaSAndroid Build Coastguard Worker         , fAlpha(alpha)
45*c8dee2aaSAndroid Build Coastguard Worker         , fUseLocalMatrixWrapper(useLocalMatrixWrapper)
46*c8dee2aaSAndroid Build Coastguard Worker     {}
47*c8dee2aaSAndroid Build Coastguard Worker 
48*c8dee2aaSAndroid Build Coastguard Worker  protected:
onOnceBeforeDraw()49*c8dee2aaSAndroid Build Coastguard Worker     void onOnceBeforeDraw() override {
50*c8dee2aaSAndroid Build Coastguard Worker        // Build the picture.
51*c8dee2aaSAndroid Build Coastguard Worker         SkPictureRecorder recorder;
52*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize);
53*c8dee2aaSAndroid Build Coastguard Worker         this->drawTile(pictureCanvas);
54*c8dee2aaSAndroid Build Coastguard Worker         fPicture = recorder.finishRecordingAsPicture();
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker         // Build a reference bitmap.
57*c8dee2aaSAndroid Build Coastguard Worker         fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize));
58*c8dee2aaSAndroid Build Coastguard Worker         fBitmap.eraseColor(SK_ColorTRANSPARENT);
59*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas bitmapCanvas(fBitmap);
60*c8dee2aaSAndroid Build Coastguard Worker         this->drawTile(&bitmapCanvas);
61*c8dee2aaSAndroid Build Coastguard Worker     }
62*c8dee2aaSAndroid Build Coastguard Worker 
getName() const63*c8dee2aaSAndroid Build Coastguard Worker     SkString getName() const override {
64*c8dee2aaSAndroid Build Coastguard Worker         return SkStringPrintf("pictureshader%s%s",
65*c8dee2aaSAndroid Build Coastguard Worker                               fUseLocalMatrixWrapper ? "_localwrapper" : "",
66*c8dee2aaSAndroid Build Coastguard Worker                               fAlpha < 1 ? "_alpha" : "");
67*c8dee2aaSAndroid Build Coastguard Worker     }
68*c8dee2aaSAndroid Build Coastguard Worker 
getISize()69*c8dee2aaSAndroid Build Coastguard Worker     SkISize getISize() override { return SkISize::Make(1400, 1450); }
70*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(SkCanvas * canvas)71*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(SkCanvas* canvas) override {
72*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0);
73*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0);
74*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1);
75*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2);
76*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0);
77*c8dee2aaSAndroid Build Coastguard Worker         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0);
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker         // One last custom row to exercise negative scaling
80*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix ctm, localMatrix;
81*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(fSceneSize * 2.1f, fSceneSize * 13.8f);
82*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(-1, -1);
83*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setScale(2, 2);
84*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, 0);
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(fSceneSize * 2.4f, fSceneSize * 12.8f);
87*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setScale(-1, -1);
88*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, 0);
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(fSceneSize * 4.8f, fSceneSize * 12.3f);
91*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(2, 2);
92*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, 0);
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(fSceneSize * 13.8f, fSceneSize * 14.3f);
95*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(-2, -2);
96*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
97*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preRotate(45);
98*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preScale(-2, -2);
99*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, 0);
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker private:
drawSceneColumn(SkCanvas * canvas,const SkPoint & pos,SkScalar scale,SkScalar localScale,unsigned tileMode)103*c8dee2aaSAndroid Build Coastguard Worker     void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale,
104*c8dee2aaSAndroid Build Coastguard Worker                          unsigned tileMode) {
105*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix ctm, localMatrix;
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(pos.x(), pos.y());
108*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(scale, scale);
109*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setScale(localScale, localScale);
110*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, tileMode);
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale);
113*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(scale, scale);
114*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
115*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preScale(localScale, localScale);
116*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, tileMode);
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale);
119*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(scale, scale);
120*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setRotate(45);
121*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preScale(localScale, localScale);
122*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, tileMode);
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale);
125*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(scale, scale);
126*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setSkew(1, 0);
127*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preScale(localScale, localScale);
128*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, tileMode);
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale);
131*c8dee2aaSAndroid Build Coastguard Worker         ctm.preScale(scale, scale);
132*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
133*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preRotate(45);
134*c8dee2aaSAndroid Build Coastguard Worker         localMatrix.preScale(localScale, localScale);
135*c8dee2aaSAndroid Build Coastguard Worker         this->drawScene(canvas, ctm, localMatrix, tileMode);
136*c8dee2aaSAndroid Build Coastguard Worker     }
137*c8dee2aaSAndroid Build Coastguard Worker 
drawTile(SkCanvas * canvas)138*c8dee2aaSAndroid Build Coastguard Worker     void drawTile(SkCanvas* canvas) {
139*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
140*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorGREEN);
141*c8dee2aaSAndroid Build Coastguard Worker         paint.setStyle(SkPaint::kFill_Style);
142*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
143*c8dee2aaSAndroid Build Coastguard Worker 
144*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint);
145*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2,
146*c8dee2aaSAndroid Build Coastguard Worker                                           fTileSize / 2, fTileSize / 2), paint);
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorRED);
149*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3,
150*c8dee2aaSAndroid Build Coastguard Worker                          fTileSize / 2, fTileSize * 2 / 3, paint);
151*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2,
152*c8dee2aaSAndroid Build Coastguard Worker                          fTileSize * 2 / 3, fTileSize / 2, paint);
153*c8dee2aaSAndroid Build Coastguard Worker     }
154*c8dee2aaSAndroid Build Coastguard Worker 
drawScene(SkCanvas * canvas,const SkMatrix & matrix,const SkMatrix & localMatrix,unsigned tileMode)155*c8dee2aaSAndroid Build Coastguard Worker     void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix,
156*c8dee2aaSAndroid Build Coastguard Worker                    unsigned tileMode) {
157*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(tileMode < std::size(kTileConfigs));
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
160*c8dee2aaSAndroid Build Coastguard Worker         paint.setStyle(SkPaint::kFill_Style);
161*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorLTGRAY);
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker         canvas->save();
164*c8dee2aaSAndroid Build Coastguard Worker         canvas->concat(matrix);
165*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
166*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint);
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker         paint.setAlphaf(fAlpha);
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker         auto pictureShader = fPicture->makeShader(kTileConfigs[tileMode].tmx,
171*c8dee2aaSAndroid Build Coastguard Worker                                                   kTileConfigs[tileMode].tmy,
172*c8dee2aaSAndroid Build Coastguard Worker                                                   SkFilterMode::kNearest,
173*c8dee2aaSAndroid Build Coastguard Worker                                                   fUseLocalMatrixWrapper ? nullptr : &localMatrix,
174*c8dee2aaSAndroid Build Coastguard Worker                                                   nullptr);
175*c8dee2aaSAndroid Build Coastguard Worker         paint.setShader(fUseLocalMatrixWrapper
176*c8dee2aaSAndroid Build Coastguard Worker                             ? pictureShader->makeWithLocalMatrix(localMatrix)
177*c8dee2aaSAndroid Build Coastguard Worker                             : pictureShader);
178*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(fSceneSize * 1.1f, 0);
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker         auto bitmapShader = fBitmap.makeShader(kTileConfigs[tileMode].tmx,
183*c8dee2aaSAndroid Build Coastguard Worker                                                kTileConfigs[tileMode].tmy,
184*c8dee2aaSAndroid Build Coastguard Worker                                                SkSamplingOptions(),
185*c8dee2aaSAndroid Build Coastguard Worker                                                fUseLocalMatrixWrapper ? nullptr : &localMatrix);
186*c8dee2aaSAndroid Build Coastguard Worker         paint.setShader(fUseLocalMatrixWrapper
187*c8dee2aaSAndroid Build Coastguard Worker                             ? bitmapShader->makeWithLocalMatrix(localMatrix)
188*c8dee2aaSAndroid Build Coastguard Worker                             : bitmapShader);
189*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
190*c8dee2aaSAndroid Build Coastguard Worker 
191*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
192*c8dee2aaSAndroid Build Coastguard Worker     }
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar   fTileSize;
195*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar   fSceneSize;
196*c8dee2aaSAndroid Build Coastguard Worker     const float      fAlpha;
197*c8dee2aaSAndroid Build Coastguard Worker     const bool       fUseLocalMatrixWrapper;
198*c8dee2aaSAndroid Build Coastguard Worker 
199*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkPicture> fPicture;
200*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap         fBitmap;
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = GM;
203*c8dee2aaSAndroid Build Coastguard Worker };
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PictureShaderGM(50, 100);)
206*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PictureShaderGM(50, 100, true);)
207*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PictureShaderGM(50, 100, false, 0.25f);)
208*c8dee2aaSAndroid Build Coastguard Worker 
209*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
210*c8dee2aaSAndroid Build Coastguard Worker     // https://code.google.com/p/skia/issues/detail?id=3398
211*c8dee2aaSAndroid Build Coastguard Worker     SkRect tile = SkRect::MakeWH(100, 100);
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     SkPictureRecorder recorder;
214*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* c = recorder.beginRecording(tile);
215*c8dee2aaSAndroid Build Coastguard Worker 
216*c8dee2aaSAndroid Build Coastguard Worker     SkRect r = tile;
217*c8dee2aaSAndroid Build Coastguard Worker     r.inset(4, 4);
218*c8dee2aaSAndroid Build Coastguard Worker     SkPaint p;
219*c8dee2aaSAndroid Build Coastguard Worker     p.setColor(ToolUtils::color_to_565(0xFF303F9F));  // dark blue
220*c8dee2aaSAndroid Build Coastguard Worker     c->drawRect(r, p);
221*c8dee2aaSAndroid Build Coastguard Worker     p.setColor(ToolUtils::color_to_565(0xFFC5CAE9));  // light blue
222*c8dee2aaSAndroid Build Coastguard Worker     p.setStrokeWidth(10);
223*c8dee2aaSAndroid Build Coastguard Worker     c->drawLine(20, 20, 80, 80, p);
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker     p.setColor(ToolUtils::color_to_565(0xFF8BC34A));  // green
228*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawPaint(p);
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker     canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
231*c8dee2aaSAndroid Build Coastguard Worker     p.setColor(0xFFB6B6B6);  // gray
232*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawPaint(p);
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker     p.setShader(picture->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
235*c8dee2aaSAndroid Build Coastguard Worker                                     SkFilterMode::kNearest));
236*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawPaint(p);
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(pictureshader_persp, canvas, 215, 110) {
240*c8dee2aaSAndroid Build Coastguard Worker     enum class DrawStrategy {
241*c8dee2aaSAndroid Build Coastguard Worker         kDirect,
242*c8dee2aaSAndroid Build Coastguard Worker         kPictureShader,
243*c8dee2aaSAndroid Build Coastguard Worker     };
244*c8dee2aaSAndroid Build Coastguard Worker 
__anon510b76250202(SkCanvas* canvas, sk_sp<SkPicture> picture, DrawStrategy strategy) 245*c8dee2aaSAndroid Build Coastguard Worker     auto drawPicture = [](SkCanvas* canvas, sk_sp<SkPicture> picture, DrawStrategy strategy) {
246*c8dee2aaSAndroid Build Coastguard Worker         // Only want local upper 50x50 of 'picture' before we apply decal (or clip)
247*c8dee2aaSAndroid Build Coastguard Worker         SkRect bounds = {0.f, 0.f, 50.f, 50.f};
248*c8dee2aaSAndroid Build Coastguard Worker         switch(strategy) {
249*c8dee2aaSAndroid Build Coastguard Worker             case DrawStrategy::kDirect: {
250*c8dee2aaSAndroid Build Coastguard Worker                 canvas->clipRect(bounds, true);
251*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawPicture(picture);
252*c8dee2aaSAndroid Build Coastguard Worker                 break; }
253*c8dee2aaSAndroid Build Coastguard Worker             case DrawStrategy::kPictureShader: {
254*c8dee2aaSAndroid Build Coastguard Worker                 SkPaint paint;
255*c8dee2aaSAndroid Build Coastguard Worker                 paint.setShader(picture->makeShader(SkTileMode::kDecal, SkTileMode::kDecal,
256*c8dee2aaSAndroid Build Coastguard Worker                                                     SkFilterMode::kLinear, nullptr, &bounds));
257*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawRect({0.f, 0.f, 50.f, 50.f}, paint);
258*c8dee2aaSAndroid Build Coastguard Worker                 break; }
259*c8dee2aaSAndroid Build Coastguard Worker         }
260*c8dee2aaSAndroid Build Coastguard Worker     };
261*c8dee2aaSAndroid Build Coastguard Worker 
__anon510b76250302() 262*c8dee2aaSAndroid Build Coastguard Worker     auto picture = []() {
263*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkTypeface> typeface = ToolUtils::DefaultPortableTypeface();
264*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(typeface);
265*c8dee2aaSAndroid Build Coastguard Worker         SkFont font;
266*c8dee2aaSAndroid Build Coastguard Worker         font.setTypeface(typeface);
267*c8dee2aaSAndroid Build Coastguard Worker         font.setHinting(SkFontHinting::kNormal);
268*c8dee2aaSAndroid Build Coastguard Worker         font.setSize(8.f);
269*c8dee2aaSAndroid Build Coastguard Worker 
270*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
271*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorGREEN);
272*c8dee2aaSAndroid Build Coastguard Worker         SkPictureRecorder recorder;
273*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas* record_canvas = recorder.beginRecording({0, 0, 100, 100});
274*c8dee2aaSAndroid Build Coastguard Worker         record_canvas->drawTextBlob(SkTextBlob::MakeFromString("Hamburgefons", font),
275*c8dee2aaSAndroid Build Coastguard Worker                                     0, 16.f, paint);
276*c8dee2aaSAndroid Build Coastguard Worker         return recorder.finishRecordingAsPicture();
277*c8dee2aaSAndroid Build Coastguard Worker     }();
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker     SkM44 m;
280*c8dee2aaSAndroid Build Coastguard Worker     m.preScale(2.f, 2.f);
281*c8dee2aaSAndroid Build Coastguard Worker     SkM44 persp = SkM44::Perspective(0.01f, 10.f, SK_ScalarPI / 3.f);
282*c8dee2aaSAndroid Build Coastguard Worker     persp.preTranslate(0.f, 5.f, -0.1f);
283*c8dee2aaSAndroid Build Coastguard Worker     persp.preConcat(SkM44::Rotate({0.f, 1.f, 0.f}, 0.008f));
284*c8dee2aaSAndroid Build Coastguard Worker     m.postConcat(persp);
285*c8dee2aaSAndroid Build Coastguard Worker 
286*c8dee2aaSAndroid Build Coastguard Worker     canvas->clear(SK_ColorBLACK);
287*c8dee2aaSAndroid Build Coastguard Worker     canvas->translate(5.f, 5.f);
288*c8dee2aaSAndroid Build Coastguard Worker     for (auto strategy : { DrawStrategy::kDirect,
289*c8dee2aaSAndroid Build Coastguard Worker                            DrawStrategy::kPictureShader }) {
290*c8dee2aaSAndroid Build Coastguard Worker         canvas->save();
291*c8dee2aaSAndroid Build Coastguard Worker 
292*c8dee2aaSAndroid Build Coastguard Worker         SkPaint outline;
293*c8dee2aaSAndroid Build Coastguard Worker         outline.setColor(SK_ColorWHITE);
294*c8dee2aaSAndroid Build Coastguard Worker         outline.setStyle(SkPaint::kStroke_Style);
295*c8dee2aaSAndroid Build Coastguard Worker         outline.setStrokeWidth(1.f);
296*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect({-1, -1, 101, 101}, outline);
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker         canvas->clipRect({0, 0, 100, 100});
299*c8dee2aaSAndroid Build Coastguard Worker         canvas->concat(m);
300*c8dee2aaSAndroid Build Coastguard Worker 
301*c8dee2aaSAndroid Build Coastguard Worker         drawPicture(canvas, picture, strategy);
302*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(105.f, 0.f);
305*c8dee2aaSAndroid Build Coastguard Worker     }
306*c8dee2aaSAndroid Build Coastguard Worker }
307