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