1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc. 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 GrStyledShape_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define GrStyledShape_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathTypes.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRRect.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPathEnums.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPathPriv.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStyle.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrShape.h" 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker struct SkArc; 28*c8dee2aaSAndroid Build Coastguard Worker class SkIDChangeListener; 29*c8dee2aaSAndroid Build Coastguard Worker class SkPaint; 30*c8dee2aaSAndroid Build Coastguard Worker struct SkPoint; 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker /** 33*c8dee2aaSAndroid Build Coastguard Worker * Represents a geometric shape (rrect or path) and the GrStyle that it should be rendered with. 34*c8dee2aaSAndroid Build Coastguard Worker * It is possible to apply the style to the GrStyledShape to produce a new GrStyledShape where the 35*c8dee2aaSAndroid Build Coastguard Worker * geometry reflects the styling information (e.g. is stroked). It is also possible to apply just 36*c8dee2aaSAndroid Build Coastguard Worker * the path effect from the style. In this case the resulting shape will include any remaining 37*c8dee2aaSAndroid Build Coastguard Worker * stroking information that is to be applied after the path effect. 38*c8dee2aaSAndroid Build Coastguard Worker * 39*c8dee2aaSAndroid Build Coastguard Worker * Shapes can produce keys that represent only the geometry information, not the style. Note that 40*c8dee2aaSAndroid Build Coastguard Worker * when styling information is applied to produce a new shape then the style has been converted 41*c8dee2aaSAndroid Build Coastguard Worker * to geometric information and is included in the new shape's key. When the same style is applied 42*c8dee2aaSAndroid Build Coastguard Worker * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes 43*c8dee2aaSAndroid Build Coastguard Worker * will be the same. 44*c8dee2aaSAndroid Build Coastguard Worker * 45*c8dee2aaSAndroid Build Coastguard Worker * Currently this can only be constructed from a path, rect, or rrect though it can become a path 46*c8dee2aaSAndroid Build Coastguard Worker * applying style to the geometry. The idea is to expand this to cover most or all of the geometries 47*c8dee2aaSAndroid Build Coastguard Worker * that have fast paths in the GPU backend. 48*c8dee2aaSAndroid Build Coastguard Worker */ 49*c8dee2aaSAndroid Build Coastguard Worker class GrStyledShape { 50*c8dee2aaSAndroid Build Coastguard Worker public: 51*c8dee2aaSAndroid Build Coastguard Worker // Keys for paths may be extracted from the path data for small paths. Clients aren't supposed 52*c8dee2aaSAndroid Build Coastguard Worker // to have to worry about this. This value is exposed for unit tests. 53*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kMaxKeyFromDataVerbCnt = 10; 54*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape()55*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape() {} 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker enum class DoSimplify : bool { kNo = false, kYes }; 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker explicit GrStyledShape(const SkPath& path, DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(path,GrStyle::SimpleFill (),doSimplify)60*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(path, GrStyle::SimpleFill(), doSimplify) {} 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker explicit GrStyledShape(const SkRRect& rrect, DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(rrect,GrStyle::SimpleFill (),doSimplify)63*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(rrect, GrStyle::SimpleFill(), doSimplify) {} 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker explicit GrStyledShape(const SkRect& rect, DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(rect,GrStyle::SimpleFill (),doSimplify)66*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(rect, GrStyle::SimpleFill(), doSimplify) {} 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkPath& path, const SkPaint& paint, 69*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(path,GrStyle (paint),doSimplify)70*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(path, GrStyle(paint), doSimplify) {} 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkRRect& rrect, const SkPaint& paint, 73*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(rrect,GrStyle (paint),doSimplify)74*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(rrect, GrStyle(paint), doSimplify) {} 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkRect& rect, const SkPaint& paint, 77*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) GrStyledShape(rect,GrStyle (paint),doSimplify)78*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(rect, GrStyle(paint), doSimplify) {} 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkPath& path, const GrStyle& style, 81*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) fShape(path)82*c8dee2aaSAndroid Build Coastguard Worker : fShape(path), fStyle(style) { 83*c8dee2aaSAndroid Build Coastguard Worker if (doSimplify == DoSimplify::kYes) { 84*c8dee2aaSAndroid Build Coastguard Worker this->simplify(); 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker } 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkRRect& rrect, const GrStyle& style, 89*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) 90*c8dee2aaSAndroid Build Coastguard Worker // Preserve legacy indices (6 for CW), see SkPathBuilder::addRRect(). 91*c8dee2aaSAndroid Build Coastguard Worker : GrStyledShape(rrect, SkPathDirection::kCW, 6, false, style, doSimplify) {} 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkRRect& rrect, SkPathDirection dir, unsigned start, bool inverted, 94*c8dee2aaSAndroid Build Coastguard Worker const GrStyle& style, DoSimplify doSimplify = DoSimplify::kYes) fShape(rrect)95*c8dee2aaSAndroid Build Coastguard Worker : fShape(rrect) 96*c8dee2aaSAndroid Build Coastguard Worker , fStyle(style) { 97*c8dee2aaSAndroid Build Coastguard Worker fShape.setPathWindingParams(dir, start); 98*c8dee2aaSAndroid Build Coastguard Worker fShape.setInverted(inverted); 99*c8dee2aaSAndroid Build Coastguard Worker if (doSimplify == DoSimplify::kYes) { 100*c8dee2aaSAndroid Build Coastguard Worker this->simplify(); 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const SkRect& rect, const GrStyle& style, 105*c8dee2aaSAndroid Build Coastguard Worker DoSimplify doSimplify = DoSimplify::kYes) fShape(rect)106*c8dee2aaSAndroid Build Coastguard Worker : fShape(rect), fStyle(style) { 107*c8dee2aaSAndroid Build Coastguard Worker if (doSimplify == DoSimplify::kYes) { 108*c8dee2aaSAndroid Build Coastguard Worker this->simplify(); 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker } 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const GrStyledShape&); 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker static GrStyledShape MakeArc(const SkArc& arc, 115*c8dee2aaSAndroid Build Coastguard Worker const GrStyle& style, 116*c8dee2aaSAndroid Build Coastguard Worker DoSimplify = DoSimplify::kYes); 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape& operator=(const GrStyledShape& that); 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker /** 121*c8dee2aaSAndroid Build Coastguard Worker * Informs MakeFilled on how to modify that shape's fill rule when making a simple filled 122*c8dee2aaSAndroid Build Coastguard Worker * version of the shape. 123*c8dee2aaSAndroid Build Coastguard Worker */ 124*c8dee2aaSAndroid Build Coastguard Worker enum class FillInversion { 125*c8dee2aaSAndroid Build Coastguard Worker kPreserve, 126*c8dee2aaSAndroid Build Coastguard Worker kFlip, 127*c8dee2aaSAndroid Build Coastguard Worker kForceNoninverted, 128*c8dee2aaSAndroid Build Coastguard Worker kForceInverted 129*c8dee2aaSAndroid Build Coastguard Worker }; 130*c8dee2aaSAndroid Build Coastguard Worker /** 131*c8dee2aaSAndroid Build Coastguard Worker * Makes a filled shape from the pre-styled original shape and optionally modifies whether 132*c8dee2aaSAndroid Build Coastguard Worker * the fill is inverted or not. It's important to note that the original shape's geometry 133*c8dee2aaSAndroid Build Coastguard Worker * may already have been modified if doing so was neutral with respect to its style 134*c8dee2aaSAndroid Build Coastguard Worker * (e.g. filled paths are always closed when stored in a shape and dashed paths are always 135*c8dee2aaSAndroid Build Coastguard Worker * made non-inverted since dashing ignores inverseness). 136*c8dee2aaSAndroid Build Coastguard Worker */ 137*c8dee2aaSAndroid Build Coastguard Worker static GrStyledShape MakeFilled(const GrStyledShape& original, 138*c8dee2aaSAndroid Build Coastguard Worker FillInversion = FillInversion::kPreserve); 139*c8dee2aaSAndroid Build Coastguard Worker style()140*c8dee2aaSAndroid Build Coastguard Worker const GrStyle& style() const { return fStyle; } 141*c8dee2aaSAndroid Build Coastguard Worker 142*c8dee2aaSAndroid Build Coastguard Worker // True if the shape and/or style were modified into a simpler, equivalent pairing simplified()143*c8dee2aaSAndroid Build Coastguard Worker bool simplified() const { return fSimplified; } 144*c8dee2aaSAndroid Build Coastguard Worker 145*c8dee2aaSAndroid Build Coastguard Worker /** 146*c8dee2aaSAndroid Build Coastguard Worker * Returns a shape that has either applied the path effect or path effect and stroking 147*c8dee2aaSAndroid Build Coastguard Worker * information from this shape's style to its geometry. Scale is used when approximating the 148*c8dee2aaSAndroid Build Coastguard Worker * output geometry and typically is computed from the view matrix 149*c8dee2aaSAndroid Build Coastguard Worker */ applyStyle(GrStyle::Apply apply,SkScalar scale)150*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape applyStyle(GrStyle::Apply apply, SkScalar scale) const { 151*c8dee2aaSAndroid Build Coastguard Worker return GrStyledShape(*this, apply, scale); 152*c8dee2aaSAndroid Build Coastguard Worker } 153*c8dee2aaSAndroid Build Coastguard Worker isRect()154*c8dee2aaSAndroid Build Coastguard Worker bool isRect() const { 155*c8dee2aaSAndroid Build Coastguard Worker // Should have simplified a rrect to a rect if possible already. 156*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fShape.isRRect() || !fShape.rrect().isRect()); 157*c8dee2aaSAndroid Build Coastguard Worker return fShape.isRect(); 158*c8dee2aaSAndroid Build Coastguard Worker } 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker /** Returns the unstyled geometry as a rrect if possible. */ 161*c8dee2aaSAndroid Build Coastguard Worker bool asRRect(SkRRect* rrect, bool* inverted) const; 162*c8dee2aaSAndroid Build Coastguard Worker 163*c8dee2aaSAndroid Build Coastguard Worker /** 164*c8dee2aaSAndroid Build Coastguard Worker * If the unstyled shape is a straight line segment, returns true and sets pts to the endpoints. 165*c8dee2aaSAndroid Build Coastguard Worker * An inverse filled line path is still considered a line. 166*c8dee2aaSAndroid Build Coastguard Worker */ 167*c8dee2aaSAndroid Build Coastguard Worker bool asLine(SkPoint pts[2], bool* inverted) const; 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker // Can this shape be drawn as a pair of filled nested rectangles? 170*c8dee2aaSAndroid Build Coastguard Worker bool asNestedRects(SkRect rects[2]) const; 171*c8dee2aaSAndroid Build Coastguard Worker 172*c8dee2aaSAndroid Build Coastguard Worker /** Returns the unstyled geometry as a path. */ asPath(SkPath * out)173*c8dee2aaSAndroid Build Coastguard Worker void asPath(SkPath* out) const { 174*c8dee2aaSAndroid Build Coastguard Worker fShape.asPath(out, fStyle.isSimpleFill()); 175*c8dee2aaSAndroid Build Coastguard Worker } 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Worker /** 178*c8dee2aaSAndroid Build Coastguard Worker * Returns whether the geometry is empty. Note that applying the style could produce a 179*c8dee2aaSAndroid Build Coastguard Worker * non-empty shape. It also may have an inverse fill. 180*c8dee2aaSAndroid Build Coastguard Worker */ isEmpty()181*c8dee2aaSAndroid Build Coastguard Worker bool isEmpty() const { return fShape.isEmpty(); } 182*c8dee2aaSAndroid Build Coastguard Worker 183*c8dee2aaSAndroid Build Coastguard Worker /** 184*c8dee2aaSAndroid Build Coastguard Worker * Gets the bounds of the geometry without reflecting the shape's styling. This ignores 185*c8dee2aaSAndroid Build Coastguard Worker * the inverse fill nature of the geometry. 186*c8dee2aaSAndroid Build Coastguard Worker */ bounds()187*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds() const { return fShape.bounds(); } 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker /** 190*c8dee2aaSAndroid Build Coastguard Worker * Gets the bounds of the geometry reflecting the shape's styling (ignoring inverse fill 191*c8dee2aaSAndroid Build Coastguard Worker * status). 192*c8dee2aaSAndroid Build Coastguard Worker */ 193*c8dee2aaSAndroid Build Coastguard Worker SkRect styledBounds() const; 194*c8dee2aaSAndroid Build Coastguard Worker 195*c8dee2aaSAndroid Build Coastguard Worker /** 196*c8dee2aaSAndroid Build Coastguard Worker * Is this shape known to be convex, before styling is applied. An unclosed but otherwise 197*c8dee2aaSAndroid Build Coastguard Worker * convex path is considered to be closed if they styling reflects a fill and not otherwise. 198*c8dee2aaSAndroid Build Coastguard Worker * This is because filling closes all contours in the path. 199*c8dee2aaSAndroid Build Coastguard Worker */ knownToBeConvex()200*c8dee2aaSAndroid Build Coastguard Worker bool knownToBeConvex() const { 201*c8dee2aaSAndroid Build Coastguard Worker return fShape.convex(fStyle.isSimpleFill()); 202*c8dee2aaSAndroid Build Coastguard Worker } 203*c8dee2aaSAndroid Build Coastguard Worker 204*c8dee2aaSAndroid Build Coastguard Worker /** 205*c8dee2aaSAndroid Build Coastguard Worker * Does the shape have a known winding direction. Some degenerate convex shapes may not have 206*c8dee2aaSAndroid Build Coastguard Worker * a computable direction, but this is not always a requirement for path renderers so it is 207*c8dee2aaSAndroid Build Coastguard Worker * kept separate from knownToBeConvex(). 208*c8dee2aaSAndroid Build Coastguard Worker */ knownDirection()209*c8dee2aaSAndroid Build Coastguard Worker bool knownDirection() const { 210*c8dee2aaSAndroid Build Coastguard Worker // Assuming this is called after knownToBeConvex(), this should just be relying on 211*c8dee2aaSAndroid Build Coastguard Worker // cached convexity and direction and will be cheap. 212*c8dee2aaSAndroid Build Coastguard Worker return !fShape.isPath() || 213*c8dee2aaSAndroid Build Coastguard Worker SkPathPriv::ComputeFirstDirection(fShape.path()) != SkPathFirstDirection::kUnknown; 214*c8dee2aaSAndroid Build Coastguard Worker } 215*c8dee2aaSAndroid Build Coastguard Worker 216*c8dee2aaSAndroid Build Coastguard Worker /** Is the pre-styled geometry inverse filled? */ inverseFilled()217*c8dee2aaSAndroid Build Coastguard Worker bool inverseFilled() const { 218*c8dee2aaSAndroid Build Coastguard Worker // Since the path tracks inverted-fillness itself, it should match what was recorded. 219*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fShape.isPath() || fShape.inverted() == fShape.path().isInverseFillType()); 220*c8dee2aaSAndroid Build Coastguard Worker // Dashing ignores inverseness. We should have caught this earlier. skbug.com/5421 221*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!(fShape.inverted() && this->style().isDashed())); 222*c8dee2aaSAndroid Build Coastguard Worker return fShape.inverted(); 223*c8dee2aaSAndroid Build Coastguard Worker } 224*c8dee2aaSAndroid Build Coastguard Worker 225*c8dee2aaSAndroid Build Coastguard Worker /** 226*c8dee2aaSAndroid Build Coastguard Worker * Might applying the styling to the geometry produce an inverse fill. The "may" part comes in 227*c8dee2aaSAndroid Build Coastguard Worker * because an arbitrary path effect could produce an inverse filled path. In other cases this 228*c8dee2aaSAndroid Build Coastguard Worker * can be thought of as "inverseFilledAfterStyling()". 229*c8dee2aaSAndroid Build Coastguard Worker */ mayBeInverseFilledAfterStyling()230*c8dee2aaSAndroid Build Coastguard Worker bool mayBeInverseFilledAfterStyling() const { 231*c8dee2aaSAndroid Build Coastguard Worker // An arbitrary path effect can produce an arbitrary output path, which may be inverse 232*c8dee2aaSAndroid Build Coastguard Worker // filled. 233*c8dee2aaSAndroid Build Coastguard Worker if (this->style().hasNonDashPathEffect()) { 234*c8dee2aaSAndroid Build Coastguard Worker return true; 235*c8dee2aaSAndroid Build Coastguard Worker } 236*c8dee2aaSAndroid Build Coastguard Worker return this->inverseFilled(); 237*c8dee2aaSAndroid Build Coastguard Worker } 238*c8dee2aaSAndroid Build Coastguard Worker 239*c8dee2aaSAndroid Build Coastguard Worker /** 240*c8dee2aaSAndroid Build Coastguard Worker * Is it known that the unstyled geometry has no unclosed contours. This means that it will 241*c8dee2aaSAndroid Build Coastguard Worker * not have any caps if stroked (modulo the effect of any path effect). 242*c8dee2aaSAndroid Build Coastguard Worker */ knownToBeClosed()243*c8dee2aaSAndroid Build Coastguard Worker bool knownToBeClosed() const { 244*c8dee2aaSAndroid Build Coastguard Worker // This refers to the base shape and does not depend on invertedness. 245*c8dee2aaSAndroid Build Coastguard Worker return fShape.closed(); 246*c8dee2aaSAndroid Build Coastguard Worker } 247*c8dee2aaSAndroid Build Coastguard Worker segmentMask()248*c8dee2aaSAndroid Build Coastguard Worker uint32_t segmentMask() const { 249*c8dee2aaSAndroid Build Coastguard Worker // This refers to the base shape and does not depend on invertedness. 250*c8dee2aaSAndroid Build Coastguard Worker return fShape.segmentMask(); 251*c8dee2aaSAndroid Build Coastguard Worker } 252*c8dee2aaSAndroid Build Coastguard Worker 253*c8dee2aaSAndroid Build Coastguard Worker /** 254*c8dee2aaSAndroid Build Coastguard Worker * Gets the size of the key for the shape represented by this GrStyledShape (ignoring its 255*c8dee2aaSAndroid Build Coastguard Worker * styling). A negative value is returned if the shape has no key (shouldn't be cached). 256*c8dee2aaSAndroid Build Coastguard Worker */ 257*c8dee2aaSAndroid Build Coastguard Worker int unstyledKeySize() const; 258*c8dee2aaSAndroid Build Coastguard Worker hasUnstyledKey()259*c8dee2aaSAndroid Build Coastguard Worker bool hasUnstyledKey() const { return this->unstyledKeySize() >= 0; } 260*c8dee2aaSAndroid Build Coastguard Worker 261*c8dee2aaSAndroid Build Coastguard Worker /** 262*c8dee2aaSAndroid Build Coastguard Worker * Writes unstyledKeySize() bytes into the provided pointer. Assumes that there is enough 263*c8dee2aaSAndroid Build Coastguard Worker * space allocated for the key and that unstyledKeySize() does not return a negative value 264*c8dee2aaSAndroid Build Coastguard Worker * for this shape. 265*c8dee2aaSAndroid Build Coastguard Worker */ 266*c8dee2aaSAndroid Build Coastguard Worker void writeUnstyledKey(uint32_t* key) const; 267*c8dee2aaSAndroid Build Coastguard Worker 268*c8dee2aaSAndroid Build Coastguard Worker /** 269*c8dee2aaSAndroid Build Coastguard Worker * Adds a listener to the *original* path. Typically used to invalidate cached resources when 270*c8dee2aaSAndroid Build Coastguard Worker * a path is no longer in-use. If the shape started out as something other than a path, this 271*c8dee2aaSAndroid Build Coastguard Worker * does nothing. 272*c8dee2aaSAndroid Build Coastguard Worker */ 273*c8dee2aaSAndroid Build Coastguard Worker void addGenIDChangeListener(sk_sp<SkIDChangeListener>) const; 274*c8dee2aaSAndroid Build Coastguard Worker 275*c8dee2aaSAndroid Build Coastguard Worker /** 276*c8dee2aaSAndroid Build Coastguard Worker * Helpers that are only exposed for unit tests, to determine if the shape is a path, and get 277*c8dee2aaSAndroid Build Coastguard Worker * the generation ID of the *original* path. This is the path that will receive 278*c8dee2aaSAndroid Build Coastguard Worker * GenIDChangeListeners added to this shape. 279*c8dee2aaSAndroid Build Coastguard Worker */ 280*c8dee2aaSAndroid Build Coastguard Worker uint32_t testingOnly_getOriginalGenerationID() const; 281*c8dee2aaSAndroid Build Coastguard Worker bool testingOnly_isPath() const; 282*c8dee2aaSAndroid Build Coastguard Worker bool testingOnly_isNonVolatilePath() const; 283*c8dee2aaSAndroid Build Coastguard Worker 284*c8dee2aaSAndroid Build Coastguard Worker /** 285*c8dee2aaSAndroid Build Coastguard Worker * Similar to GrShape::simplify but also takes into account style and stroking, possibly 286*c8dee2aaSAndroid Build Coastguard Worker * applying the style explicitly to produce a new analytic shape with a simpler style. 287*c8dee2aaSAndroid Build Coastguard Worker * Unless "doSimplify" is kNo, this method gets called automatically during construction. 288*c8dee2aaSAndroid Build Coastguard Worker */ 289*c8dee2aaSAndroid Build Coastguard Worker void simplify(); 290*c8dee2aaSAndroid Build Coastguard Worker 291*c8dee2aaSAndroid Build Coastguard Worker private: 292*c8dee2aaSAndroid Build Coastguard Worker /** Constructor used by the applyStyle() function */ 293*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape(const GrStyledShape& parentShape, GrStyle::Apply, SkScalar scale); 294*c8dee2aaSAndroid Build Coastguard Worker 295*c8dee2aaSAndroid Build Coastguard Worker /** 296*c8dee2aaSAndroid Build Coastguard Worker * Determines the key we should inherit from the input shape's geometry and style when 297*c8dee2aaSAndroid Build Coastguard Worker * we are applying the style to create a new shape. 298*c8dee2aaSAndroid Build Coastguard Worker */ 299*c8dee2aaSAndroid Build Coastguard Worker void setInheritedKey(const GrStyledShape& parentShape, GrStyle::Apply, SkScalar scale); 300*c8dee2aaSAndroid Build Coastguard Worker 301*c8dee2aaSAndroid Build Coastguard Worker /** 302*c8dee2aaSAndroid Build Coastguard Worker * As part of the simplification process, some shapes can have stroking trivially evaluated 303*c8dee2aaSAndroid Build Coastguard Worker * and form a new geometry with just a fill. 304*c8dee2aaSAndroid Build Coastguard Worker */ 305*c8dee2aaSAndroid Build Coastguard Worker void simplifyStroke(); 306*c8dee2aaSAndroid Build Coastguard Worker 307*c8dee2aaSAndroid Build Coastguard Worker /** Gets the path that gen id listeners should be added to. */ 308*c8dee2aaSAndroid Build Coastguard Worker const SkPath* originalPathForListeners() const; 309*c8dee2aaSAndroid Build Coastguard Worker 310*c8dee2aaSAndroid Build Coastguard Worker GrShape fShape; 311*c8dee2aaSAndroid Build Coastguard Worker GrStyle fStyle; 312*c8dee2aaSAndroid Build Coastguard Worker // Gen ID of the original path (path may be modified or simplified away). 313*c8dee2aaSAndroid Build Coastguard Worker int32_t fGenID = 0; 314*c8dee2aaSAndroid Build Coastguard Worker bool fClosed = false; 315*c8dee2aaSAndroid Build Coastguard Worker bool fSimplified = false; 316*c8dee2aaSAndroid Build Coastguard Worker 317*c8dee2aaSAndroid Build Coastguard Worker SkTLazy<SkPath> fInheritedPathForListeners; 318*c8dee2aaSAndroid Build Coastguard Worker skia_private::AutoSTArray<8, uint32_t> fInheritedKey; 319*c8dee2aaSAndroid Build Coastguard Worker }; 320*c8dee2aaSAndroid Build Coastguard Worker #endif 321