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