• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef skgpu_graphite_geom_Geometry_DEFINED
9 #define skgpu_graphite_geom_Geometry_DEFINED
10 
11 #include "include/core/SkVertices.h"
12 #include "src/core/SkVerticesPriv.h"
13 #include "src/gpu/graphite/geom/EdgeAAQuad.h"
14 #include "src/gpu/graphite/geom/Rect.h"
15 #include "src/gpu/graphite/geom/Shape.h"
16 #include "src/gpu/graphite/geom/SubRunData.h"
17 
18 namespace skgpu::graphite {
19 
20 /**
21  * Geometry is a container that can house Shapes, SkVertices, text SubRuns, and per-edge AA quads.
22  * TODO - Add unit tests for Geometry.
23  */
24 class Geometry {
25 public:
26     enum class Type : uint8_t {
27         kEmpty, kShape, kVertices, kSubRun, kEdgeAAQuad
28     };
29 
Geometry()30     Geometry() {}
Geometry(Geometry && geom)31     Geometry(Geometry&& geom) { *this = std::move(geom); }
Geometry(const Geometry & geom)32     Geometry(const Geometry& geom) { *this = geom; }
33 
Geometry(const Shape & shape)34     explicit Geometry(const Shape& shape) { this->setShape(shape); }
Geometry(const SubRunData & subrun)35     explicit Geometry(const SubRunData& subrun) { this->setSubRun(subrun); }
Geometry(sk_sp<SkVertices> vertices)36     explicit Geometry(sk_sp<SkVertices> vertices) { this->setVertices(vertices); }
Geometry(const EdgeAAQuad & edgeAAQuad)37     explicit Geometry(const EdgeAAQuad& edgeAAQuad) { this->setEdgeAAQuad(edgeAAQuad); }
38 
~Geometry()39     ~Geometry() { this->setType(Type::kEmpty); }
40 
41     Geometry& operator=(Geometry&& geom) {
42         if (this != &geom) {
43             switch (geom.type()) {
44                 case Type::kEmpty:
45                     this->setType(Type::kEmpty);
46                     break;
47                 case Type::kShape:
48                     this->setShape(geom.shape());
49                     geom.setType(Type::kEmpty);
50                     break;
51                 case Type::kVertices:
52                     this->setVertices(std::move(geom.fVertices));
53                     geom.setType(Type::kEmpty);
54                     break;
55                 case Type::kSubRun:
56                     this->setSubRun(geom.subRunData());
57                     geom.setType(Type::kEmpty);
58                     break;
59                 case Type::kEdgeAAQuad:
60                     this->setEdgeAAQuad(geom.edgeAAQuad());
61                     geom.setType(Type::kEmpty);
62                     break;
63             }
64         }
65         return *this;
66     }
67     Geometry& operator=(const Geometry& geom) {
68         switch (geom.type()) {
69             case Type::kEmpty: this->setType(Type::kEmpty); break;
70             case Type::kShape: this->setShape(geom.shape()); break;
71             case Type::kSubRun: this->setSubRun(geom.subRunData()); break;
72             case Type::kVertices: this->setVertices(geom.fVertices); break;
73             case Type::kEdgeAAQuad: this->setEdgeAAQuad(geom.edgeAAQuad()); break;
74             default: break;
75         }
76         return *this;
77     }
78 
type()79     Type type() const { return fType; }
80 
isShape()81     bool isShape() const { return fType == Type::kShape; }
isVertices()82     bool isVertices() const { return fType == Type::kVertices; }
isSubRun()83     bool isSubRun() const { return fType == Type::kSubRun; }
isEdgeAAQuad()84     bool isEdgeAAQuad() const { return fType == Type::kEdgeAAQuad; }
isEmpty()85     bool isEmpty() const {
86         return fType == (Type::kEmpty) || (this->isShape() && this->shape().isEmpty());
87     }
88 
shape()89     const Shape& shape() const { SkASSERT(this->isShape()); return fShape; }
subRunData()90     const SubRunData& subRunData() const { SkASSERT(this->isSubRun()); return fSubRunData; }
edgeAAQuad()91     const EdgeAAQuad& edgeAAQuad() const { SkASSERT(this->isEdgeAAQuad()); return fEdgeAAQuad; }
vertices()92     const SkVertices* vertices() const { SkASSERT(this->isVertices()); return fVertices.get(); }
refVertices()93     sk_sp<SkVertices> refVertices() const {
94         SkASSERT(this->isVertices());
95         return fVertices;
96     }
97 
setShape(const Shape & shape)98     void setShape(const Shape& shape) {
99         if (fType == Type::kShape) {
100             fShape = shape;
101         } else {
102             this->setType(Type::kShape);
103             new (&fShape) Shape(shape);
104         }
105     }
setSubRun(const SubRunData & subRun)106     void setSubRun(const SubRunData& subRun) {
107         if (fType == Type::kSubRun) {
108             fSubRunData = subRun;
109         } else {
110             this->setType(Type::kSubRun);
111             new (&fSubRunData) SubRunData(subRun);
112         }
113     }
setVertices(sk_sp<SkVertices> vertices)114     void setVertices(sk_sp<SkVertices> vertices) {
115         if (fType == Type::kVertices) {
116             fVertices = std::move(vertices);
117         } else {
118             this->setType(Type::kVertices);
119             new (&fVertices) sk_sp<SkVertices>(std::move(vertices));
120         }
121     }
122 
setEdgeAAQuad(const EdgeAAQuad & edgeAAQuad)123     void setEdgeAAQuad(const EdgeAAQuad& edgeAAQuad) {
124         if (fType == Type::kEdgeAAQuad) {
125             fEdgeAAQuad = edgeAAQuad;
126         } else {
127             this->setType(Type::kEdgeAAQuad);
128             new (&fEdgeAAQuad) EdgeAAQuad(edgeAAQuad);
129         }
130     }
131 
bounds()132     Rect bounds() const {
133         switch (fType) {
134             case Type::kEmpty: return Rect(0, 0, 0, 0);
135             case Type::kShape: return fShape.bounds();
136             case Type::kVertices: return fVertices->bounds();
137             case Type::kSubRun: return fSubRunData.bounds();
138             case Type::kEdgeAAQuad: return fEdgeAAQuad.bounds();
139         }
140         SkUNREACHABLE;
141     }
142 
143 private:
setType(Type type)144     void setType(Type type) {
145         static_assert(std::is_trivially_destructible<EdgeAAQuad>::value);
146         if (this->isShape() && type != Type::kShape) {
147             fShape.~Shape();
148         } else if (this->isSubRun() && type != Type::kSubRun) {
149             fSubRunData.~SubRunData();
150         } else if (this->isVertices() && type != Type::kVertices) {
151             fVertices.~sk_sp<SkVertices>();
152         }
153         fType = type;
154     }
155 
156     Type fType = Type::kEmpty;
157     union {
158         Shape fShape;
159         SubRunData fSubRunData;
160         sk_sp<SkVertices> fVertices;
161         EdgeAAQuad fEdgeAAQuad;
162     };
163 };
164 
165 } // namespace skgpu::graphite
166 
167 #endif // skgpu_graphite_geom_Geometry_DEFINED
168