1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google LLC. 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 "samplecode/Sample.h" 10cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 17cb93a386Sopenharmony_ci#include "src/gpu/ops/GrDrawOp.h" 18cb93a386Sopenharmony_ci#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h" 19cb93a386Sopenharmony_ci#include "src/gpu/ops/TessellationPathRenderer.h" 20cb93a386Sopenharmony_ci#include "src/gpu/tessellate/AffineMatrix.h" 21cb93a386Sopenharmony_ci#include "src/gpu/tessellate/PathCurveTessellator.h" 22cb93a386Sopenharmony_ci#include "src/gpu/tessellate/PathWedgeTessellator.h" 23cb93a386Sopenharmony_ci#include "src/gpu/tessellate/shaders/GrPathTessellationShader.h" 24cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h" 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cinamespace skgpu { 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciusing TrianglePatch = PatchWriter::TrianglePatch; 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cinamespace { 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cienum class Mode { 33cb93a386Sopenharmony_ci kWedgeMiddleOut, 34cb93a386Sopenharmony_ci kCurveMiddleOut, 35cb93a386Sopenharmony_ci kWedgeTessellate, 36cb93a386Sopenharmony_ci kCurveTessellate 37cb93a386Sopenharmony_ci}; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic const char* ModeName(Mode mode) { 40cb93a386Sopenharmony_ci switch (mode) { 41cb93a386Sopenharmony_ci case Mode::kWedgeMiddleOut: 42cb93a386Sopenharmony_ci return "MiddleOutShader (kWedges)"; 43cb93a386Sopenharmony_ci case Mode::kCurveMiddleOut: 44cb93a386Sopenharmony_ci return "MiddleOutShader (kCurves)"; 45cb93a386Sopenharmony_ci case Mode::kWedgeTessellate: 46cb93a386Sopenharmony_ci return "HardwareWedgeShader"; 47cb93a386Sopenharmony_ci case Mode::kCurveTessellate: 48cb93a386Sopenharmony_ci return "HardwareCurveShader"; 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci SkUNREACHABLE; 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci// Draws a path directly to the screen using a specific tessellator. 54cb93a386Sopenharmony_ciclass SamplePathTessellatorOp : public GrDrawOp { 55cb93a386Sopenharmony_ciprivate: 56cb93a386Sopenharmony_ci DEFINE_OP_CLASS_ID 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci SamplePathTessellatorOp(const SkRect& drawBounds, const SkPath& path, const SkMatrix& m, 59cb93a386Sopenharmony_ci GrPipeline::InputFlags pipelineFlags, Mode mode) 60cb93a386Sopenharmony_ci : GrDrawOp(ClassID()) 61cb93a386Sopenharmony_ci , fPath(path) 62cb93a386Sopenharmony_ci , fMatrix(m) 63cb93a386Sopenharmony_ci , fPipelineFlags(pipelineFlags) 64cb93a386Sopenharmony_ci , fMode(mode) { 65cb93a386Sopenharmony_ci this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci const char* name() const override { return "SamplePathTessellatorOp"; } 68cb93a386Sopenharmony_ci void visitProxies(const GrVisitProxyFunc&) const override {} 69cb93a386Sopenharmony_ci FixedFunctionFlags fixedFunctionFlags() const override { 70cb93a386Sopenharmony_ci return FixedFunctionFlags::kUsesHWAA; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip, 73cb93a386Sopenharmony_ci GrClampType clampType) override { 74cb93a386Sopenharmony_ci SkPMColor4f color; 75cb93a386Sopenharmony_ci return fProcessors.finalize(SK_PMColor4fWHITE, GrProcessorAnalysisCoverage::kNone, clip, 76cb93a386Sopenharmony_ci nullptr, caps, clampType, &color); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*, 79cb93a386Sopenharmony_ci const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override {} 80cb93a386Sopenharmony_ci void onPrepare(GrOpFlushState* flushState) override { 81cb93a386Sopenharmony_ci constexpr static SkPMColor4f kCyan = {0,1,1,1}; 82cb93a386Sopenharmony_ci auto alloc = flushState->allocator(); 83cb93a386Sopenharmony_ci const SkMatrix& shaderMatrix = SkMatrix::I(); 84cb93a386Sopenharmony_ci const SkMatrix& pathMatrix = fMatrix; 85cb93a386Sopenharmony_ci const GrCaps& caps = flushState->caps(); 86cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps = *caps.shaderCaps(); 87cb93a386Sopenharmony_ci int numVerbsToGetMiddleOut = 0; 88cb93a386Sopenharmony_ci int numVerbsToGetTessellation = caps.minPathVerbsForHwTessellation(); 89cb93a386Sopenharmony_ci auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState, std::move(fProcessors), 90cb93a386Sopenharmony_ci fPipelineFlags); 91cb93a386Sopenharmony_ci int numVerbs; 92cb93a386Sopenharmony_ci bool needsInnerFan; 93cb93a386Sopenharmony_ci switch (fMode) { 94cb93a386Sopenharmony_ci case Mode::kWedgeMiddleOut: 95cb93a386Sopenharmony_ci fTessellator = PathWedgeTessellator::Make(alloc, shaderCaps.infinitySupport()); 96cb93a386Sopenharmony_ci numVerbs = numVerbsToGetMiddleOut; 97cb93a386Sopenharmony_ci needsInnerFan = false; 98cb93a386Sopenharmony_ci break; 99cb93a386Sopenharmony_ci case Mode::kCurveMiddleOut: 100cb93a386Sopenharmony_ci fTessellator = PathCurveTessellator::Make(alloc, 101cb93a386Sopenharmony_ci shaderCaps.infinitySupport()); 102cb93a386Sopenharmony_ci numVerbs = numVerbsToGetMiddleOut; 103cb93a386Sopenharmony_ci needsInnerFan = true; 104cb93a386Sopenharmony_ci break; 105cb93a386Sopenharmony_ci case Mode::kWedgeTessellate: 106cb93a386Sopenharmony_ci fTessellator = PathWedgeTessellator::Make(alloc, shaderCaps.infinitySupport()); 107cb93a386Sopenharmony_ci numVerbs = numVerbsToGetTessellation; 108cb93a386Sopenharmony_ci needsInnerFan = false; 109cb93a386Sopenharmony_ci break; 110cb93a386Sopenharmony_ci case Mode::kCurveTessellate: 111cb93a386Sopenharmony_ci fTessellator = PathCurveTessellator::Make(alloc, 112cb93a386Sopenharmony_ci shaderCaps.infinitySupport()); 113cb93a386Sopenharmony_ci numVerbs = numVerbsToGetTessellation; 114cb93a386Sopenharmony_ci needsInnerFan = true; 115cb93a386Sopenharmony_ci break; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci auto* tessShader = GrPathTessellationShader::Make(alloc, 118cb93a386Sopenharmony_ci shaderMatrix, 119cb93a386Sopenharmony_ci kCyan, 120cb93a386Sopenharmony_ci numVerbs, 121cb93a386Sopenharmony_ci *pipeline, 122cb93a386Sopenharmony_ci fTessellator->patchAttribs(), 123cb93a386Sopenharmony_ci caps); 124cb93a386Sopenharmony_ci fProgram = GrTessellationShader::MakeProgram({alloc, flushState->writeView(), 125cb93a386Sopenharmony_ci flushState->usesMSAASurface(), 126cb93a386Sopenharmony_ci &flushState->dstProxyView(), 127cb93a386Sopenharmony_ci flushState->renderPassBarriers(), 128cb93a386Sopenharmony_ci GrLoadOp::kClear, &flushState->caps()}, 129cb93a386Sopenharmony_ci tessShader, 130cb93a386Sopenharmony_ci pipeline, 131cb93a386Sopenharmony_ci &GrUserStencilSettings::kUnused); 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci int patchPreallocCount = fTessellator->patchPreallocCount(fPath.countVerbs()); 135cb93a386Sopenharmony_ci if (needsInnerFan) { 136cb93a386Sopenharmony_ci patchPreallocCount += fPath.countVerbs() - 1; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci PatchWriter patchWriter(flushState, fTessellator, patchPreallocCount); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci if (needsInnerFan) { 141cb93a386Sopenharmony_ci // Write out inner fan triangles. 142cb93a386Sopenharmony_ci AffineMatrix m(pathMatrix); 143cb93a386Sopenharmony_ci for (PathMiddleOutFanIter it(fPath); !it.done();) { 144cb93a386Sopenharmony_ci for (auto [p0, p1, p2] : it.nextStack()) { 145cb93a386Sopenharmony_ci TrianglePatch(patchWriter) << m.map2Points(p0, p1) << m.mapPoint(p2); 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci // Write out the curves. 151cb93a386Sopenharmony_ci fTessellator->writePatches(patchWriter, 152cb93a386Sopenharmony_ci tessShader->maxTessellationSegments(*caps.shaderCaps()), 153cb93a386Sopenharmony_ci shaderMatrix, 154cb93a386Sopenharmony_ci {pathMatrix, fPath, kCyan}); 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci if (!tessShader->willUseTessellationShaders()) { 157cb93a386Sopenharmony_ci fTessellator->prepareFixedCountBuffers(flushState); 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override { 162cb93a386Sopenharmony_ci flushState->bindPipeline(*fProgram, chainBounds); 163cb93a386Sopenharmony_ci fTessellator->draw(flushState, fProgram->geomProc().willUseTessellationShaders()); 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci const SkPath fPath; 167cb93a386Sopenharmony_ci const SkMatrix fMatrix; 168cb93a386Sopenharmony_ci const GrPipeline::InputFlags fPipelineFlags; 169cb93a386Sopenharmony_ci const Mode fMode; 170cb93a386Sopenharmony_ci PathTessellator* fTessellator = nullptr; 171cb93a386Sopenharmony_ci GrProgramInfo* fProgram; 172cb93a386Sopenharmony_ci GrProcessorSet fProcessors{SkBlendMode::kSrcOver}; 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci friend class GrOp; // For ctor. 175cb93a386Sopenharmony_ci}; 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci} // namespace 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci// This sample enables wireframe and visualizes the triangles generated by path tessellators. 180cb93a386Sopenharmony_ciclass SamplePathTessellators : public Sample { 181cb93a386Sopenharmony_cipublic: 182cb93a386Sopenharmony_ci SamplePathTessellators() { 183cb93a386Sopenharmony_ci#if 0 184cb93a386Sopenharmony_ci // For viewing middle-out triangulations of the inner fan. 185cb93a386Sopenharmony_ci fPath.moveTo(1, 0); 186cb93a386Sopenharmony_ci int numSides = 32 * 3; 187cb93a386Sopenharmony_ci for (int i = 1; i < numSides; ++i) { 188cb93a386Sopenharmony_ci float theta = 2*3.1415926535897932384626433832785 * i / numSides; 189cb93a386Sopenharmony_ci fPath.lineTo(std::cos(theta), std::sin(theta)); 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci fPath.transform(SkMatrix::Scale(200, 200)); 192cb93a386Sopenharmony_ci fPath.transform(SkMatrix::Translate(300, 300)); 193cb93a386Sopenharmony_ci#else 194cb93a386Sopenharmony_ci fPath.moveTo(100, 500); 195cb93a386Sopenharmony_ci fPath.cubicTo(300, 400, -100, 300, 100, 200); 196cb93a386Sopenharmony_ci fPath.quadTo(250, 0, 400, 200); 197cb93a386Sopenharmony_ci fPath.conicTo(600, 350, 400, 500, fConicWeight); 198cb93a386Sopenharmony_ci fPath.close(); 199cb93a386Sopenharmony_ci#endif 200cb93a386Sopenharmony_ci } 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ciprivate: 203cb93a386Sopenharmony_ci void onDrawContent(SkCanvas*) override; 204cb93a386Sopenharmony_ci Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override; 205cb93a386Sopenharmony_ci bool onClick(Sample::Click*) override; 206cb93a386Sopenharmony_ci bool onChar(SkUnichar) override; 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci SkString name() override { return SkString("PathTessellators"); } 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci SkPath fPath; 211cb93a386Sopenharmony_ci GrPipeline::InputFlags fPipelineFlags = GrPipeline::InputFlags::kWireframe; 212cb93a386Sopenharmony_ci Mode fMode = Mode::kWedgeMiddleOut; 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci float fConicWeight = .5; 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci class Click; 217cb93a386Sopenharmony_ci}; 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_civoid SamplePathTessellators::onDrawContent(SkCanvas* canvas) { 220cb93a386Sopenharmony_ci canvas->clear(SK_ColorBLACK); 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ci auto ctx = canvas->recordingContext(); 223cb93a386Sopenharmony_ci auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas); 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci SkString error; 226cb93a386Sopenharmony_ci if (!sdc || !ctx) { 227cb93a386Sopenharmony_ci error = "GPU Only."; 228cb93a386Sopenharmony_ci } else if (!skgpu::v1::TessellationPathRenderer::IsSupported(*ctx->priv().caps())) { 229cb93a386Sopenharmony_ci error = "TessellationPathRenderer not supported."; 230cb93a386Sopenharmony_ci } else if (fMode >= Mode::kWedgeTessellate && 231cb93a386Sopenharmony_ci !ctx->priv().caps()->shaderCaps()->tessellationSupport()) { 232cb93a386Sopenharmony_ci error.printf("%s requires hardware tessellation support.", ModeName(fMode)); 233cb93a386Sopenharmony_ci } 234cb93a386Sopenharmony_ci if (!error.isEmpty()) { 235cb93a386Sopenharmony_ci canvas->clear(SK_ColorRED); 236cb93a386Sopenharmony_ci SkFont font(nullptr, 20); 237cb93a386Sopenharmony_ci SkPaint captionPaint; 238cb93a386Sopenharmony_ci captionPaint.setColor(SK_ColorWHITE); 239cb93a386Sopenharmony_ci canvas->drawString(error.c_str(), 10, 30, font, captionPaint); 240cb93a386Sopenharmony_ci return; 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci sdc->addDrawOp(GrOp::Make<SamplePathTessellatorOp>(ctx, 244cb93a386Sopenharmony_ci sdc->asRenderTargetProxy()->getBoundsRect(), 245cb93a386Sopenharmony_ci fPath, canvas->getTotalMatrix(), 246cb93a386Sopenharmony_ci fPipelineFlags, fMode)); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci // Draw the path points. 249cb93a386Sopenharmony_ci SkPaint pointsPaint; 250cb93a386Sopenharmony_ci pointsPaint.setColor(SK_ColorBLUE); 251cb93a386Sopenharmony_ci pointsPaint.setStrokeWidth(8); 252cb93a386Sopenharmony_ci SkPath devPath = fPath; 253cb93a386Sopenharmony_ci devPath.transform(canvas->getTotalMatrix()); 254cb93a386Sopenharmony_ci { 255cb93a386Sopenharmony_ci SkAutoCanvasRestore acr(canvas, true); 256cb93a386Sopenharmony_ci canvas->setMatrix(SkMatrix::I()); 257cb93a386Sopenharmony_ci SkString caption(ModeName(fMode)); 258cb93a386Sopenharmony_ci caption.appendf(" (w=%g)", fConicWeight); 259cb93a386Sopenharmony_ci SkFont font(nullptr, 20); 260cb93a386Sopenharmony_ci SkPaint captionPaint; 261cb93a386Sopenharmony_ci captionPaint.setColor(SK_ColorWHITE); 262cb93a386Sopenharmony_ci canvas->drawString(caption, 10, 30, font, captionPaint); 263cb93a386Sopenharmony_ci canvas->drawPoints(SkCanvas::kPoints_PointMode, devPath.countPoints(), 264cb93a386Sopenharmony_ci SkPathPriv::PointData(devPath), pointsPaint); 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci} 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ciclass SamplePathTessellators::Click : public Sample::Click { 269cb93a386Sopenharmony_cipublic: 270cb93a386Sopenharmony_ci Click(int ptIdx) : fPtIdx(ptIdx) {} 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci void doClick(SkPath* path) { 273cb93a386Sopenharmony_ci SkPoint pt = path->getPoint(fPtIdx); 274cb93a386Sopenharmony_ci SkPathPriv::UpdatePathPoint(path, fPtIdx, pt + fCurr - fPrev); 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ciprivate: 278cb93a386Sopenharmony_ci int fPtIdx; 279cb93a386Sopenharmony_ci}; 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ciSample::Click* SamplePathTessellators::onFindClickHandler(SkScalar x, SkScalar y, 282cb93a386Sopenharmony_ci skui::ModifierKey) { 283cb93a386Sopenharmony_ci const SkPoint* pts = SkPathPriv::PointData(fPath); 284cb93a386Sopenharmony_ci float fuzz = 30; 285cb93a386Sopenharmony_ci for (int i = 0; i < fPath.countPoints(); ++i) { 286cb93a386Sopenharmony_ci if (fabs(x - pts[i].x()) < fuzz && fabsf(y - pts[i].y()) < fuzz) { 287cb93a386Sopenharmony_ci return new Click(i); 288cb93a386Sopenharmony_ci } 289cb93a386Sopenharmony_ci } 290cb93a386Sopenharmony_ci return nullptr; 291cb93a386Sopenharmony_ci} 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_cibool SamplePathTessellators::onClick(Sample::Click* click) { 294cb93a386Sopenharmony_ci Click* myClick = (Click*)click; 295cb93a386Sopenharmony_ci myClick->doClick(&fPath); 296cb93a386Sopenharmony_ci return true; 297cb93a386Sopenharmony_ci} 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_cistatic SkPath update_weight(const SkPath& path, float w) { 300cb93a386Sopenharmony_ci SkPath path_; 301cb93a386Sopenharmony_ci for (auto [verb, pts, _] : SkPathPriv::Iterate(path)) { 302cb93a386Sopenharmony_ci switch (verb) { 303cb93a386Sopenharmony_ci case SkPathVerb::kMove: 304cb93a386Sopenharmony_ci path_.moveTo(pts[0]); 305cb93a386Sopenharmony_ci break; 306cb93a386Sopenharmony_ci case SkPathVerb::kLine: 307cb93a386Sopenharmony_ci path_.lineTo(pts[1]); 308cb93a386Sopenharmony_ci break; 309cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 310cb93a386Sopenharmony_ci path_.quadTo(pts[1], pts[2]); 311cb93a386Sopenharmony_ci break; 312cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 313cb93a386Sopenharmony_ci path_.cubicTo(pts[1], pts[2], pts[3]); 314cb93a386Sopenharmony_ci break; 315cb93a386Sopenharmony_ci case SkPathVerb::kConic: 316cb93a386Sopenharmony_ci path_.conicTo(pts[1], pts[2], (w != 1) ? w : .99f); 317cb93a386Sopenharmony_ci break; 318cb93a386Sopenharmony_ci case SkPathVerb::kClose: 319cb93a386Sopenharmony_ci break; 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci } 322cb93a386Sopenharmony_ci return path_; 323cb93a386Sopenharmony_ci} 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_cibool SamplePathTessellators::onChar(SkUnichar unichar) { 326cb93a386Sopenharmony_ci switch (unichar) { 327cb93a386Sopenharmony_ci case 'w': 328cb93a386Sopenharmony_ci fPipelineFlags = (GrPipeline::InputFlags)( 329cb93a386Sopenharmony_ci (int)fPipelineFlags ^ (int)GrPipeline::InputFlags::kWireframe); 330cb93a386Sopenharmony_ci return true; 331cb93a386Sopenharmony_ci case 'D': { 332cb93a386Sopenharmony_ci fPath.dump(); 333cb93a386Sopenharmony_ci return true; 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci case '+': 336cb93a386Sopenharmony_ci fConicWeight *= 2; 337cb93a386Sopenharmony_ci fPath = update_weight(fPath, fConicWeight); 338cb93a386Sopenharmony_ci return true; 339cb93a386Sopenharmony_ci case '=': 340cb93a386Sopenharmony_ci fConicWeight *= 5/4.f; 341cb93a386Sopenharmony_ci fPath = update_weight(fPath, fConicWeight); 342cb93a386Sopenharmony_ci return true; 343cb93a386Sopenharmony_ci case '_': 344cb93a386Sopenharmony_ci fConicWeight *= .5f; 345cb93a386Sopenharmony_ci fPath = update_weight(fPath, fConicWeight); 346cb93a386Sopenharmony_ci return true; 347cb93a386Sopenharmony_ci case '-': 348cb93a386Sopenharmony_ci fConicWeight *= 4/5.f; 349cb93a386Sopenharmony_ci fPath = update_weight(fPath, fConicWeight); 350cb93a386Sopenharmony_ci return true; 351cb93a386Sopenharmony_ci case '1': 352cb93a386Sopenharmony_ci case '2': 353cb93a386Sopenharmony_ci case '3': 354cb93a386Sopenharmony_ci case '4': 355cb93a386Sopenharmony_ci fMode = (Mode)(unichar - '1'); 356cb93a386Sopenharmony_ci return true; 357cb93a386Sopenharmony_ci } 358cb93a386Sopenharmony_ci return false; 359cb93a386Sopenharmony_ci} 360cb93a386Sopenharmony_ci 361cb93a386Sopenharmony_ciSample* MakeTessellatedPathSample() { return new SamplePathTessellators; } 362cb93a386Sopenharmony_cistatic SampleRegistry gTessellatedPathSample(MakeTessellatedPathSample); 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_ci} // namespace skgpu 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_ci#endif // SK_SUPPORT_GPU 367