Flutter Engine
The Flutter Engine
PatchSlide.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
14#include "include/core/SkPath.h"
23#include "src/base/SkRandom.h"
24#include "src/base/SkTime.h"
25#include "src/base/SkUTF.h"
26#include "src/core/SkGeometry.h"
27#include "src/core/SkOSFile.h"
28#include "tools/DecodeUtils.h"
29#include "tools/Resources.h"
32#include "tools/viewer/Slide.h"
33
34namespace {
36 SkBitmap bm;
38 *size = SkIPoint{bm.width(), bm.height()};
40}
41
43 SkPoint pts[] = { { 0, 0, },
44 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
46 return SkGradientShader::MakeLinear(pts, colors, nullptr,
48}
49
50class Patch {
51public:
52 Patch() { sk_bzero(fPts, sizeof(fPts)); }
53 ~Patch() {}
54
55 void setPatch(const SkPoint pts[12]) {
56 memcpy(fPts, pts, 12 * sizeof(SkPoint));
57 fPts[12] = pts[0]; // the last shall be first
58 }
59 void setBounds(int w, int h) { fW = w; fH = h; }
60
61 void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
62 bool doTextures, bool doColors);
63
64private:
65 SkPoint fPts[13];
66 int fW, fH;
67};
68
69static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
70 SkScalar t = 0;
71 SkScalar dt = SK_Scalar1 / segs;
72
73 samples[0] = cubic[0];
74 for (int i = 1; i < segs; i++) {
75 t += dt;
76 SkEvalCubicAt(cubic, t, &samples[i], nullptr, nullptr);
77 }
78}
79
80static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
81 SkPoint* pt) {
82 const int TL = 0;
83 const int TR = nu;
84 const int BR = TR + nv;
85 const int BL = BR + nu;
86
87 SkScalar u = SkIntToScalar(iu) / nu;
88 SkScalar v = SkIntToScalar(iv) / nv;
89
90 SkScalar uv = u * v;
91 SkScalar Uv = (1 - u) * v;
92 SkScalar uV = u * (1 - v);
93 SkScalar UV = (1 - u) * (1 - v);
94
95 SkScalar x0 = UV * edge[TL].fX + uV * edge[TR].fX + Uv * edge[BL].fX + uv * edge[BR].fX;
96 SkScalar y0 = UV * edge[TL].fY + uV * edge[TR].fY + Uv * edge[BL].fY + uv * edge[BR].fY;
97
98 SkScalar x = (1 - v) * edge[TL+iu].fX + u * edge[TR+iv].fX +
99 v * edge[BR+nu-iu].fX + (1 - u) * edge[BL+nv-iv].fX - x0;
100 SkScalar y = (1 - v) * edge[TL+iu].fY + u * edge[TR+iv].fY +
101 v * edge[BR+nu-iu].fY + (1 - u) * edge[BL+nv-iv].fY - y0;
102 pt->set(x, y);
103}
104
105static SkColor make_color(SkScalar s, SkScalar t) {
107}
108
109void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
110 bool doTextures, bool doColors) {
111 if (nu < 1 || nv < 1) {
112 return;
113 }
114
115 int i, npts = (nu + nv) * 2;
116 std::unique_ptr<SkPoint[]> storage(new SkPoint[npts + 1]);
117 SkPoint* edge0 = storage.get();
118 SkPoint* edge1 = edge0 + nu;
119 SkPoint* edge2 = edge1 + nv;
120 SkPoint* edge3 = edge2 + nu;
121
122 // evaluate the edge points
123 eval_patch_edge(fPts + 0, edge0, nu);
124 eval_patch_edge(fPts + 3, edge1, nv);
125 eval_patch_edge(fPts + 6, edge2, nu);
126 eval_patch_edge(fPts + 9, edge3, nv);
127 edge3[nv] = edge0[0]; // the last shall be first
128
129 for (i = 0; i < npts; i++) {
130// canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
131 }
132
133 int row, vertCount = (nu + 1) * (nv + 1);
134 std::unique_ptr<SkPoint[]> vertStorage(new SkPoint[vertCount]);
135 SkPoint* verts = vertStorage.get();
136
137 // first row
138 memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
139 // rows
140 SkPoint* r = verts;
141 for (row = 1; row < nv; row++) {
142 r += nu + 1;
143 r[0] = edge3[nv - row];
144 for (int col = 1; col < nu; col++) {
145 eval_sheet(edge0, nu, nv, col, row, &r[col]);
146 }
147 r[nu] = edge1[row];
148 }
149 // last row
150 SkPoint* last = verts + nv * (nu + 1);
151 for (i = 0; i <= nu; i++) {
152 last[i] = edge2[nu - i];
153 }
154
155// canvas->drawPoints(verts, vertCount, paint);
156
157 int stripCount = (nu + 1) * 2;
158 std::unique_ptr<SkPoint[]> stripStorage(new SkPoint[stripCount * 2]);
159 std::unique_ptr<SkColor[]> colorStorage(new SkColor[stripCount]);
160 SkPoint* strip = stripStorage.get();
161 SkPoint* tex = strip + stripCount;
162 SkColor* colors = colorStorage.get();
163 SkScalar t = 0;
164 const SkScalar ds = SK_Scalar1 * fW / nu;
165 const SkScalar dt = SK_Scalar1 * fH / nv;
166 r = verts;
167 for (row = 0; row < nv; row++) {
168 SkPoint* upper = r;
169 SkPoint* lower = r + nu + 1;
170 r = lower;
171 SkScalar s = 0;
172 for (i = 0; i <= nu; i++) {
173 strip[i*2 + 0] = *upper++;
174 strip[i*2 + 1] = *lower++;
175 tex[i*2 + 0].set(s, t);
176 tex[i*2 + 1].set(s, t + dt);
177 colors[i*2 + 0] = make_color(s/fW, t/fH);
178 colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
179 s += ds;
180 }
181 t += dt;
183 strip, doTextures ? tex : nullptr,
184 doColors ? colors : nullptr),
186 }
187}
188
189static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
190 Patch* patch) {
191 SkAutoCanvasRestore ar(canvas, true);
192
193 patch->draw(canvas, paint, nu, nv, false, false);
194 canvas->translate(SkIntToScalar(180), 0);
195 patch->draw(canvas, paint, nu, nv, true, false);
196 canvas->translate(SkIntToScalar(180), 0);
197 patch->draw(canvas, paint, nu, nv, false, true);
198 canvas->translate(SkIntToScalar(180), 0);
199 patch->draw(canvas, paint, nu, nv, true, true);
200}
201
202static constexpr SkScalar DX = 20;
203static constexpr SkScalar DY = 0;
204static constexpr SkScalar kS = 50;
205static constexpr SkScalar kT = 40;
206
207struct PatchSlide : public ClickHandlerSlide {
208 sk_sp<SkShader> fShader0;
209 sk_sp<SkShader> fShader1;
210 SkScalar fAngle = 0;
211 SkIPoint fSize0 = {0, 0},
212 fSize1 = {0, 0};
213 SkPoint fPts[12] = {
214 {kS * 0, kT * 1},
215 {kS * 1, kT * 1},
216 {kS * 2, kT * 1},
217 {kS * 3, kT * 1},
218 {kS * 3, kT * 2},
219 {kS * 3, kT * 3},
220 {kS * 3, kT * 4},
221 {kS * 2, kT * 4},
222 {kS * 1, kT * 4},
223 {kS * 0, kT * 4},
224 {kS * 0, kT * 3},
225 {kS * 0, kT * 2},
226 };
227
228public:
229 PatchSlide() { fName = "Patch"; }
230
231 void load(SkScalar w, SkScalar h) override {
232 fShader0 = make_shader0(&fSize0);
233 fSize1 = fSize0;
234 if (fSize0.fX == 0 || fSize0.fY == 0) {
235 fSize1.set(2, 2);
236 }
237 fShader1 = make_shader1(fSize1);
238 }
239
240
241 void draw(SkCanvas* canvas) override {
242 canvas->clear(SK_ColorGRAY);
243
244 const int nu = 10;
245 const int nv = 10;
246
248 paint.setDither(true);
249
250 canvas->translate(DX, DY);
251
252 Patch patch;
253
254 paint.setShader(fShader0);
255 if (fSize0.fX == 0) {
256 fSize0.fX = 1;
257 }
258 if (fSize0.fY == 0) {
259 fSize0.fY = 1;
260 }
261 patch.setBounds(fSize0.fX, fSize0.fY);
262
263 patch.setPatch(fPts);
264 drawpatches(canvas, paint, nu, nv, &patch);
265
266 paint.setShader(nullptr);
267 paint.setAntiAlias(true);
268 paint.setStrokeWidth(SkIntToScalar(5));
270
271 canvas->translate(0, SkIntToScalar(300));
272
273 paint.setAntiAlias(false);
274 paint.setShader(fShader1);
275 {
276 SkMatrix m;
277 m.setSkew(1, 0);
278 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
279 }
280 {
281 SkMatrix m;
282 m.setRotate(fAngle);
283 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
284 }
285 patch.setBounds(fSize1.fX, fSize1.fY);
286 drawpatches(canvas, paint, nu, nv, &patch);
287 }
288
289 bool animate(double nanos) override {
290 fAngle = TimeUtils::Scaled(1e-9 * nanos, 60, 360);
291 return true;
292 }
293
294protected:
295 class PtClick : public Click {
296 public:
297 int fIndex;
298 PtClick(int index) : fIndex(index) {}
299 };
300
301 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
302 x -= DX;
303 y -= DY;
304 for (size_t i = 0; i < std::size(fPts); i++) {
305 if (hittest(fPts[i], x, y)) {
306 return new PtClick((int)i);
307 }
308 }
309 return nullptr;
310 }
311
312 bool onClick(Click* click) override {
313 fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX - DX, click->fCurr.fY - DY);
314 return true;
315 }
316
317private:
318 static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
319 return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
320 }
321};
322} // namespace
323DEF_SLIDE( return new PatchSlide(); )
324
325//////////////////////////////////////////////////////////////////////////////
326
327namespace {
328static sk_sp<SkVertices> make_verts(const SkPath& path, SkScalar width) {
329 auto meas = SkContourMeasureIter(path, false).next();
330 if (!meas) {
331 return nullptr;
332 }
333
334 const SkPoint src[2] = {
335 { 0, -width/2 }, { 0, width/2 },
336 };
338
339 const SkScalar step = 2;
340 for (SkScalar distance = 0; distance < meas->length(); distance += step) {
341 SkMatrix mx;
342 if (!meas->getMatrix(distance, &mx)) {
343 continue;
344 }
345 SkPoint* dst = pts.append(2);
346 mx.mapPoints(dst, src, 2);
347 }
348
349 int vertCount = pts.size();
350 int indexCount = 0; // no texture
353 vertCount, indexCount, flags);
354 memcpy(builder.positions(), pts.begin(), vertCount * sizeof(SkPoint));
355 SkRandom rand;
356 for (int i = 0; i < vertCount; ++i) {
357 builder.colors()[i] = rand.nextU() | 0xFF000000;
358 }
359 SkDebugf("vert count = %d\n", vertCount);
360
361 return builder.detach();
362}
363
364class PseudoInkSlide : public ClickHandlerSlide {
365 enum { N = 100 };
367 sk_sp<SkVertices> fVertices[N];
368 SkPaint fSkeletonP, fStrokeP, fVertsP;
369 bool fDirty = true;
370
371public:
372 PseudoInkSlide() {
374 fSkeletonP.setAntiAlias(true);
375
377 fStrokeP.setStrokeWidth(30);
378 fStrokeP.setColor(0x44888888);
379 fName = "PseudoInk";
380 }
381
382 bool animate(double nanos) override { return true; }
383
384 void draw(SkCanvas* canvas) override {
385 if (fDirty) {
386 for (int i = 0; i < N; ++i) {
387 fVertices[i] = make_verts(fPath, 30);
388 }
389 fDirty = false;
390 }
391 for (int i = 0; i < N; ++i) {
392 canvas->drawVertices(fVertices[i], SkBlendMode::kSrc, fVertsP);
393 canvas->translate(1, 1);
394 }
395// canvas->drawPath(fPath, fStrokeP);
396 // canvas->drawPath(fPath, fSkeletonP);
397 }
398
399protected:
400 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
401 Click* click = new Click();
402 fPath.reset();
403 fPath.moveTo(x, y);
404 return click;
405 }
406
407 bool onClick(Click* click) override {
408 switch (click->fState) {
410 fPath.lineTo(click->fCurr);
411 fDirty = true;
412 break;
413 default:
414 break;
415 }
416 return true;
417 }
418};
419} // namespace
420DEF_SLIDE( return new PseudoInkSlide(); )
SkPoint fPts[2]
SkPath fPath
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
const char * fName
sk_bzero(glyphs, sizeof(glyphs))
static constexpr int kS
static bool hittest(const SkPoint &target, SkScalar x, SkScalar y)
#define SkASSERT_RELEASE(cond)
Definition: SkAssert.h:100
@ kModulate
r = s*d
static U8CPU SkUnitScalarClampToByte(SkScalar x)
Definition: SkColorPriv.h:36
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
Definition: SkGeometry.cpp:418
#define SK_Scalar1
Definition: SkScalar.h:18
#define SkIntToScalar(x)
Definition: SkScalar.h:57
#define DEF_SLIDE(code)
Definition: Slide.h:25
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
#define N
Definition: beziers.cpp:19
virtual bool onClick(Click *)=0
virtual Click * onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi)=0
int width() const
Definition: SkBitmap.h:149
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkBitmap.cpp:669
int height() const
Definition: SkBitmap.h:158
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
Definition: SkCanvas.cpp:1710
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
Definition: SkCanvas.cpp:1720
@ kPoints_PointMode
draw each point separately
Definition: SkCanvas.h:1241
sk_sp< SkContourMeasure > next()
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)
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
void setStyle(Style style)
Definition: SkPaint.cpp:105
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition: SkPaint.cpp:159
Definition: SkPath.h:59
SkPath & moveTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:688
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
SkPath & reset()
Definition: SkPath.cpp:370
uint32_t nextU()
Definition: SkRandom.h:42
int size() const
Definition: SkTDArray.h:138
T * begin()
Definition: SkTDArray.h:150
T * append()
Definition: SkTDArray.h:191
@ kHasColors_BuilderFlag
Definition: SkVertices.h:64
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
Definition: SkVertices.cpp:200
@ kTriangleStrip_VertexMode
Definition: SkVertices.h:32
virtual void load(SkScalar winWidth, SkScalar winHeight)
Definition: Slide.h:40
virtual bool animate(double nanos)
Definition: Slide.h:39
virtual void draw(SkCanvas *canvas)=0
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
struct MyStruct s
FlutterSemanticsFlag flags
double y
double x
PODArray< SkColor > colors
Definition: SkRecords.h:276
static float Scaled(float time, float speed, float period=0)
Definition: TimeUtils.h:27
bool GetResourceAsBitmap(const char *resource, SkBitmap *dst)
Definition: DecodeUtils.h:21
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
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
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:195
SkSamplingOptions(SkFilterMode::kLinear))
ModifierKey
Definition: ModifierKey.h:9
SkScalar w
SkScalar h
int32_t width
int32_t fX
x-axis value
Definition: SkPoint_impl.h:29
int32_t fY
y-axis value
Definition: SkPoint_impl.h:30
void set(int32_t x, int32_t y)
Definition: SkPoint_impl.h:65
float fX
x-axis value
Definition: SkPoint_impl.h:164
void set(float x, float y)
Definition: SkPoint_impl.h:200
static float Length(float x, float y)
Definition: SkPoint.cpp:79
float fY
y-axis value
Definition: SkPoint_impl.h:165
static sk_sp< SkShader > make_shader1(int w, int h)
static sk_sp< SkShader > make_shader0(int w, int h)