1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 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/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.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/SkSurface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "tools/GpuToolUtils.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "tools/timer/TimeUtils.h"
29*c8dee2aaSAndroid Build Coastguard Worker
make_image(SkCanvas * rootCanvas)30*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_image(SkCanvas* rootCanvas) {
31*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kSize = 50;
32*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(kSize, kSize);
33*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(info));
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
36*c8dee2aaSAndroid Build Coastguard Worker p.setAntiAlias(true);
37*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorGREEN);
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawCircle(kSize / 2, kSize / 2, kSize / 2, p);
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
42*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorRED);
43*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawLine(kSize * .25f, kSize * .50f, kSize * .75f, kSize * .50f, p);
44*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawLine(kSize * .50f, kSize * .25f, kSize * .50f, kSize * .75f, p);
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img = surface->makeImageSnapshot();
47*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::MakeTextureImage(rootCanvas, std::move(img));
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) {
51*c8dee2aaSAndroid Build Coastguard Worker auto image = make_image(canvas);
52*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
53*c8dee2aaSAndroid Build Coastguard Worker return;
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker using FactoryT = sk_sp<SkShader> (*)(const sk_sp<SkImage>&,
57*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& inner,
58*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& outer);
59*c8dee2aaSAndroid Build Coastguard Worker static const FactoryT gFactories[] = {
60*c8dee2aaSAndroid Build Coastguard Worker // SkLocalMatrixShader(SkImageShader(inner), outer)
__anon55eb75a90102() 61*c8dee2aaSAndroid Build Coastguard Worker [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
62*c8dee2aaSAndroid Build Coastguard Worker return img->makeShader(SkSamplingOptions(), inner)->makeWithLocalMatrix(outer);
63*c8dee2aaSAndroid Build Coastguard Worker },
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker // SkLocalMatrixShader(SkLocalMatrixShader(SkImageShader(I), inner), outer)
__anon55eb75a90202() 66*c8dee2aaSAndroid Build Coastguard Worker [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
67*c8dee2aaSAndroid Build Coastguard Worker return img->makeShader(SkSamplingOptions())->makeWithLocalMatrix(inner)->makeWithLocalMatrix(outer);
68*c8dee2aaSAndroid Build Coastguard Worker },
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Worker // SkLocalMatrixShader(SkComposeShader(SkImageShader(inner)), outer)
__anon55eb75a90302() 71*c8dee2aaSAndroid Build Coastguard Worker [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
72*c8dee2aaSAndroid Build Coastguard Worker return SkShaders::Blend(SkBlendMode::kSrcOver,
73*c8dee2aaSAndroid Build Coastguard Worker SkShaders::Color(SK_ColorTRANSPARENT),
74*c8dee2aaSAndroid Build Coastguard Worker img->makeShader(SkSamplingOptions(), inner))
75*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(outer);
76*c8dee2aaSAndroid Build Coastguard Worker },
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker // SkLocalMatrixShader(SkComposeShader(SkLocalMatrixShader(SkImageShader(I), inner)), outer)
__anon55eb75a90402() 79*c8dee2aaSAndroid Build Coastguard Worker [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
80*c8dee2aaSAndroid Build Coastguard Worker return SkShaders::Blend(SkBlendMode::kSrcOver,
81*c8dee2aaSAndroid Build Coastguard Worker SkShaders::Color(SK_ColorTRANSPARENT),
82*c8dee2aaSAndroid Build Coastguard Worker img->makeShader(SkSamplingOptions())->makeWithLocalMatrix(inner))
83*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(outer);
84*c8dee2aaSAndroid Build Coastguard Worker },
85*c8dee2aaSAndroid Build Coastguard Worker };
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker static const auto outer = SkMatrix::Scale(2, 2),
88*c8dee2aaSAndroid Build Coastguard Worker inner = SkMatrix::Translate(20, 20);
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker SkPaint border;
91*c8dee2aaSAndroid Build Coastguard Worker border.setAntiAlias(true);
92*c8dee2aaSAndroid Build Coastguard Worker border.setStyle(SkPaint::kStroke_Style);
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker auto rect = SkRect::Make(image->bounds());
95*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(SkMatrix::Concat(outer, inner).mapRect(&rect));
96*c8dee2aaSAndroid Build Coastguard Worker
__anon55eb75a90502() 97*c8dee2aaSAndroid Build Coastguard Worker const auto drawColumn = [&]() {
98*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
99*c8dee2aaSAndroid Build Coastguard Worker for (const auto& f : gFactories) {
100*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
101*c8dee2aaSAndroid Build Coastguard Worker p.setShader(f(image, inner, outer));
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(rect, p);
104*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(rect, border);
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, rect.height() * 1.5f);
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker };
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker drawColumn();
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker {
113*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
114*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, rect.height() * std::size(gFactories) * 1.5f);
115*c8dee2aaSAndroid Build Coastguard Worker drawColumn();
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(rect.width() * 1.5f, 0);
119*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(2, 2);
120*c8dee2aaSAndroid Build Coastguard Worker drawColumn();
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(localmatrixshader_persp, canvas, 542, 266) {
124*c8dee2aaSAndroid Build Coastguard Worker auto image = ToolUtils::GetResourceAsImage("images/yellow_rose.png");
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker SkBitmap downsized;
127*c8dee2aaSAndroid Build Coastguard Worker downsized.allocPixels(image->imageInfo().makeWH(128, 128));
128*c8dee2aaSAndroid Build Coastguard Worker image->scalePixels(downsized.pixmap(), SkSamplingOptions(SkFilterMode::kLinear));
129*c8dee2aaSAndroid Build Coastguard Worker image = downsized.asImage();
130*c8dee2aaSAndroid Build Coastguard Worker SkRect imgRect = SkRect::MakeIWH(image->width(), image->height());
131*c8dee2aaSAndroid Build Coastguard Worker
132*c8dee2aaSAndroid Build Coastguard Worker // scale matrix
133*c8dee2aaSAndroid Build Coastguard Worker SkMatrix scale = SkMatrix::Scale(1.f / 5.f, 1.f / 5.f);
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker // perspective matrix
136*c8dee2aaSAndroid Build Coastguard Worker SkPoint src[4];
137*c8dee2aaSAndroid Build Coastguard Worker imgRect.toQuad(src);
138*c8dee2aaSAndroid Build Coastguard Worker SkPoint dst[4] = {{0, 10.f},
139*c8dee2aaSAndroid Build Coastguard Worker {image->width() + 28.f, -100.f},
140*c8dee2aaSAndroid Build Coastguard Worker {image->width() - 28.f, image->height() + 100.f},
141*c8dee2aaSAndroid Build Coastguard Worker {0.f, image->height() - 10.f}};
142*c8dee2aaSAndroid Build Coastguard Worker SkMatrix persp;
143*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(persp.setPolyToPoly(src, dst, 4));
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker // combined persp * scale
146*c8dee2aaSAndroid Build Coastguard Worker SkMatrix perspScale = SkMatrix::Concat(persp, scale);
147*c8dee2aaSAndroid Build Coastguard Worker
__anon55eb75a90602(sk_sp<SkShader> shader, bool applyPerspToCTM) 148*c8dee2aaSAndroid Build Coastguard Worker auto draw = [&](sk_sp<SkShader> shader, bool applyPerspToCTM) {
149*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
150*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(imgRect);
151*c8dee2aaSAndroid Build Coastguard Worker if (applyPerspToCTM) {
152*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(persp);
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker SkPaint imgShaderPaint;
155*c8dee2aaSAndroid Build Coastguard Worker imgShaderPaint.setShader(std::move(shader));
156*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(imgShaderPaint);
157*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
158*c8dee2aaSAndroid Build Coastguard Worker
159*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(10.f + image->width(), 0.f); // advance
160*c8dee2aaSAndroid Build Coastguard Worker };
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker // SkImageShader
163*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
164*c8dee2aaSAndroid Build Coastguard Worker // 4 variants that all attempt to apply sample at persp * scale w/ an image shader
165*c8dee2aaSAndroid Build Coastguard Worker // 1. scale provided to SkImage::makeShader(...) but drawn with persp
166*c8dee2aaSAndroid Build Coastguard Worker auto s1 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
167*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &scale);
168*c8dee2aaSAndroid Build Coastguard Worker draw(s1, true);
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker // 2. scale provided to SkImage::makeShader, then wrapped in persp makeWithLocalMatrix
171*c8dee2aaSAndroid Build Coastguard Worker // These post-concat, so it ends up as persp * scale.
172*c8dee2aaSAndroid Build Coastguard Worker auto s2 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
173*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &scale)
174*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(persp);
175*c8dee2aaSAndroid Build Coastguard Worker draw(s2, false);
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker // 3. Providing pre-computed persp*scale to SkImage::makeShader()
178*c8dee2aaSAndroid Build Coastguard Worker auto s3 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
179*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &perspScale);
180*c8dee2aaSAndroid Build Coastguard Worker draw(s3, false);
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
183*c8dee2aaSAndroid Build Coastguard Worker auto s4 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions())
184*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(perspScale);
185*c8dee2aaSAndroid Build Coastguard Worker draw(s4, false);
186*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0.f, 10.f + image->height()); // advance to next row
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker // SkGradientShader
191*c8dee2aaSAndroid Build Coastguard Worker const SkColor kGradColors[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
192*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
193*c8dee2aaSAndroid Build Coastguard Worker // 1. scale provided to Make, drawn with persp
194*c8dee2aaSAndroid Build Coastguard Worker auto g1 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
195*c8dee2aaSAndroid Build Coastguard Worker imgRect.width() / 2.f, kGradColors, nullptr, 2,
196*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat, 0, &scale);
197*c8dee2aaSAndroid Build Coastguard Worker draw(g1, true);
198*c8dee2aaSAndroid Build Coastguard Worker
199*c8dee2aaSAndroid Build Coastguard Worker // 2. scale provided to Make, then wrapped with makeWithLocalMatrix (post-concat as before).
200*c8dee2aaSAndroid Build Coastguard Worker auto g2 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
201*c8dee2aaSAndroid Build Coastguard Worker imgRect.width() / 2.f, kGradColors, nullptr, 2,
202*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat, 0, &scale)
203*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(persp);
204*c8dee2aaSAndroid Build Coastguard Worker draw(g2, false);
205*c8dee2aaSAndroid Build Coastguard Worker
206*c8dee2aaSAndroid Build Coastguard Worker // 3. Provide per-computed persp*scale to Make
207*c8dee2aaSAndroid Build Coastguard Worker auto g3 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
208*c8dee2aaSAndroid Build Coastguard Worker imgRect.width() / 2.f, kGradColors, nullptr, 2,
209*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat, 0, &perspScale);
210*c8dee2aaSAndroid Build Coastguard Worker draw(g3, false);
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
213*c8dee2aaSAndroid Build Coastguard Worker auto g4 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
214*c8dee2aaSAndroid Build Coastguard Worker imgRect.width() / 2.f, kGradColors, nullptr, 2,
215*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat)
216*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(perspScale);
217*c8dee2aaSAndroid Build Coastguard Worker draw(g4, false);
218*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
222*c8dee2aaSAndroid Build Coastguard Worker class LocalMatrixOrder : public GM {
223*c8dee2aaSAndroid Build Coastguard Worker public:
LocalMatrixOrder()224*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixOrder() {}
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const227*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("localmatrix_order"); }
228*c8dee2aaSAndroid Build Coastguard Worker
getISize()229*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(500, 500); }
230*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()231*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
232*c8dee2aaSAndroid Build Coastguard Worker auto mandrill = ToolUtils::GetResourceAsImage("images/mandrill_256.png"); // 256x256
233*c8dee2aaSAndroid Build Coastguard Worker auto example5 = ToolUtils::GetResourceAsImage("images/example_5.png"); // 128x128
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker auto mshader = mandrill->makeShader(
236*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
237*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
238*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kNearest,
239*c8dee2aaSAndroid Build Coastguard Worker SkMatrix::RotateDeg(45, {128, 128})); // rotate about center
240*c8dee2aaSAndroid Build Coastguard Worker auto eshader = example5->makeShader(
241*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
242*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
243*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kNearest,
244*c8dee2aaSAndroid Build Coastguard Worker SkMatrix::Scale(2, 2)); // make same size as mandrill and...
245*c8dee2aaSAndroid Build Coastguard Worker // ... rotate about center
246*c8dee2aaSAndroid Build Coastguard Worker eshader = eshader->makeWithLocalMatrix(SkMatrix::RotateDeg(45, {128, 128}));
247*c8dee2aaSAndroid Build Coastguard Worker
248*c8dee2aaSAndroid Build Coastguard Worker // blend the two rotated and aligned images.
249*c8dee2aaSAndroid Build Coastguard Worker fShader = SkShaders::Blend(SkBlendMode::kModulate, mshader, eshader);
250*c8dee2aaSAndroid Build Coastguard Worker }
251*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)252*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
253*c8dee2aaSAndroid Build Coastguard Worker // Rotate fShader about the canvas center
254*c8dee2aaSAndroid Build Coastguard Worker auto center = SkRect::Make(canvas->imageInfo().bounds()).center();
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker // viewer can insert a dpi scaling matrix. Make the animation always rotate about the device
257*c8dee2aaSAndroid Build Coastguard Worker // center.
258*c8dee2aaSAndroid Build Coastguard Worker if (auto ictm = canvas->getTotalMatrix(); ictm.invert(&ictm)) {
259*c8dee2aaSAndroid Build Coastguard Worker center = ictm.mapPoint(center);
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker
262*c8dee2aaSAndroid Build Coastguard Worker auto shader = fShader->makeWithLocalMatrix(SkMatrix::RotateDeg(fAngle, center));
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
265*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(shader);
266*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
267*c8dee2aaSAndroid Build Coastguard Worker }
268*c8dee2aaSAndroid Build Coastguard Worker
onAnimate(double nanos)269*c8dee2aaSAndroid Build Coastguard Worker bool onAnimate(double nanos) override {
270*c8dee2aaSAndroid Build Coastguard Worker fAngle = TimeUtils::NanosToSeconds(nanos) * 5.f;
271*c8dee2aaSAndroid Build Coastguard Worker return true;
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fShader;
275*c8dee2aaSAndroid Build Coastguard Worker float fAngle = 0.f;
276*c8dee2aaSAndroid Build Coastguard Worker };
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new LocalMatrixOrder;)
279*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
280