blob: 3e01b477000e5a1658aafbcd64c44c5d85f32eb8 [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"
11#include "include/core/SkGraphics.h"
12#include "include/core/SkPath.h"
13#include "include/core/SkRegion.h"
14#include "include/core/SkShader.h"
15#include "include/core/SkTime.h"
16#include "include/core/SkTypeface.h"
17#include "include/core/SkVertices.h"
18#include "include/effects/SkGradientShader.h"
19#include "include/utils/SkRandom.h"
20#include "samplecode/DecodeFile.h"
21#include "samplecode/Sample.h"
22#include "src/utils/SkUTF.h"
23#include "tools/timer/AnimTimer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000024
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "include/core/SkStream.h"
26#include "src/core/SkOSFile.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000027
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/core/SkGeometry.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
reed8a21c9f2016-03-08 18:50:00 -080030static sk_sp<SkShader> make_shader0(SkIPoint* size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 SkBitmap bm;
reed@google.com82065d62011-02-07 15:30:46 +000032
msarettd15750c2016-03-18 15:48:49 -070033// decode_file("/skimages/progressivejpg.jpg", &bm);
34 decode_file("/skimages/logo.png", &bm);
reed@android.com8a1c16f2008-12-17 15:59:43 +000035 size->set(bm.width(), bm.height());
Mike Reed50acf8f2019-04-08 13:20:23 -040036 return bm.makeShader();
reed@android.com8a1c16f2008-12-17 15:59:43 +000037}
38
reed8a21c9f2016-03-08 18:50:00 -080039static sk_sp<SkShader> make_shader1(const SkIPoint& size) {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +000040 SkPoint pts[] = { { 0, 0, },
41 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
reed8a21c9f2016-03-08 18:50:00 -080043 return SkGradientShader::MakeLinear(pts, colors, nullptr,
Mike Reedfae8fce2019-04-03 10:27:45 -040044 SK_ARRAY_COUNT(colors), SkTileMode::kMirror);
reed@android.com8a1c16f2008-12-17 15:59:43 +000045}
46
47///////////////////////////////////////////////////////////////////////////////
48
49class Patch {
50public:
reed@android.com4516f472009-06-29 16:25:36 +000051 Patch() { sk_bzero(fPts, sizeof(fPts)); }
reed@android.com8a1c16f2008-12-17 15:59:43 +000052 ~Patch() {}
reed@google.com82065d62011-02-07 15:30:46 +000053
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 void setPatch(const SkPoint pts[12]) {
55 memcpy(fPts, pts, 12 * sizeof(SkPoint));
56 fPts[12] = pts[0]; // the last shall be first
57 }
58 void setBounds(int w, int h) { fW = w; fH = h; }
59
60 void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
61 bool doTextures, bool doColors);
reed@google.com82065d62011-02-07 15:30:46 +000062
reed@android.com8a1c16f2008-12-17 15:59:43 +000063private:
64 SkPoint fPts[13];
65 int fW, fH;
66};
67
68static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
69 SkScalar t = 0;
70 SkScalar dt = SK_Scalar1 / segs;
71
72 samples[0] = cubic[0];
73 for (int i = 1; i < segs; i++) {
74 t += dt;
halcanary96fcdcc2015-08-27 07:41:13 -070075 SkEvalCubicAt(cubic, t, &samples[i], nullptr, nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 }
77}
78
79static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
80 SkPoint* pt) {
81 const int TL = 0;
82 const int TR = nu;
83 const int BR = TR + nv;
84 const int BL = BR + nu;
85
86 SkScalar u = SkIntToScalar(iu) / nu;
87 SkScalar v = SkIntToScalar(iv) / nv;
reed@google.com82065d62011-02-07 15:30:46 +000088
Mike Reeddf85c382017-02-14 10:59:19 -050089 SkScalar uv = u * v;
90 SkScalar Uv = (1 - u) * v;
91 SkScalar uV = u * (1 - v);
92 SkScalar UV = (1 - u) * (1 - v);
reed@google.com82065d62011-02-07 15:30:46 +000093
Mike Reeddf85c382017-02-14 10:59:19 -050094 SkScalar x0 = UV * edge[TL].fX + uV * edge[TR].fX + Uv * edge[BL].fX + uv * edge[BR].fX;
95 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 +000096
Mike Reeddf85c382017-02-14 10:59:19 -050097 SkScalar x = (1 - v) * edge[TL+iu].fX + u * edge[TR+iv].fX +
98 v * edge[BR+nu-iu].fX + (1 - u) * edge[BL+nv-iv].fX - x0;
99 SkScalar y = (1 - v) * edge[TL+iu].fY + u * edge[TR+iv].fY +
100 v * edge[BR+nu-iu].fY + (1 - u) * edge[BL+nv-iv].fY - y0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101 pt->set(x, y);
102}
103
reed@android.com8a1c16f2008-12-17 15:59:43 +0000104static SkColor make_color(SkScalar s, SkScalar t) {
benjaminwagnere7be3e52016-03-01 13:44:10 -0800105 return SkColorSetARGB(0xFF, SkUnitScalarClampToByte(s), SkUnitScalarClampToByte(t), 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106}
107
108void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
109 bool doTextures, bool doColors) {
110 if (nu < 1 || nv < 1) {
111 return;
112 }
113
114 int i, npts = (nu + nv) * 2;
115 SkAutoSTMalloc<16, SkPoint> storage(npts + 1);
116 SkPoint* edge0 = storage.get();
117 SkPoint* edge1 = edge0 + nu;
118 SkPoint* edge2 = edge1 + nv;
119 SkPoint* edge3 = edge2 + nu;
reed@google.com82065d62011-02-07 15:30:46 +0000120
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 // evaluate the edge points
122 eval_patch_edge(fPts + 0, edge0, nu);
123 eval_patch_edge(fPts + 3, edge1, nv);
124 eval_patch_edge(fPts + 6, edge2, nu);
125 eval_patch_edge(fPts + 9, edge3, nv);
126 edge3[nv] = edge0[0]; // the last shall be first
reed@google.com82065d62011-02-07 15:30:46 +0000127
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 for (i = 0; i < npts; i++) {
129// canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
130 }
reed@google.com82065d62011-02-07 15:30:46 +0000131
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 int row, vertCount = (nu + 1) * (nv + 1);
133 SkAutoTMalloc<SkPoint> vertStorage(vertCount);
134 SkPoint* verts = vertStorage.get();
reed@google.com82065d62011-02-07 15:30:46 +0000135
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 // first row
137 memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
138 // rows
139 SkPoint* r = verts;
140 for (row = 1; row < nv; row++) {
141 r += nu + 1;
142 r[0] = edge3[nv - row];
143 for (int col = 1; col < nu; col++) {
144 eval_sheet(edge0, nu, nv, col, row, &r[col]);
145 }
146 r[nu] = edge1[row];
147 }
148 // last row
149 SkPoint* last = verts + nv * (nu + 1);
150 for (i = 0; i <= nu; i++) {
151 last[i] = edge2[nu - i];
152 }
reed@google.com82065d62011-02-07 15:30:46 +0000153
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154// canvas->drawPoints(verts, vertCount, paint);
reed@google.com82065d62011-02-07 15:30:46 +0000155
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156 int stripCount = (nu + 1) * 2;
157 SkAutoTMalloc<SkPoint> stripStorage(stripCount * 2);
158 SkAutoTMalloc<SkColor> colorStorage(stripCount);
159 SkPoint* strip = stripStorage.get();
160 SkPoint* tex = strip + stripCount;
161 SkColor* colors = colorStorage.get();
162 SkScalar t = 0;
163 const SkScalar ds = SK_Scalar1 * fW / nu;
164 const SkScalar dt = SK_Scalar1 * fH / nv;
165 r = verts;
166 for (row = 0; row < nv; row++) {
167 SkPoint* upper = r;
168 SkPoint* lower = r + nu + 1;
169 r = lower;
170 SkScalar s = 0;
171 for (i = 0; i <= nu; i++) {
172 strip[i*2 + 0] = *upper++;
173 strip[i*2 + 1] = *lower++;
174 tex[i*2 + 0].set(s, t);
175 tex[i*2 + 1].set(s, t + dt);
176 colors[i*2 + 0] = make_color(s/fW, t/fH);
177 colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
178 s += ds;
179 }
180 t += dt;
Mike Reed887cdf12017-04-03 11:11:09 -0400181 canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangleStrip_VertexMode, stripCount,
182 strip, doTextures ? tex : nullptr,
183 doColors ? colors : nullptr),
184 SkBlendMode::kModulate, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185 }
186}
187
188static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
189 Patch* patch) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190 SkAutoCanvasRestore ar(canvas, true);
191
reedcdf2db92014-08-06 09:54:19 -0700192 patch->draw(canvas, paint, nu, nv, false, false);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000193 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700194 patch->draw(canvas, paint, nu, nv, true, false);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000195 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700196 patch->draw(canvas, paint, nu, nv, false, true);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000197 canvas->translate(SkIntToScalar(180), 0);
reedcdf2db92014-08-06 09:54:19 -0700198 patch->draw(canvas, paint, nu, nv, true, true);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199}
200
reed147476d2014-08-06 07:00:27 -0700201const SkScalar DX = 20;
202const SkScalar DY = 0;
203
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400204class PatchView : public Sample {
reed339cdbf2015-02-05 22:02:37 -0800205 SkScalar fAngle;
reed8a21c9f2016-03-08 18:50:00 -0800206 sk_sp<SkShader> fShader0;
207 sk_sp<SkShader> fShader1;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 SkIPoint fSize0, fSize1;
209 SkPoint fPts[12];
reed@google.com82065d62011-02-07 15:30:46 +0000210
211public:
reed339cdbf2015-02-05 22:02:37 -0800212 PatchView() : fAngle(0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 fShader0 = make_shader0(&fSize0);
214 fSize1 = fSize0;
215 if (fSize0.fX == 0 || fSize0.fY == 0) {
216 fSize1.set(2, 2);
217 }
218 fShader1 = make_shader1(fSize1);
219
reed@android.com6b82d1a2009-06-03 02:35:01 +0000220 const SkScalar S = SkIntToScalar(50);
221 const SkScalar T = SkIntToScalar(40);
222 fPts[0].set(S*0, T);
223 fPts[1].set(S*1, T);
224 fPts[2].set(S*2, T);
225 fPts[3].set(S*3, T);
226 fPts[4].set(S*3, T*2);
227 fPts[5].set(S*3, T*3);
228 fPts[6].set(S*3, T*4);
229 fPts[7].set(S*2, T*4);
230 fPts[8].set(S*1, T*4);
231 fPts[9].set(S*0, T*4);
232 fPts[10].set(S*0, T*3);
233 fPts[11].set(S*0, T*2);
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000234
235 this->setBGColor(SK_ColorGRAY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 }
reed@google.com82065d62011-02-07 15:30:46 +0000237
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238protected:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400239 bool onQuery(Sample::Event* evt) override {
240 if (Sample::TitleQ(*evt)) {
241 Sample::TitleR(evt, "Patch");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 return true;
243 }
244 return this->INHERITED::onQuery(evt);
245 }
reed@google.com82065d62011-02-07 15:30:46 +0000246
mtkleinf0599002015-07-13 06:18:39 -0700247 void onDrawContent(SkCanvas* canvas) override {
reedcdf2db92014-08-06 09:54:19 -0700248 const int nu = 10;
249 const int nv = 10;
250
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 SkPaint paint;
252 paint.setDither(true);
reed93a12152015-03-16 10:08:34 -0700253 paint.setFilterQuality(kLow_SkFilterQuality);
reed@google.com82065d62011-02-07 15:30:46 +0000254
reed147476d2014-08-06 07:00:27 -0700255 canvas->translate(DX, DY);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000256
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257 Patch patch;
reed@google.com82065d62011-02-07 15:30:46 +0000258
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259 paint.setShader(fShader0);
260 if (fSize0.fX == 0) {
261 fSize0.fX = 1;
262 }
263 if (fSize0.fY == 0) {
264 fSize0.fY = 1;
265 }
266 patch.setBounds(fSize0.fX, fSize0.fY);
reed@google.com82065d62011-02-07 15:30:46 +0000267
268 patch.setPatch(fPts);
reedcdf2db92014-08-06 09:54:19 -0700269 drawpatches(canvas, paint, nu, nv, &patch);
reed@google.com82065d62011-02-07 15:30:46 +0000270
halcanary96fcdcc2015-08-27 07:41:13 -0700271 paint.setShader(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000272 paint.setAntiAlias(true);
273 paint.setStrokeWidth(SkIntToScalar(5));
reed@android.comf2b98d62010-12-20 18:26:13 +0000274 canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint);
reed@google.com82065d62011-02-07 15:30:46 +0000275
reed@android.com8a1c16f2008-12-17 15:59:43 +0000276 canvas->translate(0, SkIntToScalar(300));
reed@google.com82065d62011-02-07 15:30:46 +0000277
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278 paint.setAntiAlias(false);
279 paint.setShader(fShader1);
reedcdf2db92014-08-06 09:54:19 -0700280 if (true) {
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000281 SkMatrix m;
282 m.setSkew(1, 0);
reed150835e2016-03-10 06:36:49 -0800283 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000284 }
reedcdf2db92014-08-06 09:54:19 -0700285 if (true) {
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000286 SkMatrix m;
reed339cdbf2015-02-05 22:02:37 -0800287 m.setRotate(fAngle);
reed150835e2016-03-10 06:36:49 -0800288 paint.setShader(paint.getShader()->makeWithLocalMatrix(m));
commit-bot@chromium.org8fae2132014-05-07 22:26:37 +0000289 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 patch.setBounds(fSize1.fX, fSize1.fY);
reedcdf2db92014-08-06 09:54:19 -0700291 drawpatches(canvas, paint, nu, nv, &patch);
reed339cdbf2015-02-05 22:02:37 -0800292 }
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +0000293
Mike Kleincd5104e2019-03-20 11:55:08 -0500294 bool onAnimate(const AnimTimer& timer) override {
reed339cdbf2015-02-05 22:02:37 -0800295 fAngle = timer.scaled(60, 360);
296 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000297 }
reed@google.com82065d62011-02-07 15:30:46 +0000298
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299 class PtClick : public Click {
300 public:
301 int fIndex;
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400302 PtClick(Sample* view, int index) : Click(view), fIndex(index) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 };
reed@google.com82065d62011-02-07 15:30:46 +0000304
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
306 return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
307 }
reed@google.com82065d62011-02-07 15:30:46 +0000308
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400309 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
reed147476d2014-08-06 07:00:27 -0700310 x -= DX;
311 y -= DY;
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000312 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313 if (hittest(fPts[i], x, y)) {
reed@google.com7fa2a652014-01-27 13:42:58 +0000314 return new PtClick(this, (int)i);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315 }
316 }
reed@google.com4d5c26d2013-01-08 16:17:50 +0000317 return this->INHERITED::onFindClickHandler(x, y, modi);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318 }
reed@google.com82065d62011-02-07 15:30:46 +0000319
mtkleinf0599002015-07-13 06:18:39 -0700320 bool onClick(Click* click) override {
reed147476d2014-08-06 07:00:27 -0700321 fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX - DX, click->fCurr.fY - DY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 return true;
323 }
reed@google.com82065d62011-02-07 15:30:46 +0000324
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400326 typedef Sample INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327};
Mike Reed72542812019-03-04 17:00:39 -0500328DEF_SAMPLE( return new PatchView(); )
reed@android.com8a1c16f2008-12-17 15:59:43 +0000329
330//////////////////////////////////////////////////////////////////////////////
331
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500332#include "include/core/SkContourMeasure.h"
333#include "include/private/SkTDArray.h"
Mike Reed72542812019-03-04 17:00:39 -0500334
335static sk_sp<SkVertices> make_verts(const SkPath& path, SkScalar width) {
336 auto meas = SkContourMeasureIter(path, false).next();
337 if (!meas) {
338 return nullptr;
339 }
340
341 const SkPoint src[2] = {
342 { 0, -width/2 }, { 0, width/2 },
343 };
344 SkTDArray<SkPoint> pts;
345
346 const SkScalar step = 2;
347 for (SkScalar distance = 0; distance < meas->length(); distance += step) {
348 SkMatrix mx;
349 if (!meas->getMatrix(distance, &mx)) {
350 continue;
351 }
352 SkPoint* dst = pts.append(2);
353 mx.mapPoints(dst, src, 2);
354 }
355
356 int vertCount = pts.count();
357 int indexCount = 0; // no texture
358 unsigned flags = SkVertices::kHasColors_BuilderFlag |
359 SkVertices::kIsNonVolatile_BuilderFlag;
360 SkVertices::Builder builder(SkVertices::kTriangleStrip_VertexMode,
361 vertCount, indexCount, flags);
362 memcpy(builder.positions(), pts.begin(), vertCount * sizeof(SkPoint));
363 SkRandom rand;
364 for (int i = 0; i < vertCount; ++i) {
365 builder.colors()[i] = rand.nextU() | 0xFF000000;
366 }
367 SkDebugf("vert count = %d\n", vertCount);
368
369 return builder.detach();
370}
371
372class PseudoInkView : public Sample {
Mike Reed541ae452019-03-05 14:29:50 -0500373 enum { N = 100 };
Mike Reed72542812019-03-04 17:00:39 -0500374 SkPath fPath;
Mike Reed541ae452019-03-05 14:29:50 -0500375 sk_sp<SkVertices> fVertices[N];
Mike Reed72542812019-03-04 17:00:39 -0500376 SkPaint fSkeletonP, fStrokeP, fVertsP;
Mike Reed541ae452019-03-05 14:29:50 -0500377 bool fDirty = true;
Mike Reed72542812019-03-04 17:00:39 -0500378
379public:
380 PseudoInkView() {
381 fSkeletonP.setStyle(SkPaint::kStroke_Style);
382 fSkeletonP.setAntiAlias(true);
383
384 fStrokeP.setStyle(SkPaint::kStroke_Style);
385 fStrokeP.setStrokeWidth(30);
386 fStrokeP.setColor(0x44888888);
387 }
388
389protected:
390 bool onQuery(Sample::Event* evt) override {
391 if (Sample::TitleQ(*evt)) {
392 Sample::TitleR(evt, "PseudoInk");
393 return true;
394 }
395 return this->INHERITED::onQuery(evt);
396 }
397
Mike Kleincd5104e2019-03-20 11:55:08 -0500398 bool onAnimate(const AnimTimer& timer) override { return true; }
Mike Reed72542812019-03-04 17:00:39 -0500399
400 void onDrawContent(SkCanvas* canvas) override {
Mike Reed541ae452019-03-05 14:29:50 -0500401 if (fDirty) {
402 for (int i = 0; i < N; ++i) {
403 fVertices[i] = make_verts(fPath, 30);
404 }
405 fDirty = false;
Mike Reed72542812019-03-04 17:00:39 -0500406 }
Mike Reed541ae452019-03-05 14:29:50 -0500407 for (int i = 0; i < N; ++i) {
408 canvas->drawVertices(fVertices[i], SkBlendMode::kSrc, fVertsP);
409 canvas->translate(1, 1);
Mike Reed72542812019-03-04 17:00:39 -0500410 }
411// canvas->drawPath(fPath, fStrokeP);
412 // canvas->drawPath(fPath, fSkeletonP);
413 }
414
415 Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
416 Click* click = new Click(this);
417 fPath.reset();
418 fPath.moveTo(x, y);
419 return click;
420 }
421
422 bool onClick(Click* click) override {
423 switch (click->fState) {
424 case Click::kMoved_State:
425 fPath.lineTo(click->fCurr);
Mike Reed541ae452019-03-05 14:29:50 -0500426 fDirty = true;
Mike Reed72542812019-03-04 17:00:39 -0500427 break;
428 default:
429 break;
430 }
431 return true;
432 }
433
434private:
435 typedef Sample INHERITED;
436};
437DEF_SAMPLE( return new PseudoInkView(); )
Mike Reed5ee611b2019-03-31 22:39:32 -0400438
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500439#include "include/effects/SkOpPathEffect.h"
Mike Reed5ee611b2019-03-31 22:39:32 -0400440// Show stroking options using patheffects (and pathops)
441// and why strokeandfill is a hacks
442class ManyStrokesView : public Sample {
443 SkPath fPath;
444 sk_sp<SkPathEffect> fPE[6];
445
446public:
447 ManyStrokesView() {
448 fPE[0] = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap);
449
450 auto p0 = SkStrokePathEffect::Make(25, SkPaint::kRound_Join, SkPaint::kRound_Cap);
451 auto p1 = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap);
452 fPE[1] = SkMergePathEffect::Make(p0, p1, SkPathOp::kDifference_SkPathOp);
453
454 fPE[2] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kDifference_SkPathOp);
455 fPE[3] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kUnion_SkPathOp);
456 fPE[4] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kDifference_SkPathOp);
457 fPE[5] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kIntersect_SkPathOp);
458 }
459
460protected:
461 bool onQuery(Sample::Event* evt) override {
462 if (Sample::TitleQ(*evt)) {
463 Sample::TitleR(evt, "ManyStrokes");
464 return true;
465 }
466 return this->INHERITED::onQuery(evt);
467 }
468
469 bool onAnimate(const AnimTimer& timer) override { return true; }
470
471 void dodraw(SkCanvas* canvas, sk_sp<SkPathEffect> pe, SkScalar x, SkScalar y,
472 const SkPaint* ptr = nullptr) {
473 SkPaint paint;
474 paint.setAntiAlias(true);
475 paint.setPathEffect(pe);
476 canvas->save();
477 canvas->translate(x, y);
478 canvas->drawPath(fPath, ptr ? *ptr : paint);
479
480 paint.setPathEffect(nullptr);
481 paint.setStyle(SkPaint::kStroke_Style);
482 paint.setColor(SK_ColorGREEN);
483 canvas->drawPath(fPath, paint);
484
485 canvas->restore();
486 }
487
488 void onDrawContent(SkCanvas* canvas) override {
489 SkPaint p;
490 p.setColor(0);
491 this->dodraw(canvas, nullptr, 0, 0, &p);
492
493 this->dodraw(canvas, fPE[0], 300, 0);
494 this->dodraw(canvas, fPE[1], 0, 300);
495 this->dodraw(canvas, fPE[2], 300, 300);
496 this->dodraw(canvas, fPE[3], 600, 300);
497 this->dodraw(canvas, fPE[4], 900, 0);
498 this->dodraw(canvas, fPE[5], 900, 300);
499
500 p.setColor(SK_ColorBLACK);
501 p.setStyle(SkPaint::kStrokeAndFill_Style);
502 p.setStrokeJoin(SkPaint::kRound_Join);
503 p.setStrokeCap(SkPaint::kRound_Cap);
504 p.setStrokeWidth(20);
505 this->dodraw(canvas, nullptr, 600, 0, &p);
506 }
507
508 Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
509 Click* click = new Click(this);
510 fPath.reset();
511 fPath.moveTo(x, y);
512 return click;
513 }
514
515 bool onClick(Click* click) override {
516 switch (click->fState) {
517 case Click::kMoved_State:
518 fPath.lineTo(click->fCurr);
519 break;
520 default:
521 break;
522 }
523 return true;
524 }
525
526private:
527 typedef Sample INHERITED;
528};
529DEF_SAMPLE( return new ManyStrokesView(); )