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