blob: 3fd7d3db8e075fe60a86df724c344b4733fc6a4a [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
reed339cdbf2015-02-05 22:02:37 -08007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkColorFilter.h"
10#include "include/core/SkColorPriv.h"
Hal Canary5f4a7542019-07-03 22:17:24 -040011#include "include/core/SkContourMeasure.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkGraphics.h"
13#include "include/core/SkPath.h"
14#include "include/core/SkRegion.h"
15#include "include/core/SkShader.h"
Hal Canary5f4a7542019-07-03 22:17:24 -040016#include "include/core/SkStream.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/core/SkTime.h"
18#include "include/core/SkTypeface.h"
19#include "include/core/SkVertices.h"
20#include "include/effects/SkGradientShader.h"
Hal Canary5f4a7542019-07-03 22:17:24 -040021#include "include/effects/SkOpPathEffect.h"
22#include "include/private/SkTDArray.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/utils/SkRandom.h"
24#include "samplecode/DecodeFile.h"
25#include "samplecode/Sample.h"
Hal Canary5f4a7542019-07-03 22:17:24 -040026#include "src/core/SkGeometry.h"
27#include "src/core/SkOSFile.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/utils/SkUTF.h"
Hal Canary5f4a7542019-07-03 22:17:24 -040029#include "tools/Resources.h"
Hal Canary41248072019-07-11 16:32:53 -040030#include "tools/timer/TimeUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000031
Hal Canary5f4a7542019-07-03 22:17:24 -040032namespace {
reed8a21c9f2016-03-08 18:50:00 -080033static sk_sp<SkShader> make_shader0(SkIPoint* size) {
Hal Canary5f4a7542019-07-03 22:17:24 -040034 SkBitmap bm;
35 decode_file(GetResourceAsData("images/dog.jpg"), &bm);
36 *size = SkIPoint{bm.width(), bm.height()};
Mike Reed50acf8f2019-04-08 13:20:23 -040037 return bm.makeShader();
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
reed8a21c9f2016-03-08 18:50:00 -080040static sk_sp<SkShader> make_shader1(const SkIPoint& size) {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +000041 SkPoint pts[] = { { 0, 0, },
42 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
reed8a21c9f2016-03-08 18:50:00 -080044 return SkGradientShader::MakeLinear(pts, colors, nullptr,
Mike Reedfae8fce2019-04-03 10:27:45 -040045 SK_ARRAY_COUNT(colors), SkTileMode::kMirror);
reed@android.com8a1c16f2008-12-17 15:59:43 +000046}
47
reed@android.com8a1c16f2008-12-17 15:59:43 +000048class Patch {
49public:
reed@android.com4516f472009-06-29 16:25:36 +000050 Patch() { sk_bzero(fPts, sizeof(fPts)); }
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 ~Patch() {}
reed@google.com82065d62011-02-07 15:30:46 +000052
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 void setPatch(const SkPoint pts[12]) {
54 memcpy(fPts, pts, 12 * sizeof(SkPoint));
55 fPts[12] = pts[0]; // the last shall be first
56 }
57 void setBounds(int w, int h) { fW = w; fH = h; }
58
59 void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
60 bool doTextures, bool doColors);
reed@google.com82065d62011-02-07 15:30:46 +000061
reed@android.com8a1c16f2008-12-17 15:59:43 +000062private:
63 SkPoint fPts[13];
64 int fW, fH;
65};
66
67static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
68 SkScalar t = 0;
69 SkScalar dt = SK_Scalar1 / segs;
70
71 samples[0] = cubic[0];
72 for (int i = 1; i < segs; i++) {
73 t += dt;
halcanary96fcdcc2015-08-27 07:41:13 -070074 SkEvalCubicAt(cubic, t, &samples[i], nullptr, nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000075 }
76}
77
78static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
79 SkPoint* pt) {
80 const int TL = 0;
81 const int TR = nu;
82 const int BR = TR + nv;
83 const int BL = BR + nu;
84
85 SkScalar u = SkIntToScalar(iu) / nu;
86 SkScalar v = SkIntToScalar(iv) / nv;
reed@google.com82065d62011-02-07 15:30:46 +000087
Mike Reeddf85c382017-02-14 10:59:19 -050088 SkScalar uv = u * v;
89 SkScalar Uv = (1 - u) * v;
90 SkScalar uV = u * (1 - v);
91 SkScalar UV = (1 - u) * (1 - v);
reed@google.com82065d62011-02-07 15:30:46 +000092
Mike Reeddf85c382017-02-14 10:59:19 -050093 SkScalar x0 = UV * edge[TL].fX + uV * edge[TR].fX + Uv * edge[BL].fX + uv * edge[BR].fX;
94 SkScalar y0 = UV * edge[TL].fY + uV * edge[TR].fY + Uv * edge[BL].fY + uv * edge[BR].fY;
reed@android.com8a1c16f2008-12-17 15:59:43 +000095
Mike Reeddf85c382017-02-14 10:59:19 -050096 SkScalar x = (1 - v) * edge[TL+iu].fX + u * edge[TR+iv].fX +
97 v * edge[BR+nu-iu].fX + (1 - u) * edge[BL+nv-iv].fX - x0;
98 SkScalar y = (1 - v) * edge[TL+iu].fY + u * edge[TR+iv].fY +
99 v * edge[BR+nu-iu].fY + (1 - u) * edge[BL+nv-iv].fY - y0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100 pt->set(x, y);
101}
102
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103static SkColor make_color(SkScalar s, SkScalar t) {
benjaminwagnere7be3e52016-03-01 13:44:10 -0800104 return SkColorSetARGB(0xFF, SkUnitScalarClampToByte(s), SkUnitScalarClampToByte(t), 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105}
106
107void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
108 bool doTextures, bool doColors) {
109 if (nu < 1 || nv < 1) {
110 return;
111 }
112
113 int i, npts = (nu + nv) * 2;
114 SkAutoSTMalloc<16, SkPoint> storage(npts + 1);
115 SkPoint* edge0 = storage.get();
116 SkPoint* edge1 = edge0 + nu;
117 SkPoint* edge2 = edge1 + nv;
118 SkPoint* edge3 = edge2 + nu;
reed@google.com82065d62011-02-07 15:30:46 +0000119
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 // evaluate the edge points
121 eval_patch_edge(fPts + 0, edge0, nu);
122 eval_patch_edge(fPts + 3, edge1, nv);
123 eval_patch_edge(fPts + 6, edge2, nu);
124 eval_patch_edge(fPts + 9, edge3, nv);
125 edge3[nv] = edge0[0]; // the last shall be first
reed@google.com82065d62011-02-07 15:30:46 +0000126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 for (i = 0; i < npts; i++) {
128// canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
129 }
reed@google.com82065d62011-02-07 15:30:46 +0000130
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 int row, vertCount = (nu + 1) * (nv + 1);
132 SkAutoTMalloc<SkPoint> vertStorage(vertCount);
133 SkPoint* verts = vertStorage.get();
reed@google.com82065d62011-02-07 15:30:46 +0000134
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135 // first row
136 memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
137 // rows
138 SkPoint* r = verts;
139 for (row = 1; row < nv; row++) {
140 r += nu + 1;
141 r[0] = edge3[nv - row];
142 for (int col = 1; col < nu; col++) {
143 eval_sheet(edge0, nu, nv, col, row, &r[col]);
144 }
145 r[nu] = edge1[row];
146 }
147 // last row
148 SkPoint* last = verts + nv * (nu + 1);
149 for (i = 0; i <= nu; i++) {
150 last[i] = edge2[nu - i];
151 }
reed@google.com82065d62011-02-07 15:30:46 +0000152
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153// canvas->drawPoints(verts, vertCount, paint);
reed@google.com82065d62011-02-07 15:30:46 +0000154
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155 int stripCount = (nu + 1) * 2;
156 SkAutoTMalloc<SkPoint> stripStorage(stripCount * 2);
157 SkAutoTMalloc<SkColor> colorStorage(stripCount);
158 SkPoint* strip = stripStorage.get();
159 SkPoint* tex = strip + stripCount;
160 SkColor* colors = colorStorage.get();
161 SkScalar t = 0;
162 const SkScalar ds = SK_Scalar1 * fW / nu;
163 const SkScalar dt = SK_Scalar1 * fH / nv;
164 r = verts;
165 for (row = 0; row < nv; row++) {
166 SkPoint* upper = r;
167 SkPoint* lower = r + nu + 1;
168 r = lower;
169 SkScalar s = 0;
170 for (i = 0; i <= nu; i++) {
171 strip[i*2 + 0] = *upper++;
172 strip[i*2 + 1] = *lower++;
173 tex[i*2 + 0].set(s, t);
174 tex[i*2 + 1].set(s, t + dt);
175 colors[i*2 + 0] = make_color(s/fW, t/fH);
176 colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
177 s += ds;
178 }
179 t += dt;
Mike Reed887cdf12017-04-03 11:11:09 -0400180 canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangleStrip_VertexMode, stripCount,
181 strip, doTextures ? tex : nullptr,
182 doColors ? colors : nullptr),
183 SkBlendMode::kModulate, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 }
185}
186
187static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
188 Patch* patch) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 SkAutoCanvasRestore ar(canvas, true);
190
reedcdf2db92014-08-06 09:54:19 -0700191 patch->draw(canvas, paint, nu, nv, false, false);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000192 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700193 patch->draw(canvas, paint, nu, nv, true, false);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000194 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700195 patch->draw(canvas, paint, nu, nv, false, true);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000196 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700197 patch->draw(canvas, paint, nu, nv, true, true);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198}
199
Hal Canary5f4a7542019-07-03 22:17:24 -0400200static constexpr SkScalar DX = 20;
201static constexpr SkScalar DY = 0;
202static constexpr SkScalar kS = 50;
203static constexpr SkScalar kT = 40;
reed147476d2014-08-06 07:00:27 -0700204
Hal Canary5f4a7542019-07-03 22:17:24 -0400205struct PatchView : public Sample {
reed8a21c9f2016-03-08 18:50:00 -0800206 sk_sp<SkShader> fShader0;
207 sk_sp<SkShader> fShader1;
Hal Canary5f4a7542019-07-03 22:17:24 -0400208 SkScalar fAngle = 0;
209 SkIPoint fSize0 = {0, 0},
210 fSize1 = {0, 0};
211 SkPoint fPts[12] = {
212 {kS * 0, kT * 1},
213 {kS * 1, kT * 1},
214 {kS * 2, kT * 1},
215 {kS * 3, kT * 1},
216 {kS * 3, kT * 2},
217 {kS * 3, kT * 3},
218 {kS * 3, kT * 4},
219 {kS * 2, kT * 4},
220 {kS * 1, kT * 4},
221 {kS * 0, kT * 4},
222 {kS * 0, kT * 3},
223 {kS * 0, kT * 2},
224 };
reed@google.com82065d62011-02-07 15:30:46 +0000225
Hal Canary5f4a7542019-07-03 22:17:24 -0400226 void onOnceBeforeDraw() override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227 fShader0 = make_shader0(&fSize0);
228 fSize1 = fSize0;
229 if (fSize0.fX == 0 || fSize0.fY == 0) {
230 fSize1.set(2, 2);
231 }
232 fShader1 = make_shader1(fSize1);
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000233 this->setBGColor(SK_ColorGRAY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234 }
reed@google.com82065d62011-02-07 15:30:46 +0000235
Hal Canary8a027312019-07-03 10:55:44 -0400236 SkString name() override { return SkString("Patch"); }
reed@google.com82065d62011-02-07 15:30:46 +0000237
mtkleinf0599002015-07-13 06:18:39 -0700238 void onDrawContent(SkCanvas* canvas) override {
reedcdf2db92014-08-06 09:54:19 -0700239 const int nu = 10;
240 const int nv = 10;
241
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 SkPaint paint;
243 paint.setDither(true);
reed93a12152015-03-16 10:08:34 -0700244 paint.setFilterQuality(kLow_SkFilterQuality);
reed@google.com82065d62011-02-07 15:30:46 +0000245
reed147476d2014-08-06 07:00:27 -0700246 canvas->translate(DX, DY);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000247
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 Patch patch;
reed@google.com82065d62011-02-07 15:30:46 +0000249
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250 paint.setShader(fShader0);
251 if (fSize0.fX == 0) {
252 fSize0.fX = 1;
253 }
254 if (fSize0.fY == 0) {
255 fSize0.fY = 1;
256 }
257 patch.setBounds(fSize0.fX, fSize0.fY);
reed@google.com82065d62011-02-07 15:30:46 +0000258
259 patch.setPatch(fPts);
reedcdf2db92014-08-06 09:54:19 -0700260 drawpatches(canvas, paint, nu, nv, &patch);
reed@google.com82065d62011-02-07 15:30:46 +0000261
halcanary96fcdcc2015-08-27 07:41:13 -0700262 paint.setShader(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263 paint.setAntiAlias(true);
264 paint.setStrokeWidth(SkIntToScalar(5));
reed@android.comf2b98d62010-12-20 18:26:13 +0000265 canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint);
reed@google.com82065d62011-02-07 15:30:46 +0000266
reed@android.com8a1c16f2008-12-17 15:59:43 +0000267 canvas->translate(0, SkIntToScalar(300));
reed@google.com82065d62011-02-07 15:30:46 +0000268
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269 paint.setAntiAlias(false);
270 paint.setShader(fShader1);
Hal Canary5f4a7542019-07-03 22:17:24 -0400271 {
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000272 SkMatrix m;
273 m.setSkew(1, 0);
reed150835e2016-03-10 06:36:49 -0800274 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000275 }
Hal Canary5f4a7542019-07-03 22:17:24 -0400276 {
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000277 SkMatrix m;
reed339cdbf2015-02-05 22:02:37 -0800278 m.setRotate(fAngle);
reed150835e2016-03-10 06:36:49 -0800279 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000280 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 patch.setBounds(fSize1.fX, fSize1.fY);
reedcdf2db92014-08-06 09:54:19 -0700282 drawpatches(canvas, paint, nu, nv, &patch);
reed339cdbf2015-02-05 22:02:37 -0800283 }
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +0000284
Hal Canary41248072019-07-11 16:32:53 -0400285 bool onAnimate(double nanos) override {
286 fAngle = TimeUtils::Scaled(1e-9 * nanos, 60, 360);
reed339cdbf2015-02-05 22:02:37 -0800287 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000288 }
reed@google.com82065d62011-02-07 15:30:46 +0000289
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 class PtClick : public Click {
291 public:
292 int fIndex;
Hal Canaryfcf63592019-07-12 11:32:43 -0400293 PtClick(int index) : fIndex(index) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294 };
reed@google.com82065d62011-02-07 15:30:46 +0000295
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
297 return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
298 }
reed@google.com82065d62011-02-07 15:30:46 +0000299
Hal Canaryb1f411a2019-08-29 10:39:22 -0400300 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
reed147476d2014-08-06 07:00:27 -0700301 x -= DX;
302 y -= DY;
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000303 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 if (hittest(fPts[i], x, y)) {
Hal Canaryfcf63592019-07-12 11:32:43 -0400305 return new PtClick((int)i);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306 }
307 }
Hal Canaryfcf63592019-07-12 11:32:43 -0400308 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 }
reed@google.com82065d62011-02-07 15:30:46 +0000310
mtkleinf0599002015-07-13 06:18:39 -0700311 bool onClick(Click* click) override {
reed147476d2014-08-06 07:00:27 -0700312 fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX - DX, click->fCurr.fY - DY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313 return true;
314 }
reed@google.com82065d62011-02-07 15:30:46 +0000315
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400317 typedef Sample INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318};
Hal Canary5f4a7542019-07-03 22:17:24 -0400319} // namespace
Mike Reed72542812019-03-04 17:00:39 -0500320DEF_SAMPLE( return new PatchView(); )
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321
322//////////////////////////////////////////////////////////////////////////////
323
Hal Canary5f4a7542019-07-03 22:17:24 -0400324namespace {
Mike Reed72542812019-03-04 17:00:39 -0500325static sk_sp<SkVertices> make_verts(const SkPath& path, SkScalar width) {
326 auto meas = SkContourMeasureIter(path, false).next();
327 if (!meas) {
328 return nullptr;
329 }
330
331 const SkPoint src[2] = {
332 { 0, -width/2 }, { 0, width/2 },
333 };
334 SkTDArray<SkPoint> pts;
335
336 const SkScalar step = 2;
337 for (SkScalar distance = 0; distance < meas->length(); distance += step) {
338 SkMatrix mx;
339 if (!meas->getMatrix(distance, &mx)) {
340 continue;
341 }
342 SkPoint* dst = pts.append(2);
343 mx.mapPoints(dst, src, 2);
344 }
345
346 int vertCount = pts.count();
347 int indexCount = 0; // no texture
348 unsigned flags = SkVertices::kHasColors_BuilderFlag |
349 SkVertices::kIsNonVolatile_BuilderFlag;
350 SkVertices::Builder builder(SkVertices::kTriangleStrip_VertexMode,
351 vertCount, indexCount, flags);
352 memcpy(builder.positions(), pts.begin(), vertCount * sizeof(SkPoint));
353 SkRandom rand;
354 for (int i = 0; i < vertCount; ++i) {
355 builder.colors()[i] = rand.nextU() | 0xFF000000;
356 }
357 SkDebugf("vert count = %d\n", vertCount);
358
359 return builder.detach();
360}
361
362class PseudoInkView : public Sample {
Mike Reed541ae452019-03-05 14:29:50 -0500363 enum { N = 100 };
Mike Reed72542812019-03-04 17:00:39 -0500364 SkPath fPath;
Mike Reed541ae452019-03-05 14:29:50 -0500365 sk_sp<SkVertices> fVertices[N];
Mike Reed72542812019-03-04 17:00:39 -0500366 SkPaint fSkeletonP, fStrokeP, fVertsP;
Mike Reed541ae452019-03-05 14:29:50 -0500367 bool fDirty = true;
Mike Reed72542812019-03-04 17:00:39 -0500368
369public:
370 PseudoInkView() {
371 fSkeletonP.setStyle(SkPaint::kStroke_Style);
372 fSkeletonP.setAntiAlias(true);
373
374 fStrokeP.setStyle(SkPaint::kStroke_Style);
375 fStrokeP.setStrokeWidth(30);
376 fStrokeP.setColor(0x44888888);
377 }
378
379protected:
Hal Canary8a027312019-07-03 10:55:44 -0400380 SkString name() override { return SkString("PseudoInk"); }
Mike Reed72542812019-03-04 17:00:39 -0500381
Hal Canary41248072019-07-11 16:32:53 -0400382 bool onAnimate(double nanos) override { return true; }
Mike Reed72542812019-03-04 17:00:39 -0500383
384 void onDrawContent(SkCanvas* canvas) override {
Mike Reed541ae452019-03-05 14:29:50 -0500385 if (fDirty) {
386 for (int i = 0; i < N; ++i) {
387 fVertices[i] = make_verts(fPath, 30);
388 }
389 fDirty = false;
Mike Reed72542812019-03-04 17:00:39 -0500390 }
Mike Reed541ae452019-03-05 14:29:50 -0500391 for (int i = 0; i < N; ++i) {
392 canvas->drawVertices(fVertices[i], SkBlendMode::kSrc, fVertsP);
393 canvas->translate(1, 1);
Mike Reed72542812019-03-04 17:00:39 -0500394 }
395// canvas->drawPath(fPath, fStrokeP);
396 // canvas->drawPath(fPath, fSkeletonP);
397 }
398
Hal Canaryb1f411a2019-08-29 10:39:22 -0400399 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
Hal Canaryfcf63592019-07-12 11:32:43 -0400400 Click* click = new Click();
Mike Reed72542812019-03-04 17:00:39 -0500401 fPath.reset();
402 fPath.moveTo(x, y);
403 return click;
404 }
405
406 bool onClick(Click* click) override {
407 switch (click->fState) {
Hal Canaryb1f411a2019-08-29 10:39:22 -0400408 case skui::InputState::kMove:
Mike Reed72542812019-03-04 17:00:39 -0500409 fPath.lineTo(click->fCurr);
Mike Reed541ae452019-03-05 14:29:50 -0500410 fDirty = true;
Mike Reed72542812019-03-04 17:00:39 -0500411 break;
412 default:
413 break;
414 }
415 return true;
416 }
417
418private:
419 typedef Sample INHERITED;
420};
Hal Canary5f4a7542019-07-03 22:17:24 -0400421} // namespace
Mike Reed72542812019-03-04 17:00:39 -0500422DEF_SAMPLE( return new PseudoInkView(); )
Mike Reed5ee611b2019-03-31 22:39:32 -0400423
Hal Canary5f4a7542019-07-03 22:17:24 -0400424namespace {
Mike Reed5ee611b2019-03-31 22:39:32 -0400425// Show stroking options using patheffects (and pathops)
426// and why strokeandfill is a hacks
427class ManyStrokesView : public Sample {
428 SkPath fPath;
429 sk_sp<SkPathEffect> fPE[6];
430
431public:
432 ManyStrokesView() {
433 fPE[0] = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap);
434
435 auto p0 = SkStrokePathEffect::Make(25, SkPaint::kRound_Join, SkPaint::kRound_Cap);
436 auto p1 = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap);
437 fPE[1] = SkMergePathEffect::Make(p0, p1, SkPathOp::kDifference_SkPathOp);
438
439 fPE[2] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kDifference_SkPathOp);
440 fPE[3] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kUnion_SkPathOp);
441 fPE[4] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kDifference_SkPathOp);
442 fPE[5] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kIntersect_SkPathOp);
443 }
444
445protected:
Hal Canary8a027312019-07-03 10:55:44 -0400446 SkString name() override { return SkString("ManyStrokes"); }
Mike Reed5ee611b2019-03-31 22:39:32 -0400447
Hal Canary41248072019-07-11 16:32:53 -0400448 bool onAnimate(double nanos) override { return true; }
Mike Reed5ee611b2019-03-31 22:39:32 -0400449
450 void dodraw(SkCanvas* canvas, sk_sp<SkPathEffect> pe, SkScalar x, SkScalar y,
451 const SkPaint* ptr = nullptr) {
452 SkPaint paint;
453 paint.setAntiAlias(true);
454 paint.setPathEffect(pe);
455 canvas->save();
456 canvas->translate(x, y);
457 canvas->drawPath(fPath, ptr ? *ptr : paint);
458
459 paint.setPathEffect(nullptr);
460 paint.setStyle(SkPaint::kStroke_Style);
461 paint.setColor(SK_ColorGREEN);
462 canvas->drawPath(fPath, paint);
463
464 canvas->restore();
465 }
466
467 void onDrawContent(SkCanvas* canvas) override {
468 SkPaint p;
469 p.setColor(0);
470 this->dodraw(canvas, nullptr, 0, 0, &p);
471
472 this->dodraw(canvas, fPE[0], 300, 0);
473 this->dodraw(canvas, fPE[1], 0, 300);
474 this->dodraw(canvas, fPE[2], 300, 300);
475 this->dodraw(canvas, fPE[3], 600, 300);
476 this->dodraw(canvas, fPE[4], 900, 0);
477 this->dodraw(canvas, fPE[5], 900, 300);
478
479 p.setColor(SK_ColorBLACK);
480 p.setStyle(SkPaint::kStrokeAndFill_Style);
481 p.setStrokeJoin(SkPaint::kRound_Join);
482 p.setStrokeCap(SkPaint::kRound_Cap);
483 p.setStrokeWidth(20);
484 this->dodraw(canvas, nullptr, 600, 0, &p);
485 }
486
Hal Canaryb1f411a2019-08-29 10:39:22 -0400487 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
Hal Canaryfcf63592019-07-12 11:32:43 -0400488 Click* click = new Click();
Mike Reed5ee611b2019-03-31 22:39:32 -0400489 fPath.reset();
490 fPath.moveTo(x, y);
491 return click;
492 }
493
494 bool onClick(Click* click) override {
495 switch (click->fState) {
Hal Canaryb1f411a2019-08-29 10:39:22 -0400496 case skui::InputState::kMove:
Mike Reed5ee611b2019-03-31 22:39:32 -0400497 fPath.lineTo(click->fCurr);
498 break;
499 default:
500 break;
501 }
502 return true;
503 }
504
505private:
506 typedef Sample INHERITED;
507};
Hal Canary5f4a7542019-07-03 22:17:24 -0400508} // namespace
Mike Reed5ee611b2019-03-31 22:39:32 -0400509DEF_SAMPLE( return new ManyStrokesView(); )