1 /*
2 * Copyright 2022 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/piet/Scene.h"
9
10 #include "include/core/SkTypes.h"
11
12 namespace skgpu::piet {
13 namespace {
14
get_piet_verb(SkPath::Verb verb,PgpuPathVerb * outVerb)15 bool get_piet_verb(SkPath::Verb verb, PgpuPathVerb* outVerb) {
16 switch (verb) {
17 case SkPath::kMove_Verb:
18 *outVerb = PgpuPathVerb::MoveTo;
19 break;
20 case SkPath::kLine_Verb:
21 *outVerb = PgpuPathVerb::LineTo;
22 break;
23 case SkPath::kQuad_Verb:
24 *outVerb = PgpuPathVerb::QuadTo;
25 break;
26 case SkPath::kConic_Verb:
27 case SkPath::kCubic_Verb:
28 *outVerb = PgpuPathVerb::CurveTo;
29 break;
30 case SkPath::kClose_Verb:
31 *outVerb = PgpuPathVerb::Close;
32 break;
33 case SkPath::kDone_Verb:
34 default:
35 return false;
36 }
37 return true;
38 }
39
get_fill_type(SkPathFillType fillType)40 PgpuFill get_fill_type(SkPathFillType fillType) {
41 switch (fillType) {
42 case SkPathFillType::kWinding:
43 return PgpuFill::NonZero;
44 case SkPathFillType::kEvenOdd:
45 return PgpuFill::EvenOdd;
46 default:
47 // TODO(b/238756757): pgpu-render doesn't define fill types for kInverseWinding and
48 // kInverseEvenOdd. This should be updated to support those cases.
49 SkDebugf("piet: unsupported fill type\n");
50 break;
51 }
52 return PgpuFill::NonZero;
53 }
54
55 } // namespace
56
Scene()57 Scene::Scene() : Object(pgpu_scene_new()) { SkASSERT(this->get() != nullptr); }
58
addPath(const SkPath & path,const Transform & transform)59 void Scene::addPath(const SkPath& path, const Transform& transform) {
60 this->initBuilderIfNecessary();
61
62 SkPath::Iter pathIter(path, /*forceClose=*/false);
63 PgpuPathIter iter;
64 iter.context = &pathIter;
65 iter.next_element = [](void* context, PgpuPathElement* outElem) {
66 SkASSERT(outElem);
67 SkASSERT(context);
68
69 SkPoint points[4];
70 SkPath::Verb verb = static_cast<SkPath::Iter*>(context)->next(points);
71 if (!get_piet_verb(verb, &outElem->verb)) {
72 return false;
73 }
74
75 for (int i = 0; i < 3; ++i) {
76 const SkPoint& p = points[i];
77 outElem->points[i] = {p.x(), p.y()};
78 }
79
80 return true;
81 };
82
83 pgpu_scene_builder_transform(fActiveBuilder->get(), &transform);
84 pgpu_scene_builder_fill_path(
85 fActiveBuilder->get(), get_fill_type(path.getFillType()), nullptr, nullptr, &iter);
86 }
87
finalize()88 bool Scene::finalize() {
89 if (!fActiveBuilder) {
90 return false;
91 }
92 fActiveBuilder.reset();
93 return true;
94 }
95
initBuilderIfNecessary()96 void Scene::initBuilderIfNecessary() {
97 if (!fActiveBuilder) {
98 fActiveBuilder = Builder(pgpu_scene_builder_for_scene(this->get()));
99 SkASSERT(fActiveBuilder);
100 }
101 }
102
103 } // namespace skgpu::piet
104