Flutter Engine
The Flutter Engine
arithmode.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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"
11#include "include/core/SkFont.h"
17#include "include/core/SkRect.h"
21#include "include/core/SkSize.h"
30#include "tools/ToolUtils.h"
32
33#include <utility>
34
35static sk_sp<SkImage> make_src(int w, int h) {
37 SkCanvas* canvas = surface->getCanvas();
38
40 SkPoint pts[] = { {0, 0}, {SkIntToScalar(w), SkIntToScalar(h)} };
41 SkColor colors[] = {
44 };
47 canvas->drawPaint(paint);
48 return surface->makeImageSnapshot();
49}
50
51static sk_sp<SkImage> make_dst(int w, int h) {
53 SkCanvas* canvas = surface->getCanvas();
54
56 SkPoint pts[] = { {0, SkIntToScalar(h)}, {SkIntToScalar(w), 0} };
57 SkColor colors[] = {
60 };
63 canvas->drawPaint(paint);
64 return surface->makeImageSnapshot();
65}
66
67static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
71 paint.setAntiAlias(true);
72 for (int i = 0; i < 4; ++i) {
73 SkString str;
74 str.appendScalar(k[i]);
75 SkScalar width = font.measureText(str.c_str(), str.size(), SkTextEncoding::kUTF8);
76 canvas->drawString(str, x, y + font.getSize(), font, paint);
77 x += width + SkIntToScalar(10);
78 }
79}
80
81class ArithmodeGM : public skiagm::GM {
82 SkString getName() const override { return SkString("arithmode"); }
83
84 SkISize getISize() override { return {640, 572}; }
85
86 void onDraw(SkCanvas* canvas) override {
87 constexpr int WW = 100,
88 HH = 32;
89
90 sk_sp<SkImage> src = make_src(WW, HH);
91 sk_sp<SkImage> dst = make_dst(WW, HH);
94
95 constexpr SkScalar one = SK_Scalar1;
96 constexpr SkScalar K[] = {
97 0, 0, 0, 0,
98 0, 0, 0, one,
99 0, one, 0, 0,
100 0, 0, one, 0,
101 0, one, one, 0,
102 0, one, -one, 0,
103 0, one/2, one/2, 0,
104 0, one/2, one/2, one/4,
105 0, one/2, one/2, -one/4,
106 one/4, one/2, one/2, 0,
107 -one/4, one/2, one/2, 0,
108 };
109
110 const SkScalar* k = K;
111 const SkScalar* stop = k + std::size(K);
112 // Many of the Arithmetic filters have a 4th coefficient that's not zero, which means they
113 // affect transparent black. 'rect' is used as a crop filter to make sure they don't
114 // overwrite each other.
115 const SkRect rect = SkRect::MakeWH(WW, HH);
116 SkScalar gap = SkIntToScalar(WW + 20);
117 while (k < stop) {
118 {
119 SkAutoCanvasRestore acr(canvas, true);
120 canvas->drawImage(src, 0, 0);
121 canvas->translate(gap, 0);
122 canvas->drawImage(dst, 0, 0);
123 canvas->translate(gap, 0);
125 paint.setImageFilter(SkImageFilters::Arithmetic(k[0], k[1], k[2], k[3], true,
126 dstFilter, srcFilter, rect));
127 canvas->saveLayer(nullptr, &paint);
128 canvas->restore();
129
130 canvas->translate(gap, 0);
131 show_k_text(canvas, 0, 0, k);
132 }
133
134 k += 4;
135 canvas->translate(0, HH + 12);
136 }
137
138 // Draw two special cases to test enforcePMColor. In these cases, we
139 // draw the dst bitmap twice, the first time it is halved and inverted,
140 // leading to invalid premultiplied colors. If we enforcePMColor, these
141 // invalid values should be clamped, and will not contribute to the
142 // second draw.
143 for (int i = 0; i < 2; i++) {
144 const bool enforcePMColor = (i == 0);
145
146 {
147 SkAutoCanvasRestore acr(canvas, true);
148 canvas->translate(gap, 0);
149 canvas->drawImage(dst, 0, 0);
150 canvas->translate(gap, 0);
151
153 SkImageFilters::Arithmetic(0, 0, -one / 2, 1, enforcePMColor, dstFilter,
154 nullptr, nullptr);
155 SkPaint p;
156 p.setImageFilter(SkImageFilters::Arithmetic(0, one / 2, -one, 1, true,
157 std::move(bg), dstFilter, rect));
158 canvas->saveLayer(nullptr, &p);
159 canvas->restore();
160 canvas->translate(gap, 0);
161
162 // Label
164 SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
165 canvas->drawString(str, 0, font.getSize(), font, SkPaint());
166 }
167 canvas->translate(0, HH + 12);
168 }
169 }
170
171private:
172 using INHERITED = GM;
173};
174DEF_GM( return new ArithmodeGM; )
175
176///////////////////////////////////////////////////////////////////////////////
177
178#include "include/effects/SkBlenders.h"
179
181 float fK1, fK2, fK3, fK4;
182 sk_sp<SkImage> fSrc, fDst, fChecker;
183 sk_sp<SkShader> fSrcShader, fDstShader;
184 sk_sp<SkRuntimeEffect> fRuntimeEffect;
185
186 SkString getName() const override { return SkString("arithmode_blender"); }
187
188 static constexpr int W = 200;
189 static constexpr int H = 200;
190
191 SkISize getISize() override { return {(W + 30) * 2, (H + 30) * 4}; }
192
193 void onOnceBeforeDraw() override {
194 // Prepare a runtime effect for this blend.
195 static constexpr char kShader[] = R"(
196 uniform shader srcImage;
197 uniform shader dstImage;
198 uniform blender arithBlend;
199 half4 main(float2 xy) {
200 return arithBlend.eval(srcImage.eval(xy), dstImage.eval(xy));
201 }
202 )";
203 auto [effect, error] = SkRuntimeEffect::MakeForShader(SkString(kShader));
204 SkASSERT(effect);
205 fRuntimeEffect = effect;
206
207 // Start with interesting K-values, in case we're drawn without calling onAnimate().
208 fK1 = -0.25f;
209 fK2 = 0.25f;
210 fK3 = 0.25f;
211 fK4 = 0;
212
213 fSrc = make_src(W, H);
214 fDst = make_dst(W, H);
216 fDstShader = fDst->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
217
218 fChecker = ToolUtils::create_checkerboard_image(W, H, 0xFFBBBBBB, 0xFFEEEEEE, 8);
219 }
220
221 bool onAnimate(double nanos) override {
222 double theta = nanos * 1e-6 * 0.001;
223 fK1 = sin(theta + 0) * 0.25;
224 fK2 = cos(theta + 1) * 0.25;
225 fK3 = sin(theta + 2) * 0.25;
226 fK4 = 0.5;
227 return true;
228 }
229
230 void onDraw(SkCanvas* canvas) override {
231 const SkRect rect = SkRect::MakeWH(W, H);
232
233 canvas->drawImage(fSrc, 10, 10);
234 canvas->drawImage(fDst, 10, 10 + H + 10);
235
237 sk_sp<SkBlender> blender = SkBlenders::Arithmetic(fK1, fK2, fK3, fK4,
238 /*enforcePremul=*/true);
239 canvas->translate(10 + W + 10, 10);
240
241 // All three images drawn below should appear identical.
242 // Draw via blend step
243 SkPaint blenderPaint;
244 canvas->drawImage(fChecker, 0, 0);
245 canvas->saveLayer(&rect, nullptr);
246 canvas->drawImage(fDst, 0, 0);
247 blenderPaint.setBlender(blender);
248 canvas->drawImage(fSrc, 0, 0, sampling, &blenderPaint);
249 canvas->restore();
250
251 canvas->translate(0, 10 + H);
252
253 // Draw via SkImageFilters::Blend (should appear the same as above)
254 SkPaint imageFilterPaint;
255 canvas->drawImage(fChecker, 0, 0);
256 imageFilterPaint.setImageFilter(
257 SkImageFilters::Blend(blender,
258 /*background=*/nullptr,
259 /*foreground=*/SkImageFilters::Image(fSrc, sampling)));
260 canvas->drawImage(fDst, 0, 0, sampling, &imageFilterPaint);
261
262 canvas->translate(0, 10 + H);
263
264 // Draw via SkShaders::Blend (should still appear the same as above)
265 SkPaint shaderBlendPaint;
266 canvas->drawImage(fChecker, 0, 0);
267 shaderBlendPaint.setShader(SkShaders::Blend(blender, fDstShader, fSrcShader));
268 canvas->drawRect(rect, shaderBlendPaint);
269
270 canvas->translate(0, 10 + H);
271
272 // Draw via runtime effect (should still appear the same as above)
273 SkPaint runtimePaint;
274 canvas->drawImage(fChecker, 0, 0);
275 SkRuntimeEffect::ChildPtr children[] = {fSrcShader, fDstShader, blender};
276 runtimePaint.setShader(fRuntimeEffect->makeShader(/*uniforms=*/{}, children));
277 canvas->drawRect(rect, runtimePaint);
278 }
279
280private:
281 using INHERITED = GM;
282};
283DEF_GM( return new ArithmodeBlenderGM; )
SkRect fDst
Definition: LatticeOp.cpp:381
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorYELLOW
Definition: SkColor.h:139
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
@ kUTF8
uses bytes to represent UTF-8 or ASCII
#define SK_Scalar1
Definition: SkScalar.h:18
#define SkIntToScalar(x)
Definition: SkScalar.h:57
#define W
Definition: aaa.cpp:17
static sk_sp< SkImage > make_src(int w, int h)
Definition: arithmode.cpp:35
static sk_sp< SkImage > make_dst(int w, int h)
Definition: arithmode.cpp:51
static void show_k_text(SkCanvas *canvas, SkScalar x, SkScalar y, const SkScalar k[])
Definition: arithmode.cpp:67
static sk_sp< SkBlender > Arithmetic(float k1, float k2, float k3, float k4, bool enforcePremul)
Definition: SkBlenders.cpp:20
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawPaint(const SkPaint &paint)
Definition: SkCanvas.cpp:1668
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
Definition: SkFont.h:35
@ kAntiAlias
may have transparent pixels on glyph edges
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkImageFilter > Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
static sk_sp< SkImageFilter > Blend(SkBlendMode mode, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground=nullptr, const CropRect &cropRect={})
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
void setShader(sk_sp< SkShader > shader)
void setBlender(sk_sp< SkBlender > blender)
Definition: SkPaint.cpp:155
sk_sp< SkShader > makeShader(sk_sp< const SkData > uniforms, sk_sp< SkShader > children[], size_t childCount, const SkMatrix *localMatrix=nullptr) const
static Result MakeForShader(SkString sksl, const Options &)
size_t size() const
Definition: SkString.h:131
void appendScalar(SkScalar value)
Definition: SkString.h:213
const char * c_str() const
Definition: SkString.h:133
Definition: gm.h:110
GM(SkColor backgroundColor=SK_ColorWHITE)
Definition: gm.cpp:81
const Paint & paint
Definition: color_source.cc:38
static const int K
Definition: daa.cpp:21
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
const uint8_t uint32_t uint32_t GError ** error
#define DEF_GM(CODE)
Definition: gm.h:40
double y
double x
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
PODArray< SkColor > colors
Definition: SkRecords.h:276
SkSamplingOptions sampling
Definition: SkRecords.h:337
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
sk_sp< SkTypeface > DefaultPortableTypeface()
sk_sp< SkImage > create_checkerboard_image(int w, int h, SkColor c1, SkColor c2, int checkSize)
Definition: ToolUtils.cpp:168
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
font
Font Metadata and Metrics.
dst
Definition: cp.py:12
SkSamplingOptions(SkFilterMode::kLinear))
SkScalar w
SkScalar h
int32_t width
Definition: SkMD5.cpp:130
Definition: SkSize.h:16
static SkImageInfo MakeN32Premul(int width, int height)
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609