xref: /aosp_15_r20/external/skia/src/gpu/ganesh/geometry/GrShape.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrShape_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define GrShape_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkArc.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRRect.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTypeTraits.h"
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
22*c8dee2aaSAndroid Build Coastguard Worker #include <new>
23*c8dee2aaSAndroid Build Coastguard Worker #include <type_traits>
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker // Represents a line segment between two points.
26*c8dee2aaSAndroid Build Coastguard Worker struct GrLineSegment {
27*c8dee2aaSAndroid Build Coastguard Worker     SkPoint fP1;
28*c8dee2aaSAndroid Build Coastguard Worker     SkPoint fP2;
29*c8dee2aaSAndroid Build Coastguard Worker };
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker /**
32*c8dee2aaSAndroid Build Coastguard Worker  * GrShape is a convenience class to represent the many different specialized geometries that
33*c8dee2aaSAndroid Build Coastguard Worker  * Ganesh can handle, including rects, round rects, lines, as well as paths. It is intended as
34*c8dee2aaSAndroid Build Coastguard Worker  * a data-only class where any additional complex behavior is handled by an owning type (e.g.
35*c8dee2aaSAndroid Build Coastguard Worker  * GrStyledShape). However, it does include some basic utilities that unify common functionality
36*c8dee2aaSAndroid Build Coastguard Worker  * (such as contains()) from the underlying shape types.
37*c8dee2aaSAndroid Build Coastguard Worker  *
38*c8dee2aaSAndroid Build Coastguard Worker  * In order to have lossless simplification of the geometry, it also tracks winding direction, start
39*c8dee2aaSAndroid Build Coastguard Worker  * index, and fill inversion. The direction and index are match the SkPath indexing scheme for
40*c8dee2aaSAndroid Build Coastguard Worker  * the shape's type (e.g. rect, rrect, or oval).
41*c8dee2aaSAndroid Build Coastguard Worker  *
42*c8dee2aaSAndroid Build Coastguard Worker  * Regarding GrShape's empty shape:
43*c8dee2aaSAndroid Build Coastguard Worker  * - GrShape uses empty to refer to the absence of any geometric data
44*c8dee2aaSAndroid Build Coastguard Worker  * - SkRect::isEmpty() returns true if the rect is not sorted, even if it has area. GrShape will not
45*c8dee2aaSAndroid Build Coastguard Worker  *   simplify these shapes to an empty GrShape. Rects with actual 0 width and height will simplify
46*c8dee2aaSAndroid Build Coastguard Worker  *   to a point or line, not empty. This is to preserve geometric data for path effects and strokes.
47*c8dee2aaSAndroid Build Coastguard Worker  * - SkRRect::isEmpty() is true when the bounds have 0 width or height, so GrShape will simplify it
48*c8dee2aaSAndroid Build Coastguard Worker  *   to a point or line, just like a rect. SkRRect does not have the concept of unsorted edges.
49*c8dee2aaSAndroid Build Coastguard Worker  */
50*c8dee2aaSAndroid Build Coastguard Worker class GrShape {
51*c8dee2aaSAndroid Build Coastguard Worker public:
52*c8dee2aaSAndroid Build Coastguard Worker     // The current set of types GrShape can represent directly
53*c8dee2aaSAndroid Build Coastguard Worker     enum class Type : uint8_t {
54*c8dee2aaSAndroid Build Coastguard Worker         kEmpty, kPoint, kRect, kRRect, kPath, kArc, kLine
55*c8dee2aaSAndroid Build Coastguard Worker     };
56*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kTypeCount = static_cast<int>(Type::kLine) + 1;
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     // The direction and start index used when a shape does not have a representable winding,
59*c8dee2aaSAndroid Build Coastguard Worker     // or when that information was discarded during simplification (kIgnoreWinding_Flag).
60*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr SkPathDirection kDefaultDir   = SkPathDirection::kCW;
61*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr unsigned        kDefaultStart = 0;
62*c8dee2aaSAndroid Build Coastguard Worker     // The fill rule that is used by asPath() for shapes that aren't already a path.
63*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr SkPathFillType  kDefaultFillType = SkPathFillType::kEvenOdd;
64*c8dee2aaSAndroid Build Coastguard Worker 
GrShape()65*c8dee2aaSAndroid Build Coastguard Worker     GrShape() {}
GrShape(const SkPoint & point)66*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const SkPoint& point) { this->setPoint(point); }
GrShape(const SkRect & rect)67*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const SkRect& rect) { this->setRect(rect); }
GrShape(const SkRRect & rrect)68*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const SkRRect& rrect) { this->setRRect(rrect); }
GrShape(const SkPath & path)69*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const SkPath& path) { this->setPath(path); }
GrShape(const SkArc & arc)70*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const SkArc& arc) { this->setArc(arc); }
GrShape(const GrLineSegment & line)71*c8dee2aaSAndroid Build Coastguard Worker     explicit GrShape(const GrLineSegment& line){ this->setLine(line); }
72*c8dee2aaSAndroid Build Coastguard Worker 
GrShape(const GrShape & shape)73*c8dee2aaSAndroid Build Coastguard Worker     GrShape(const GrShape& shape) { *this = shape; }
74*c8dee2aaSAndroid Build Coastguard Worker 
~GrShape()75*c8dee2aaSAndroid Build Coastguard Worker     ~GrShape() { this->reset(); }
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     // NOTE: None of the geometry types benefit from move semantics, so we don't bother
78*c8dee2aaSAndroid Build Coastguard Worker     // defining a move assignment operator for GrShape.
79*c8dee2aaSAndroid Build Coastguard Worker     GrShape& operator=(const GrShape& shape);
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     // These type queries reflect the shape type provided when assigned, it does not incorporate
82*c8dee2aaSAndroid Build Coastguard Worker     // any potential simplification (e.g. if isRRect() is true and rrect().isRect() is true,
83*c8dee2aaSAndroid Build Coastguard Worker     // isRect() will still be false, until simplify() is called).
isEmpty()84*c8dee2aaSAndroid Build Coastguard Worker     bool isEmpty() const { return this->type() == Type::kEmpty; }
isPoint()85*c8dee2aaSAndroid Build Coastguard Worker     bool isPoint() const { return this->type() == Type::kPoint; }
isRect()86*c8dee2aaSAndroid Build Coastguard Worker     bool isRect() const { return this->type() == Type::kRect; }
isRRect()87*c8dee2aaSAndroid Build Coastguard Worker     bool isRRect() const { return this->type() == Type::kRRect; }
isPath()88*c8dee2aaSAndroid Build Coastguard Worker     bool isPath() const { return this->type() == Type::kPath; }
isArc()89*c8dee2aaSAndroid Build Coastguard Worker     bool isArc() const { return this->type() == Type::kArc; }
isLine()90*c8dee2aaSAndroid Build Coastguard Worker     bool isLine() const { return this->type() == Type::kLine; }
91*c8dee2aaSAndroid Build Coastguard Worker 
type()92*c8dee2aaSAndroid Build Coastguard Worker     Type type() const { return fType; }
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker     // Report the shape type, winding direction, start index, and invertedness as a value suitable
95*c8dee2aaSAndroid Build Coastguard Worker     // for use in a resource key. This does not include any geometry coordinates into the key value.
96*c8dee2aaSAndroid Build Coastguard Worker     uint32_t stateKey() const;
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker     // Whether or not the shape is meant to be the inverse of its geometry (i.e. its exterior).
inverted()99*c8dee2aaSAndroid Build Coastguard Worker     bool inverted() const {
100*c8dee2aaSAndroid Build Coastguard Worker         return this->isPath() ? fPath.isInverseFillType() : SkToBool(fInverted);
101*c8dee2aaSAndroid Build Coastguard Worker     }
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     // Returns the path direction extracted from the path during simplification, if the shape's
104*c8dee2aaSAndroid Build Coastguard Worker     // type represents a rrect, rect, or oval.
dir()105*c8dee2aaSAndroid Build Coastguard Worker     SkPathDirection dir() const { return fCW ? SkPathDirection::kCW : SkPathDirection::kCCW; }
106*c8dee2aaSAndroid Build Coastguard Worker     // Returns the start index extracted from the path during simplification, if the shape's
107*c8dee2aaSAndroid Build Coastguard Worker     // type represents a rrect, rect, or oval.
startIndex()108*c8dee2aaSAndroid Build Coastguard Worker     unsigned startIndex() const { return fStart; }
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker     // Override the direction and start parameters for the simplified contour. These are only
111*c8dee2aaSAndroid Build Coastguard Worker     // meaningful for rects, rrects, and ovals.
setPathWindingParams(SkPathDirection dir,unsigned start)112*c8dee2aaSAndroid Build Coastguard Worker     void setPathWindingParams(SkPathDirection dir, unsigned start) {
113*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT((this->isRect() && start < 4) || (this->isRRect() && start < 8) ||
114*c8dee2aaSAndroid Build Coastguard Worker                  (dir == kDefaultDir && start == kDefaultStart));
115*c8dee2aaSAndroid Build Coastguard Worker         fCW = dir == SkPathDirection::kCW;
116*c8dee2aaSAndroid Build Coastguard Worker         fStart = static_cast<uint8_t>(start);
117*c8dee2aaSAndroid Build Coastguard Worker     }
118*c8dee2aaSAndroid Build Coastguard Worker 
setInverted(bool inverted)119*c8dee2aaSAndroid Build Coastguard Worker     void setInverted(bool inverted) {
120*c8dee2aaSAndroid Build Coastguard Worker         if (this->isPath()) {
121*c8dee2aaSAndroid Build Coastguard Worker             if (inverted != fPath.isInverseFillType()) {
122*c8dee2aaSAndroid Build Coastguard Worker                 fPath.toggleInverseFillType();
123*c8dee2aaSAndroid Build Coastguard Worker             }
124*c8dee2aaSAndroid Build Coastguard Worker         } else {
125*c8dee2aaSAndroid Build Coastguard Worker             fInverted = inverted;
126*c8dee2aaSAndroid Build Coastguard Worker         }
127*c8dee2aaSAndroid Build Coastguard Worker     }
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     // Access the actual geometric description of the shape. May only access the appropriate type
130*c8dee2aaSAndroid Build Coastguard Worker     // based on what was last set. The type may change after simplify() is called.
point()131*c8dee2aaSAndroid Build Coastguard Worker     SkPoint& point() { SkASSERT(this->isPoint()); return fPoint; }
point()132*c8dee2aaSAndroid Build Coastguard Worker     const SkPoint& point() const { SkASSERT(this->isPoint()); return fPoint; }
133*c8dee2aaSAndroid Build Coastguard Worker 
rect()134*c8dee2aaSAndroid Build Coastguard Worker     SkRect& rect() { SkASSERT(this->isRect()); return fRect; }
rect()135*c8dee2aaSAndroid Build Coastguard Worker     const SkRect& rect() const { SkASSERT(this->isRect()); return fRect; }
136*c8dee2aaSAndroid Build Coastguard Worker 
rrect()137*c8dee2aaSAndroid Build Coastguard Worker     SkRRect& rrect() { SkASSERT(this->isRRect()); return fRRect; }
rrect()138*c8dee2aaSAndroid Build Coastguard Worker     const SkRRect& rrect() const { SkASSERT(this->isRRect()); return fRRect; }
139*c8dee2aaSAndroid Build Coastguard Worker 
path()140*c8dee2aaSAndroid Build Coastguard Worker     SkPath& path() { SkASSERT(this->isPath()); return fPath; }
path()141*c8dee2aaSAndroid Build Coastguard Worker     const SkPath& path() const { SkASSERT(this->isPath()); return fPath; }
142*c8dee2aaSAndroid Build Coastguard Worker 
arc()143*c8dee2aaSAndroid Build Coastguard Worker     SkArc& arc() { SkASSERT(this->isArc()); return fArc; }
arc()144*c8dee2aaSAndroid Build Coastguard Worker     const SkArc& arc() const { SkASSERT(this->isArc()); return fArc; }
145*c8dee2aaSAndroid Build Coastguard Worker 
line()146*c8dee2aaSAndroid Build Coastguard Worker     GrLineSegment& line() { SkASSERT(this->isLine()); return fLine; }
line()147*c8dee2aaSAndroid Build Coastguard Worker     const GrLineSegment& line() const { SkASSERT(this->isLine()); return fLine; }
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     // Update the geometry stored in the GrShape and update its associated type to match. This
150*c8dee2aaSAndroid Build Coastguard Worker     // performs no simplification, so calling setRRect() with a round rect that has isRect() return
151*c8dee2aaSAndroid Build Coastguard Worker     // true will still be considered an rrect by this shape until simplify() is called.
152*c8dee2aaSAndroid Build Coastguard Worker     //
153*c8dee2aaSAndroid Build Coastguard Worker     // These also reset any extracted direction, start, and inverted state from a prior simplified
154*c8dee2aaSAndroid Build Coastguard Worker     // path, since these functions ared used to describe a new geometry.
setPoint(const SkPoint & point)155*c8dee2aaSAndroid Build Coastguard Worker     void setPoint(const SkPoint& point) {
156*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kPoint);
157*c8dee2aaSAndroid Build Coastguard Worker         fPoint = point;
158*c8dee2aaSAndroid Build Coastguard Worker     }
setRect(const SkRect & rect)159*c8dee2aaSAndroid Build Coastguard Worker     void setRect(const SkRect& rect) {
160*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kRect);
161*c8dee2aaSAndroid Build Coastguard Worker         fRect = rect;
162*c8dee2aaSAndroid Build Coastguard Worker     }
setRRect(const SkRRect & rrect)163*c8dee2aaSAndroid Build Coastguard Worker     void setRRect(const SkRRect& rrect) {
164*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kRRect);
165*c8dee2aaSAndroid Build Coastguard Worker         fRRect = rrect;
166*c8dee2aaSAndroid Build Coastguard Worker     }
setArc(const SkArc & arc)167*c8dee2aaSAndroid Build Coastguard Worker     void setArc(const SkArc& arc) {
168*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kArc);
169*c8dee2aaSAndroid Build Coastguard Worker         fArc = arc;
170*c8dee2aaSAndroid Build Coastguard Worker     }
setLine(const GrLineSegment & line)171*c8dee2aaSAndroid Build Coastguard Worker     void setLine(const GrLineSegment& line) {
172*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kLine);
173*c8dee2aaSAndroid Build Coastguard Worker         fLine = line;
174*c8dee2aaSAndroid Build Coastguard Worker     }
setPath(const SkPath & path)175*c8dee2aaSAndroid Build Coastguard Worker     void setPath(const SkPath& path) {
176*c8dee2aaSAndroid Build Coastguard Worker         if (this->isPath()) {
177*c8dee2aaSAndroid Build Coastguard Worker             // Assign directly
178*c8dee2aaSAndroid Build Coastguard Worker             fPath = path;
179*c8dee2aaSAndroid Build Coastguard Worker         } else {
180*c8dee2aaSAndroid Build Coastguard Worker             // In-place initialize
181*c8dee2aaSAndroid Build Coastguard Worker             this->setType(Type::kPath);
182*c8dee2aaSAndroid Build Coastguard Worker             new (&fPath) SkPath(path);
183*c8dee2aaSAndroid Build Coastguard Worker         }
184*c8dee2aaSAndroid Build Coastguard Worker         // Must also set these since we didn't call reset() like other setX functions.
185*c8dee2aaSAndroid Build Coastguard Worker         this->setPathWindingParams(kDefaultDir, kDefaultStart);
186*c8dee2aaSAndroid Build Coastguard Worker         fInverted = path.isInverseFillType();
187*c8dee2aaSAndroid Build Coastguard Worker     }
reset()188*c8dee2aaSAndroid Build Coastguard Worker     void reset() {
189*c8dee2aaSAndroid Build Coastguard Worker         this->reset(Type::kEmpty);
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     // Flags that enable more aggressive, "destructive" simplifications to the geometry
193*c8dee2aaSAndroid Build Coastguard Worker     enum SimplifyFlags : unsigned {
194*c8dee2aaSAndroid Build Coastguard Worker         // If set, it is assumed the original shape would have been implicitly filled when drawn or
195*c8dee2aaSAndroid Build Coastguard Worker         // clipped, so simpler shape types that are closed can still be considered. Shapes with
196*c8dee2aaSAndroid Build Coastguard Worker         // 0 area (i.e. points and lines) can be turned into empty.
197*c8dee2aaSAndroid Build Coastguard Worker         kSimpleFill_Flag    = 0b001,
198*c8dee2aaSAndroid Build Coastguard Worker         // If set, simplifications that would impact a directional stroke or path effect can still
199*c8dee2aaSAndroid Build Coastguard Worker         // be taken (e.g. dir and start are not required, arcs can be converted to ovals).
200*c8dee2aaSAndroid Build Coastguard Worker         kIgnoreWinding_Flag = 0b010,
201*c8dee2aaSAndroid Build Coastguard Worker         // If set, the geometry will be updated to have sorted coordinates (rects, lines), modulated
202*c8dee2aaSAndroid Build Coastguard Worker         // sweep angles (arcs).
203*c8dee2aaSAndroid Build Coastguard Worker         kMakeCanonical_Flag = 0b100,
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker         kAll_Flags          = 0b111
206*c8dee2aaSAndroid Build Coastguard Worker     };
207*c8dee2aaSAndroid Build Coastguard Worker     // Returns true if the shape was originally closed based on type (or detected type within a
208*c8dee2aaSAndroid Build Coastguard Worker     // path), even if the final simplification results in a point, line, or empty.
209*c8dee2aaSAndroid Build Coastguard Worker     bool simplify(unsigned flags = kAll_Flags);
210*c8dee2aaSAndroid Build Coastguard Worker 
211*c8dee2aaSAndroid Build Coastguard Worker     // True if the given bounding box is completely inside the shape, if it's conservatively treated
212*c8dee2aaSAndroid Build Coastguard Worker     // as a filled, closed shape.
213*c8dee2aaSAndroid Build Coastguard Worker     bool conservativeContains(const SkRect& rect) const;
214*c8dee2aaSAndroid Build Coastguard Worker     bool conservativeContains(const SkPoint& point) const;
215*c8dee2aaSAndroid Build Coastguard Worker 
216*c8dee2aaSAndroid Build Coastguard Worker     // True if the underlying geometry represents a closed shape, without the need for an
217*c8dee2aaSAndroid Build Coastguard Worker     // implicit close (note that if simplified earlier with 'simpleFill' = true, a shape that was
218*c8dee2aaSAndroid Build Coastguard Worker     // not closed may become closed).
219*c8dee2aaSAndroid Build Coastguard Worker     bool closed() const;
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     // True if the underlying shape is known to be convex, assuming no other styles. If 'simpleFill'
222*c8dee2aaSAndroid Build Coastguard Worker     // is true, it is assumed the contours will be implicitly closed when drawn or used.
223*c8dee2aaSAndroid Build Coastguard Worker     bool convex(bool simpleFill = true) const;
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker     // The bounding box of the shape.
226*c8dee2aaSAndroid Build Coastguard Worker     SkRect bounds() const;
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker     // The segment masks that describe the shape, were it to be converted to an SkPath
229*c8dee2aaSAndroid Build Coastguard Worker     uint32_t segmentMask() const;
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker     // Convert the shape into a path that describes the same geometry.
232*c8dee2aaSAndroid Build Coastguard Worker     void asPath(SkPath* out, bool simpleFill = true) const;
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker     using sk_is_trivially_relocatable = std::true_type;
235*c8dee2aaSAndroid Build Coastguard Worker 
236*c8dee2aaSAndroid Build Coastguard Worker private:
237*c8dee2aaSAndroid Build Coastguard Worker 
setType(Type type)238*c8dee2aaSAndroid Build Coastguard Worker     void setType(Type type) {
239*c8dee2aaSAndroid Build Coastguard Worker         if (this->isPath() && type != Type::kPath) {
240*c8dee2aaSAndroid Build Coastguard Worker             fInverted = fPath.isInverseFillType();
241*c8dee2aaSAndroid Build Coastguard Worker             fPath.~SkPath();
242*c8dee2aaSAndroid Build Coastguard Worker         }
243*c8dee2aaSAndroid Build Coastguard Worker         fType = type;
244*c8dee2aaSAndroid Build Coastguard Worker     }
245*c8dee2aaSAndroid Build Coastguard Worker 
reset(Type type)246*c8dee2aaSAndroid Build Coastguard Worker     void reset(Type type) {
247*c8dee2aaSAndroid Build Coastguard Worker         this->setType(type);
248*c8dee2aaSAndroid Build Coastguard Worker         this->setPathWindingParams(kDefaultDir, kDefaultStart);
249*c8dee2aaSAndroid Build Coastguard Worker         this->setInverted(false);
250*c8dee2aaSAndroid Build Coastguard Worker     }
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker     // Paths and arcs are root shapes, another type will never simplify to them, so they do
253*c8dee2aaSAndroid Build Coastguard Worker     // not take the geometry to simplify as an argument. Since they are root shapes, they also
254*c8dee2aaSAndroid Build Coastguard Worker     // return whether or not they were originally closed before being simplified.
255*c8dee2aaSAndroid Build Coastguard Worker     bool simplifyPath(unsigned flags);
256*c8dee2aaSAndroid Build Coastguard Worker     bool simplifyArc(unsigned flags);
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker     // The simpler type classes do take the geometry because it may represent an in-progress
259*c8dee2aaSAndroid Build Coastguard Worker     // simplification that hasn't been set on the GrShape yet. The simpler types do not report
260*c8dee2aaSAndroid Build Coastguard Worker     // whether or not they were closed because it's implicit in their type.
261*c8dee2aaSAndroid Build Coastguard Worker     void simplifyLine(const SkPoint& p1, const SkPoint& p2, unsigned flags);
262*c8dee2aaSAndroid Build Coastguard Worker     void simplifyPoint(const SkPoint& point, unsigned flags);
263*c8dee2aaSAndroid Build Coastguard Worker 
264*c8dee2aaSAndroid Build Coastguard Worker     // RRects and rects care about winding for path effects and will set the path winding state
265*c8dee2aaSAndroid Build Coastguard Worker     // of the shape as well.
266*c8dee2aaSAndroid Build Coastguard Worker     void simplifyRRect(const SkRRect& rrect, SkPathDirection dir, unsigned start, unsigned flags);
267*c8dee2aaSAndroid Build Coastguard Worker     void simplifyRect(const SkRect& rect, SkPathDirection dir, unsigned start, unsigned flags);
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     union {
270*c8dee2aaSAndroid Build Coastguard Worker         SkPoint       fPoint;
271*c8dee2aaSAndroid Build Coastguard Worker         SkRect        fRect;
272*c8dee2aaSAndroid Build Coastguard Worker         SkRRect       fRRect;
273*c8dee2aaSAndroid Build Coastguard Worker         SkPath        fPath;
274*c8dee2aaSAndroid Build Coastguard Worker         SkArc         fArc;
275*c8dee2aaSAndroid Build Coastguard Worker         GrLineSegment fLine;
276*c8dee2aaSAndroid Build Coastguard Worker     };
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker     Type            fType = Type::kEmpty;
279*c8dee2aaSAndroid Build Coastguard Worker     uint8_t         fStart; // Restricted to rrects and simpler, so this will be < 8
280*c8dee2aaSAndroid Build Coastguard Worker     bool            fCW;
281*c8dee2aaSAndroid Build Coastguard Worker     bool            fInverted;
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fPoint)>::value);
284*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fRect)>::value);
285*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fRRect)>::value);
286*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fPath)>::value);
287*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fArc)>::value);
288*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fLine)>::value);
289*c8dee2aaSAndroid Build Coastguard Worker     static_assert(::sk_is_trivially_relocatable<decltype(fType)>::value);
290*c8dee2aaSAndroid Build Coastguard Worker };
291*c8dee2aaSAndroid Build Coastguard Worker 
292*c8dee2aaSAndroid Build Coastguard Worker #endif
293