Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
localmatrixshader.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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"
17#include "include/core/SkRect.h"
24#include "tools/DecodeUtils.h"
25#include "tools/GpuToolUtils.h"
26#include "tools/Resources.h"
27#include "tools/ToolUtils.h"
29
30static sk_sp<SkImage> make_image(SkCanvas* rootCanvas) {
31 static constexpr SkScalar kSize = 50;
34
35 SkPaint p;
36 p.setAntiAlias(true);
37 p.setColor(SK_ColorGREEN);
38
39 surface->getCanvas()->drawCircle(kSize / 2, kSize / 2, kSize / 2, p);
40
41 p.setStyle(SkPaint::kStroke_Style);
42 p.setColor(SK_ColorRED);
43 surface->getCanvas()->drawLine(kSize * .25f, kSize * .50f, kSize * .75f, kSize * .50f, p);
44 surface->getCanvas()->drawLine(kSize * .50f, kSize * .25f, kSize * .50f, kSize * .75f, p);
45
46 sk_sp<SkImage> img = surface->makeImageSnapshot();
47 return ToolUtils::MakeTextureImage(rootCanvas, std::move(img));
48}
49
50DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) {
51 auto image = make_image(canvas);
52 if (!image) {
53 return;
54 }
55
56 using FactoryT = sk_sp<SkShader> (*)(const sk_sp<SkImage>&,
57 const SkMatrix& inner,
58 const SkMatrix& outer);
59 static const FactoryT gFactories[] = {
60 // SkLocalMatrixShader(SkImageShader(inner), outer)
61 [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
62 return img->makeShader(SkSamplingOptions(), inner)->makeWithLocalMatrix(outer);
63 },
64
65 // SkLocalMatrixShader(SkLocalMatrixShader(SkImageShader(I), inner), outer)
66 [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
67 return img->makeShader(SkSamplingOptions())->makeWithLocalMatrix(inner)->makeWithLocalMatrix(outer);
68 },
69
70 // SkLocalMatrixShader(SkComposeShader(SkImageShader(inner)), outer)
71 [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
74 img->makeShader(SkSamplingOptions(), inner))
75 ->makeWithLocalMatrix(outer);
76 },
77
78 // SkLocalMatrixShader(SkComposeShader(SkLocalMatrixShader(SkImageShader(I), inner)), outer)
79 [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
82 img->makeShader(SkSamplingOptions())->makeWithLocalMatrix(inner))
83 ->makeWithLocalMatrix(outer);
84 },
85 };
86
87 static const auto outer = SkMatrix::Scale(2, 2),
88 inner = SkMatrix::Translate(20, 20);
89
90 SkPaint border;
91 border.setAntiAlias(true);
93
94 auto rect = SkRect::Make(image->bounds());
95 SkAssertResult(SkMatrix::Concat(outer, inner).mapRect(&rect));
96
97 const auto drawColumn = [&]() {
98 SkAutoCanvasRestore acr(canvas, true);
99 for (const auto& f : gFactories) {
100 SkPaint p;
101 p.setShader(f(image, inner, outer));
102
103 canvas->drawRect(rect, p);
104 canvas->drawRect(rect, border);
105
106 canvas->translate(0, rect.height() * 1.5f);
107 }
108 };
109
110 drawColumn();
111
112 {
113 SkAutoCanvasRestore acr(canvas, true);
114 canvas->translate(0, rect.height() * std::size(gFactories) * 1.5f);
115 drawColumn();
116 }
117
118 canvas->translate(rect.width() * 1.5f, 0);
119 canvas->scale(2, 2);
120 drawColumn();
121}
122
123DEF_SIMPLE_GM(localmatrixshader_persp, canvas, 542, 266) {
124 auto image = ToolUtils::GetResourceAsImage("images/yellow_rose.png");
125
126 SkBitmap downsized;
127 downsized.allocPixels(image->imageInfo().makeWH(128, 128));
129 image = downsized.asImage();
130 SkRect imgRect = SkRect::MakeIWH(image->width(), image->height());
131
132 // scale matrix
133 SkMatrix scale = SkMatrix::Scale(1.f / 5.f, 1.f / 5.f);
134
135 // perspective matrix
136 SkPoint src[4];
137 imgRect.toQuad(src);
138 SkPoint dst[4] = {{0, 10.f},
139 {image->width() + 28.f, -100.f},
140 {image->width() - 28.f, image->height() + 100.f},
141 {0.f, image->height() - 10.f}};
142 SkMatrix persp;
144
145 // combined persp * scale
146 SkMatrix perspScale = SkMatrix::Concat(persp, scale);
147
148 auto draw = [&](sk_sp<SkShader> shader, bool applyPerspToCTM) {
149 canvas->save();
150 canvas->clipRect(imgRect);
151 if (applyPerspToCTM) {
152 canvas->concat(persp);
153 }
154 SkPaint imgShaderPaint;
155 imgShaderPaint.setShader(std::move(shader));
156 canvas->drawPaint(imgShaderPaint);
157 canvas->restore();
158
159 canvas->translate(10.f + image->width(), 0.f); // advance
160 };
161
162 // SkImageShader
163 canvas->save();
164 // 4 variants that all attempt to apply sample at persp * scale w/ an image shader
165 // 1. scale provided to SkImage::makeShader(...) but drawn with persp
168 draw(s1, true);
169
170 // 2. scale provided to SkImage::makeShader, then wrapped in persp makeWithLocalMatrix
171 // These post-concat, so it ends up as persp * scale.
174 ->makeWithLocalMatrix(persp);
175 draw(s2, false);
176
177 // 3. Providing pre-computed persp*scale to SkImage::makeShader()
179 SkSamplingOptions(), &perspScale);
180 draw(s3, false);
181
182 // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
184 ->makeWithLocalMatrix(perspScale);
185 draw(s4, false);
186 canvas->restore();
187
188 canvas->translate(0.f, 10.f + image->height()); // advance to next row
189
190 // SkGradientShader
191 const SkColor kGradColors[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
192 canvas->save();
193 // 1. scale provided to Make, drawn with persp
194 auto g1 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
195 imgRect.width() / 2.f, kGradColors, nullptr, 2,
197 draw(g1, true);
198
199 // 2. scale provided to Make, then wrapped with makeWithLocalMatrix (post-concat as before).
200 auto g2 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
201 imgRect.width() / 2.f, kGradColors, nullptr, 2,
203 ->makeWithLocalMatrix(persp);
204 draw(g2, false);
205
206 // 3. Provide per-computed persp*scale to Make
207 auto g3 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
208 imgRect.width() / 2.f, kGradColors, nullptr, 2,
209 SkTileMode::kRepeat, 0, &perspScale);
210 draw(g3, false);
211
212 // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
213 auto g4 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
214 imgRect.width() / 2.f, kGradColors, nullptr, 2,
216 ->makeWithLocalMatrix(perspScale);
217 draw(g4, false);
218 canvas->restore();
219}
220
221namespace skiagm {
222class LocalMatrixOrder : public GM {
223public:
225
226protected:
227 SkString getName() const override { return SkString("localmatrix_order"); }
228
229 SkISize getISize() override { return SkISize::Make(500, 500); }
230
231 void onOnceBeforeDraw() override {
232 auto mandrill = ToolUtils::GetResourceAsImage("images/mandrill_256.png"); // 256x256
233 auto example5 = ToolUtils::GetResourceAsImage("images/example_5.png"); // 128x128
234
235 auto mshader = mandrill->makeShader(
239 SkMatrix::RotateDeg(45, {128, 128})); // rotate about center
240 auto eshader = example5->makeShader(
244 SkMatrix::Scale(2, 2)); // make same size as mandrill and...
245 // ... rotate about center
246 eshader = eshader->makeWithLocalMatrix(SkMatrix::RotateDeg(45, {128, 128}));
247
248 // blend the two rotated and aligned images.
250 }
251
252 void onDraw(SkCanvas* canvas) override {
253 // Rotate fShader about the canvas center
254 auto center = SkRect::Make(canvas->imageInfo().bounds()).center();
255
256 // viewer can insert a dpi scaling matrix. Make the animation always rotate about the device
257 // center.
258 if (auto ictm = canvas->getTotalMatrix(); ictm.invert(&ictm)) {
259 center = ictm.mapPoint(center);
260 }
261
262 auto shader = fShader->makeWithLocalMatrix(SkMatrix::RotateDeg(fAngle, center));
263
265 paint.setShader(shader);
266 canvas->drawPaint(paint);
267 }
268
269 bool onAnimate(double nanos) override {
270 fAngle = TimeUtils::NanosToSeconds(nanos) * 5.f;
271 return true;
272 }
273
275 float fAngle = 0.f;
276};
277
278DEF_GM(return new LocalMatrixOrder;)
279} // namespace skiagm
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kModulate
r = s*d
@ kSrcOver
r = s + (1-sa)*d
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:258
sk_sp< SkImage > asImage() const
Definition: SkBitmap.cpp:645
const SkPixmap & pixmap() const
Definition: SkBitmap.h:133
void drawPaint(const SkPaint &paint)
Definition: SkCanvas.cpp:1668
SkMatrix getTotalMatrix() const
Definition: SkCanvas.cpp:1629
SkImageInfo imageInfo() const
Definition: SkCanvas.cpp:1206
static sk_sp< SkShader > MakeRadial(const SkPoint &center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
const SkImageInfo & imageInfo() const
Definition: SkImage.h:279
int width() const
Definition: SkImage.h:285
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
int height() const
Definition: SkImage.h:291
SkIRect bounds() const
Definition: SkImage.h:303
bool scalePixels(const SkPixmap &dst, const SkSamplingOptions &, CachingHint cachingHint=kAllow_CachingHint) const
Definition: SkImage.cpp:127
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix RotateDeg(SkScalar deg)
Definition: SkMatrix.h:104
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrix.h:1775
bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count)
Definition: SkMatrix.cpp:1385
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
void setStyle(Style style)
Definition: SkPaint.cpp:105
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setShader(sk_sp< SkShader > shader)
sk_sp< SkShader > makeWithLocalMatrix(const SkMatrix &) const
Definition: SkShader.cpp:26
Definition: gm.h:110
bool onAnimate(double nanos) override
void onDraw(SkCanvas *canvas) override
SkString getName() const override
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
constexpr int kSize
static sk_sp< SkImage > make_image(SkCanvas *rootCanvas)
DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
SK_API sk_sp< SkShader > Color(SkColor)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
static double NanosToSeconds(double nanos)
Definition: TimeUtils.h:22
sk_sp< SkImage > MakeTextureImage(SkCanvas *canvas, sk_sp< SkImage > orig)
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition: DecodeUtils.h:25
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
SkSamplingOptions(SkFilterMode::kLinear))
const Scalar scale
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
SkImageInfo makeWH(int newWidth, int newHeight) const
Definition: SkImageInfo.h:444
static SkImageInfo MakeN32Premul(int width, int height)
SkIRect bounds() const
Definition: SkImageInfo.h:427
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
void toQuad(SkPoint quad[4]) const
Definition: SkRect.cpp:50
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float centerY() const
Definition: SkRect.h:785
constexpr float width() const
Definition: SkRect.h:762
constexpr SkPoint center() const
Definition: SkRect.h:792