1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColorPriv.h" 11cb93a386Sopenharmony_ci#include "include/core/SkContourMeasure.h" 12cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 14cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 15cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 16cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 17cb93a386Sopenharmony_ci#include "include/core/SkTime.h" 18cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 19cb93a386Sopenharmony_ci#include "include/core/SkVertices.h" 20cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 21cb93a386Sopenharmony_ci#include "include/effects/SkOpPathEffect.h" 22cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h" 23cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 24cb93a386Sopenharmony_ci#include "samplecode/DecodeFile.h" 25cb93a386Sopenharmony_ci#include "samplecode/Sample.h" 26cb93a386Sopenharmony_ci#include "src/core/SkGeometry.h" 27cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 28cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h" 29cb93a386Sopenharmony_ci#include "tools/Resources.h" 30cb93a386Sopenharmony_ci#include "tools/timer/TimeUtils.h" 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cinamespace { 33cb93a386Sopenharmony_cistatic sk_sp<SkShader> make_shader0(SkIPoint* size) { 34cb93a386Sopenharmony_ci SkBitmap bm; 35cb93a386Sopenharmony_ci decode_file(GetResourceAsData("images/dog.jpg"), &bm); 36cb93a386Sopenharmony_ci *size = SkIPoint{bm.width(), bm.height()}; 37cb93a386Sopenharmony_ci return bm.makeShader(SkSamplingOptions(SkFilterMode::kLinear)); 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_cistatic sk_sp<SkShader> make_shader1(const SkIPoint& size) { 41cb93a386Sopenharmony_ci SkPoint pts[] = { { 0, 0, }, 42cb93a386Sopenharmony_ci { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } }; 43cb93a386Sopenharmony_ci SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED }; 44cb93a386Sopenharmony_ci return SkGradientShader::MakeLinear(pts, colors, nullptr, 45cb93a386Sopenharmony_ci SK_ARRAY_COUNT(colors), SkTileMode::kMirror); 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ciclass Patch { 49cb93a386Sopenharmony_cipublic: 50cb93a386Sopenharmony_ci Patch() { sk_bzero(fPts, sizeof(fPts)); } 51cb93a386Sopenharmony_ci ~Patch() {} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci void setPatch(const SkPoint pts[12]) { 54cb93a386Sopenharmony_ci memcpy(fPts, pts, 12 * sizeof(SkPoint)); 55cb93a386Sopenharmony_ci fPts[12] = pts[0]; // the last shall be first 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci void setBounds(int w, int h) { fW = w; fH = h; } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci void draw(SkCanvas*, const SkPaint&, int segsU, int segsV, 60cb93a386Sopenharmony_ci bool doTextures, bool doColors); 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ciprivate: 63cb93a386Sopenharmony_ci SkPoint fPts[13]; 64cb93a386Sopenharmony_ci int fW, fH; 65cb93a386Sopenharmony_ci}; 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cistatic void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) { 68cb93a386Sopenharmony_ci SkScalar t = 0; 69cb93a386Sopenharmony_ci SkScalar dt = SK_Scalar1 / segs; 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci samples[0] = cubic[0]; 72cb93a386Sopenharmony_ci for (int i = 1; i < segs; i++) { 73cb93a386Sopenharmony_ci t += dt; 74cb93a386Sopenharmony_ci SkEvalCubicAt(cubic, t, &samples[i], nullptr, nullptr); 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_cistatic void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv, 79cb93a386Sopenharmony_ci SkPoint* pt) { 80cb93a386Sopenharmony_ci const int TL = 0; 81cb93a386Sopenharmony_ci const int TR = nu; 82cb93a386Sopenharmony_ci const int BR = TR + nv; 83cb93a386Sopenharmony_ci const int BL = BR + nu; 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci SkScalar u = SkIntToScalar(iu) / nu; 86cb93a386Sopenharmony_ci SkScalar v = SkIntToScalar(iv) / nv; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci SkScalar uv = u * v; 89cb93a386Sopenharmony_ci SkScalar Uv = (1 - u) * v; 90cb93a386Sopenharmony_ci SkScalar uV = u * (1 - v); 91cb93a386Sopenharmony_ci SkScalar UV = (1 - u) * (1 - v); 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci SkScalar x0 = UV * edge[TL].fX + uV * edge[TR].fX + Uv * edge[BL].fX + uv * edge[BR].fX; 94cb93a386Sopenharmony_ci SkScalar y0 = UV * edge[TL].fY + uV * edge[TR].fY + Uv * edge[BL].fY + uv * edge[BR].fY; 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci SkScalar x = (1 - v) * edge[TL+iu].fX + u * edge[TR+iv].fX + 97cb93a386Sopenharmony_ci v * edge[BR+nu-iu].fX + (1 - u) * edge[BL+nv-iv].fX - x0; 98cb93a386Sopenharmony_ci SkScalar y = (1 - v) * edge[TL+iu].fY + u * edge[TR+iv].fY + 99cb93a386Sopenharmony_ci v * edge[BR+nu-iu].fY + (1 - u) * edge[BL+nv-iv].fY - y0; 100cb93a386Sopenharmony_ci pt->set(x, y); 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cistatic SkColor make_color(SkScalar s, SkScalar t) { 104cb93a386Sopenharmony_ci return SkColorSetARGB(0xFF, SkUnitScalarClampToByte(s), SkUnitScalarClampToByte(t), 0); 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_civoid Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv, 108cb93a386Sopenharmony_ci bool doTextures, bool doColors) { 109cb93a386Sopenharmony_ci if (nu < 1 || nv < 1) { 110cb93a386Sopenharmony_ci return; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci int i, npts = (nu + nv) * 2; 114cb93a386Sopenharmony_ci SkAutoSTMalloc<16, SkPoint> storage(npts + 1); 115cb93a386Sopenharmony_ci SkPoint* edge0 = storage.get(); 116cb93a386Sopenharmony_ci SkPoint* edge1 = edge0 + nu; 117cb93a386Sopenharmony_ci SkPoint* edge2 = edge1 + nv; 118cb93a386Sopenharmony_ci SkPoint* edge3 = edge2 + nu; 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci // evaluate the edge points 121cb93a386Sopenharmony_ci eval_patch_edge(fPts + 0, edge0, nu); 122cb93a386Sopenharmony_ci eval_patch_edge(fPts + 3, edge1, nv); 123cb93a386Sopenharmony_ci eval_patch_edge(fPts + 6, edge2, nu); 124cb93a386Sopenharmony_ci eval_patch_edge(fPts + 9, edge3, nv); 125cb93a386Sopenharmony_ci edge3[nv] = edge0[0]; // the last shall be first 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci for (i = 0; i < npts; i++) { 128cb93a386Sopenharmony_ci// canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci int row, vertCount = (nu + 1) * (nv + 1); 132cb93a386Sopenharmony_ci SkAutoTMalloc<SkPoint> vertStorage(vertCount); 133cb93a386Sopenharmony_ci SkPoint* verts = vertStorage.get(); 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci // first row 136cb93a386Sopenharmony_ci memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint)); 137cb93a386Sopenharmony_ci // rows 138cb93a386Sopenharmony_ci SkPoint* r = verts; 139cb93a386Sopenharmony_ci for (row = 1; row < nv; row++) { 140cb93a386Sopenharmony_ci r += nu + 1; 141cb93a386Sopenharmony_ci r[0] = edge3[nv - row]; 142cb93a386Sopenharmony_ci for (int col = 1; col < nu; col++) { 143cb93a386Sopenharmony_ci eval_sheet(edge0, nu, nv, col, row, &r[col]); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci r[nu] = edge1[row]; 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci // last row 148cb93a386Sopenharmony_ci SkPoint* last = verts + nv * (nu + 1); 149cb93a386Sopenharmony_ci for (i = 0; i <= nu; i++) { 150cb93a386Sopenharmony_ci last[i] = edge2[nu - i]; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci// canvas->drawPoints(verts, vertCount, paint); 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci int stripCount = (nu + 1) * 2; 156cb93a386Sopenharmony_ci SkAutoTMalloc<SkPoint> stripStorage(stripCount * 2); 157cb93a386Sopenharmony_ci SkAutoTMalloc<SkColor> colorStorage(stripCount); 158cb93a386Sopenharmony_ci SkPoint* strip = stripStorage.get(); 159cb93a386Sopenharmony_ci SkPoint* tex = strip + stripCount; 160cb93a386Sopenharmony_ci SkColor* colors = colorStorage.get(); 161cb93a386Sopenharmony_ci SkScalar t = 0; 162cb93a386Sopenharmony_ci const SkScalar ds = SK_Scalar1 * fW / nu; 163cb93a386Sopenharmony_ci const SkScalar dt = SK_Scalar1 * fH / nv; 164cb93a386Sopenharmony_ci r = verts; 165cb93a386Sopenharmony_ci for (row = 0; row < nv; row++) { 166cb93a386Sopenharmony_ci SkPoint* upper = r; 167cb93a386Sopenharmony_ci SkPoint* lower = r + nu + 1; 168cb93a386Sopenharmony_ci r = lower; 169cb93a386Sopenharmony_ci SkScalar s = 0; 170cb93a386Sopenharmony_ci for (i = 0; i <= nu; i++) { 171cb93a386Sopenharmony_ci strip[i*2 + 0] = *upper++; 172cb93a386Sopenharmony_ci strip[i*2 + 1] = *lower++; 173cb93a386Sopenharmony_ci tex[i*2 + 0].set(s, t); 174cb93a386Sopenharmony_ci tex[i*2 + 1].set(s, t + dt); 175cb93a386Sopenharmony_ci colors[i*2 + 0] = make_color(s/fW, t/fH); 176cb93a386Sopenharmony_ci colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH); 177cb93a386Sopenharmony_ci s += ds; 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci t += dt; 180cb93a386Sopenharmony_ci canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangleStrip_VertexMode, stripCount, 181cb93a386Sopenharmony_ci strip, doTextures ? tex : nullptr, 182cb93a386Sopenharmony_ci doColors ? colors : nullptr), 183cb93a386Sopenharmony_ci SkBlendMode::kModulate, paint); 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci} 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_cistatic void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv, 188cb93a386Sopenharmony_ci Patch* patch) { 189cb93a386Sopenharmony_ci SkAutoCanvasRestore ar(canvas, true); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci patch->draw(canvas, paint, nu, nv, false, false); 192cb93a386Sopenharmony_ci canvas->translate(SkIntToScalar(180), 0); 193cb93a386Sopenharmony_ci patch->draw(canvas, paint, nu, nv, true, false); 194cb93a386Sopenharmony_ci canvas->translate(SkIntToScalar(180), 0); 195cb93a386Sopenharmony_ci patch->draw(canvas, paint, nu, nv, false, true); 196cb93a386Sopenharmony_ci canvas->translate(SkIntToScalar(180), 0); 197cb93a386Sopenharmony_ci patch->draw(canvas, paint, nu, nv, true, true); 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_cistatic constexpr SkScalar DX = 20; 201cb93a386Sopenharmony_cistatic constexpr SkScalar DY = 0; 202cb93a386Sopenharmony_cistatic constexpr SkScalar kS = 50; 203cb93a386Sopenharmony_cistatic constexpr SkScalar kT = 40; 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_cistruct PatchView : public Sample { 206cb93a386Sopenharmony_ci sk_sp<SkShader> fShader0; 207cb93a386Sopenharmony_ci sk_sp<SkShader> fShader1; 208cb93a386Sopenharmony_ci SkScalar fAngle = 0; 209cb93a386Sopenharmony_ci SkIPoint fSize0 = {0, 0}, 210cb93a386Sopenharmony_ci fSize1 = {0, 0}; 211cb93a386Sopenharmony_ci SkPoint fPts[12] = { 212cb93a386Sopenharmony_ci {kS * 0, kT * 1}, 213cb93a386Sopenharmony_ci {kS * 1, kT * 1}, 214cb93a386Sopenharmony_ci {kS * 2, kT * 1}, 215cb93a386Sopenharmony_ci {kS * 3, kT * 1}, 216cb93a386Sopenharmony_ci {kS * 3, kT * 2}, 217cb93a386Sopenharmony_ci {kS * 3, kT * 3}, 218cb93a386Sopenharmony_ci {kS * 3, kT * 4}, 219cb93a386Sopenharmony_ci {kS * 2, kT * 4}, 220cb93a386Sopenharmony_ci {kS * 1, kT * 4}, 221cb93a386Sopenharmony_ci {kS * 0, kT * 4}, 222cb93a386Sopenharmony_ci {kS * 0, kT * 3}, 223cb93a386Sopenharmony_ci {kS * 0, kT * 2}, 224cb93a386Sopenharmony_ci }; 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 227cb93a386Sopenharmony_ci fShader0 = make_shader0(&fSize0); 228cb93a386Sopenharmony_ci fSize1 = fSize0; 229cb93a386Sopenharmony_ci if (fSize0.fX == 0 || fSize0.fY == 0) { 230cb93a386Sopenharmony_ci fSize1.set(2, 2); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci fShader1 = make_shader1(fSize1); 233cb93a386Sopenharmony_ci this->setBGColor(SK_ColorGRAY); 234cb93a386Sopenharmony_ci } 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci SkString name() override { return SkString("Patch"); } 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci void onDrawContent(SkCanvas* canvas) override { 239cb93a386Sopenharmony_ci const int nu = 10; 240cb93a386Sopenharmony_ci const int nv = 10; 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci SkPaint paint; 243cb93a386Sopenharmony_ci paint.setDither(true); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci canvas->translate(DX, DY); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci Patch patch; 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci paint.setShader(fShader0); 250cb93a386Sopenharmony_ci if (fSize0.fX == 0) { 251cb93a386Sopenharmony_ci fSize0.fX = 1; 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci if (fSize0.fY == 0) { 254cb93a386Sopenharmony_ci fSize0.fY = 1; 255cb93a386Sopenharmony_ci } 256cb93a386Sopenharmony_ci patch.setBounds(fSize0.fX, fSize0.fY); 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci patch.setPatch(fPts); 259cb93a386Sopenharmony_ci drawpatches(canvas, paint, nu, nv, &patch); 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ci paint.setShader(nullptr); 262cb93a386Sopenharmony_ci paint.setAntiAlias(true); 263cb93a386Sopenharmony_ci paint.setStrokeWidth(SkIntToScalar(5)); 264cb93a386Sopenharmony_ci canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint); 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci canvas->translate(0, SkIntToScalar(300)); 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci paint.setAntiAlias(false); 269cb93a386Sopenharmony_ci paint.setShader(fShader1); 270cb93a386Sopenharmony_ci { 271cb93a386Sopenharmony_ci SkMatrix m; 272cb93a386Sopenharmony_ci m.setSkew(1, 0); 273cb93a386Sopenharmony_ci paint.setShader(paint.getShader()->makeWithLocalMatrix(m)); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci { 276cb93a386Sopenharmony_ci SkMatrix m; 277cb93a386Sopenharmony_ci m.setRotate(fAngle); 278cb93a386Sopenharmony_ci paint.setShader(paint.getShader()->makeWithLocalMatrix(m)); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci patch.setBounds(fSize1.fX, fSize1.fY); 281cb93a386Sopenharmony_ci drawpatches(canvas, paint, nu, nv, &patch); 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { 285cb93a386Sopenharmony_ci fAngle = TimeUtils::Scaled(1e-9 * nanos, 60, 360); 286cb93a386Sopenharmony_ci return true; 287cb93a386Sopenharmony_ci } 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci class PtClick : public Click { 290cb93a386Sopenharmony_ci public: 291cb93a386Sopenharmony_ci int fIndex; 292cb93a386Sopenharmony_ci PtClick(int index) : fIndex(index) {} 293cb93a386Sopenharmony_ci }; 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) { 296cb93a386Sopenharmony_ci return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5); 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override { 300cb93a386Sopenharmony_ci x -= DX; 301cb93a386Sopenharmony_ci y -= DY; 302cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) { 303cb93a386Sopenharmony_ci if (hittest(fPts[i], x, y)) { 304cb93a386Sopenharmony_ci return new PtClick((int)i); 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci } 307cb93a386Sopenharmony_ci return nullptr; 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ci bool onClick(Click* click) override { 311cb93a386Sopenharmony_ci fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX - DX, click->fCurr.fY - DY); 312cb93a386Sopenharmony_ci return true; 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ciprivate: 316cb93a386Sopenharmony_ci using INHERITED = Sample; 317cb93a386Sopenharmony_ci}; 318cb93a386Sopenharmony_ci} // namespace 319cb93a386Sopenharmony_ciDEF_SAMPLE( return new PatchView(); ) 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_cinamespace { 324cb93a386Sopenharmony_cistatic sk_sp<SkVertices> make_verts(const SkPath& path, SkScalar width) { 325cb93a386Sopenharmony_ci auto meas = SkContourMeasureIter(path, false).next(); 326cb93a386Sopenharmony_ci if (!meas) { 327cb93a386Sopenharmony_ci return nullptr; 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci const SkPoint src[2] = { 331cb93a386Sopenharmony_ci { 0, -width/2 }, { 0, width/2 }, 332cb93a386Sopenharmony_ci }; 333cb93a386Sopenharmony_ci SkTDArray<SkPoint> pts; 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci const SkScalar step = 2; 336cb93a386Sopenharmony_ci for (SkScalar distance = 0; distance < meas->length(); distance += step) { 337cb93a386Sopenharmony_ci SkMatrix mx; 338cb93a386Sopenharmony_ci if (!meas->getMatrix(distance, &mx)) { 339cb93a386Sopenharmony_ci continue; 340cb93a386Sopenharmony_ci } 341cb93a386Sopenharmony_ci SkPoint* dst = pts.append(2); 342cb93a386Sopenharmony_ci mx.mapPoints(dst, src, 2); 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci int vertCount = pts.count(); 346cb93a386Sopenharmony_ci int indexCount = 0; // no texture 347cb93a386Sopenharmony_ci unsigned flags = SkVertices::kHasColors_BuilderFlag; 348cb93a386Sopenharmony_ci SkVertices::Builder builder(SkVertices::kTriangleStrip_VertexMode, 349cb93a386Sopenharmony_ci vertCount, indexCount, flags); 350cb93a386Sopenharmony_ci memcpy(builder.positions(), pts.begin(), vertCount * sizeof(SkPoint)); 351cb93a386Sopenharmony_ci SkRandom rand; 352cb93a386Sopenharmony_ci for (int i = 0; i < vertCount; ++i) { 353cb93a386Sopenharmony_ci builder.colors()[i] = rand.nextU() | 0xFF000000; 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci SkDebugf("vert count = %d\n", vertCount); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci return builder.detach(); 358cb93a386Sopenharmony_ci} 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ciclass PseudoInkView : public Sample { 361cb93a386Sopenharmony_ci enum { N = 100 }; 362cb93a386Sopenharmony_ci SkPath fPath; 363cb93a386Sopenharmony_ci sk_sp<SkVertices> fVertices[N]; 364cb93a386Sopenharmony_ci SkPaint fSkeletonP, fStrokeP, fVertsP; 365cb93a386Sopenharmony_ci bool fDirty = true; 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_cipublic: 368cb93a386Sopenharmony_ci PseudoInkView() { 369cb93a386Sopenharmony_ci fSkeletonP.setStyle(SkPaint::kStroke_Style); 370cb93a386Sopenharmony_ci fSkeletonP.setAntiAlias(true); 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci fStrokeP.setStyle(SkPaint::kStroke_Style); 373cb93a386Sopenharmony_ci fStrokeP.setStrokeWidth(30); 374cb93a386Sopenharmony_ci fStrokeP.setColor(0x44888888); 375cb93a386Sopenharmony_ci } 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ciprotected: 378cb93a386Sopenharmony_ci SkString name() override { return SkString("PseudoInk"); } 379cb93a386Sopenharmony_ci 380cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { return true; } 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci void onDrawContent(SkCanvas* canvas) override { 383cb93a386Sopenharmony_ci if (fDirty) { 384cb93a386Sopenharmony_ci for (int i = 0; i < N; ++i) { 385cb93a386Sopenharmony_ci fVertices[i] = make_verts(fPath, 30); 386cb93a386Sopenharmony_ci } 387cb93a386Sopenharmony_ci fDirty = false; 388cb93a386Sopenharmony_ci } 389cb93a386Sopenharmony_ci for (int i = 0; i < N; ++i) { 390cb93a386Sopenharmony_ci canvas->drawVertices(fVertices[i], SkBlendMode::kSrc, fVertsP); 391cb93a386Sopenharmony_ci canvas->translate(1, 1); 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci// canvas->drawPath(fPath, fStrokeP); 394cb93a386Sopenharmony_ci // canvas->drawPath(fPath, fSkeletonP); 395cb93a386Sopenharmony_ci } 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override { 398cb93a386Sopenharmony_ci Click* click = new Click(); 399cb93a386Sopenharmony_ci fPath.reset(); 400cb93a386Sopenharmony_ci fPath.moveTo(x, y); 401cb93a386Sopenharmony_ci return click; 402cb93a386Sopenharmony_ci } 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci bool onClick(Click* click) override { 405cb93a386Sopenharmony_ci switch (click->fState) { 406cb93a386Sopenharmony_ci case skui::InputState::kMove: 407cb93a386Sopenharmony_ci fPath.lineTo(click->fCurr); 408cb93a386Sopenharmony_ci fDirty = true; 409cb93a386Sopenharmony_ci break; 410cb93a386Sopenharmony_ci default: 411cb93a386Sopenharmony_ci break; 412cb93a386Sopenharmony_ci } 413cb93a386Sopenharmony_ci return true; 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_ciprivate: 417cb93a386Sopenharmony_ci using INHERITED = Sample; 418cb93a386Sopenharmony_ci}; 419cb93a386Sopenharmony_ci} // namespace 420cb93a386Sopenharmony_ciDEF_SAMPLE( return new PseudoInkView(); ) 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_cinamespace { 423cb93a386Sopenharmony_ci// Show stroking options using patheffects (and pathops) 424cb93a386Sopenharmony_ci// and why strokeandfill is a hacks 425cb93a386Sopenharmony_ciclass ManyStrokesView : public Sample { 426cb93a386Sopenharmony_ci SkPath fPath; 427cb93a386Sopenharmony_ci sk_sp<SkPathEffect> fPE[6]; 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_cipublic: 430cb93a386Sopenharmony_ci ManyStrokesView() { 431cb93a386Sopenharmony_ci fPE[0] = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap); 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci auto p0 = SkStrokePathEffect::Make(25, SkPaint::kRound_Join, SkPaint::kRound_Cap); 434cb93a386Sopenharmony_ci auto p1 = SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap); 435cb93a386Sopenharmony_ci fPE[1] = SkMergePathEffect::Make(p0, p1, SkPathOp::kDifference_SkPathOp); 436cb93a386Sopenharmony_ci 437cb93a386Sopenharmony_ci fPE[2] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kDifference_SkPathOp); 438cb93a386Sopenharmony_ci fPE[3] = SkMergePathEffect::Make(nullptr, p1, SkPathOp::kUnion_SkPathOp); 439cb93a386Sopenharmony_ci fPE[4] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kDifference_SkPathOp); 440cb93a386Sopenharmony_ci fPE[5] = SkMergePathEffect::Make(p0, nullptr, SkPathOp::kIntersect_SkPathOp); 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci 443cb93a386Sopenharmony_ciprotected: 444cb93a386Sopenharmony_ci SkString name() override { return SkString("ManyStrokes"); } 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { return true; } 447cb93a386Sopenharmony_ci 448cb93a386Sopenharmony_ci void dodraw(SkCanvas* canvas, sk_sp<SkPathEffect> pe, SkScalar x, SkScalar y, 449cb93a386Sopenharmony_ci const SkPaint* ptr = nullptr) { 450cb93a386Sopenharmony_ci SkPaint paint; 451cb93a386Sopenharmony_ci paint.setAntiAlias(true); 452cb93a386Sopenharmony_ci paint.setPathEffect(pe); 453cb93a386Sopenharmony_ci canvas->save(); 454cb93a386Sopenharmony_ci canvas->translate(x, y); 455cb93a386Sopenharmony_ci canvas->drawPath(fPath, ptr ? *ptr : paint); 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ci paint.setPathEffect(nullptr); 458cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 459cb93a386Sopenharmony_ci paint.setColor(SK_ColorGREEN); 460cb93a386Sopenharmony_ci canvas->drawPath(fPath, paint); 461cb93a386Sopenharmony_ci 462cb93a386Sopenharmony_ci canvas->restore(); 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci 465cb93a386Sopenharmony_ci void onDrawContent(SkCanvas* canvas) override { 466cb93a386Sopenharmony_ci SkPaint p; 467cb93a386Sopenharmony_ci p.setColor(0); 468cb93a386Sopenharmony_ci this->dodraw(canvas, nullptr, 0, 0, &p); 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[0], 300, 0); 471cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[1], 0, 300); 472cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[2], 300, 300); 473cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[3], 600, 300); 474cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[4], 900, 0); 475cb93a386Sopenharmony_ci this->dodraw(canvas, fPE[5], 900, 300); 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ci p.setColor(SK_ColorBLACK); 478cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStrokeAndFill_Style); 479cb93a386Sopenharmony_ci p.setStrokeJoin(SkPaint::kRound_Join); 480cb93a386Sopenharmony_ci p.setStrokeCap(SkPaint::kRound_Cap); 481cb93a386Sopenharmony_ci p.setStrokeWidth(20); 482cb93a386Sopenharmony_ci this->dodraw(canvas, nullptr, 600, 0, &p); 483cb93a386Sopenharmony_ci } 484cb93a386Sopenharmony_ci 485cb93a386Sopenharmony_ci Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override { 486cb93a386Sopenharmony_ci Click* click = new Click(); 487cb93a386Sopenharmony_ci fPath.reset(); 488cb93a386Sopenharmony_ci fPath.moveTo(x, y); 489cb93a386Sopenharmony_ci return click; 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_ci bool onClick(Click* click) override { 493cb93a386Sopenharmony_ci switch (click->fState) { 494cb93a386Sopenharmony_ci case skui::InputState::kMove: 495cb93a386Sopenharmony_ci fPath.lineTo(click->fCurr); 496cb93a386Sopenharmony_ci break; 497cb93a386Sopenharmony_ci default: 498cb93a386Sopenharmony_ci break; 499cb93a386Sopenharmony_ci } 500cb93a386Sopenharmony_ci return true; 501cb93a386Sopenharmony_ci } 502cb93a386Sopenharmony_ci 503cb93a386Sopenharmony_ciprivate: 504cb93a386Sopenharmony_ci using INHERITED = Sample; 505cb93a386Sopenharmony_ci}; 506cb93a386Sopenharmony_ci} // namespace 507cb93a386Sopenharmony_ciDEF_SAMPLE( return new ManyStrokesView(); ) 508