| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef GrShape_DEFINED | 8 #ifndef GrShape_DEFINED |
| 9 #define GrShape_DEFINED | 9 #define GrShape_DEFINED |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 GrShape() : fType(Type::kEmpty) {} | 37 GrShape() : fType(Type::kEmpty) {} |
| 38 | 38 |
| 39 explicit GrShape(const SkPath& path) | 39 explicit GrShape(const SkPath& path) |
| 40 : fType(Type::kPath) | 40 : fType(Type::kPath) |
| 41 , fPath(&path) { | 41 , fPath(&path) { |
| 42 this->attemptToReduceFromPath(); | 42 this->attemptToReduceFromPath(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 explicit GrShape(const SkRRect& rrect) | 45 explicit GrShape(const SkRRect& rrect) |
| 46 : fType(Type::kRRect) | 46 : fType(Type::kRRect) |
| 47 , fRRect(rrect) { | 47 , fRRect(rrect) |
| 48 , fRRectIsInverted(false) { |
| 48 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir); | 49 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir); |
| 49 this->attemptToReduceFromRRect(); | 50 this->attemptToReduceFromRRect(); |
| 50 } | 51 } |
| 51 | 52 |
| 52 explicit GrShape(const SkRect& rect) | 53 explicit GrShape(const SkRect& rect) |
| 53 : fType(Type::kRRect) | 54 : fType(Type::kRRect) |
| 54 , fRRect(SkRRect::MakeRect(rect)) { | 55 , fRRect(SkRRect::MakeRect(rect)) |
| 56 , fRRectIsInverted(false) { |
| 55 fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir); | 57 fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir); |
| 56 this->attemptToReduceFromRRect(); | 58 this->attemptToReduceFromRRect(); |
| 57 } | 59 } |
| 58 | 60 |
| 59 GrShape(const SkPath& path, const GrStyle& style) | 61 GrShape(const SkPath& path, const GrStyle& style) |
| 60 : fType(Type::kPath) | 62 : fType(Type::kPath) |
| 61 , fPath(&path) | 63 , fPath(&path) |
| 62 , fStyle(style) { | 64 , fStyle(style) { |
| 63 this->attemptToReduceFromPath(); | 65 this->attemptToReduceFromPath(); |
| 64 } | 66 } |
| 65 | 67 |
| 66 GrShape(const SkRRect& rrect, const GrStyle& style) | 68 GrShape(const SkRRect& rrect, const GrStyle& style) |
| 67 : fType(Type::kRRect) | 69 : fType(Type::kRRect) |
| 68 , fRRect(rrect) | 70 , fRRect(rrect) |
| 71 , fRRectIsInverted(false) |
| 69 , fStyle(style) { | 72 , fStyle(style) { |
| 70 fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(),
&fRRectDir); | 73 fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(),
&fRRectDir); |
| 71 this->attemptToReduceFromRRect(); | 74 this->attemptToReduceFromRRect(); |
| 72 } | 75 } |
| 73 | 76 |
| 74 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, const G
rStyle& style) | 77 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool in
verted, |
| 78 const GrStyle& style) |
| 75 : fType(Type::kRRect) | 79 : fType(Type::kRRect) |
| 76 , fRRect(rrect) | 80 , fRRect(rrect) |
| 81 , fRRectIsInverted(inverted) |
| 77 , fStyle(style) { | 82 , fStyle(style) { |
| 78 if (style.pathEffect()) { | 83 if (style.pathEffect()) { |
| 79 fRRectDir = dir; | 84 fRRectDir = dir; |
| 80 fRRectStart = start; | 85 fRRectStart = start; |
| 86 if (fRRect.getType() == SkRRect::kRect_Type) { |
| 87 fRRectStart = (fRRectStart + 1) & 0b110; |
| 88 } else if (fRRect.getType() == SkRRect::kOval_Type) { |
| 89 fRRectStart &= 0b110; |
| 90 } |
| 81 } else { | 91 } else { |
| 82 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir)
; | 92 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir)
; |
| 83 } | 93 } |
| 84 this->attemptToReduceFromRRect(); | 94 this->attemptToReduceFromRRect(); |
| 85 } | 95 } |
| 86 | 96 |
| 87 GrShape(const SkRect& rect, const GrStyle& style) | 97 GrShape(const SkRect& rect, const GrStyle& style) |
| 88 : fType(Type::kRRect) | 98 : fType(Type::kRRect) |
| 89 , fRRect(SkRRect::MakeRect(rect)) | 99 , fRRect(SkRRect::MakeRect(rect)) |
| 100 , fRRectIsInverted(false) |
| 90 , fStyle(style) { | 101 , fStyle(style) { |
| 91 fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), &
fRRectDir); | 102 fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), &
fRRectDir); |
| 92 this->attemptToReduceFromRRect(); | 103 this->attemptToReduceFromRRect(); |
| 93 } | 104 } |
| 94 | 105 |
| 95 GrShape(const SkPath& path, const SkPaint& paint) | 106 GrShape(const SkPath& path, const SkPaint& paint) |
| 96 : fType(Type::kPath) | 107 : fType(Type::kPath) |
| 97 , fPath(&path) | 108 , fPath(&path) |
| 98 , fStyle(paint) { | 109 , fStyle(paint) { |
| 99 this->attemptToReduceFromPath(); | 110 this->attemptToReduceFromPath(); |
| 100 } | 111 } |
| 101 | 112 |
| 102 GrShape(const SkRRect& rrect, const SkPaint& paint) | 113 GrShape(const SkRRect& rrect, const SkPaint& paint) |
| 103 : fType(Type::kRRect) | 114 : fType(Type::kRRect) |
| 104 , fRRect(rrect) | 115 , fRRect(rrect) |
| 116 , fRRectIsInverted(false) |
| 105 , fStyle(paint) { | 117 , fStyle(paint) { |
| 106 fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect()
, &fRRectDir); | 118 fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect()
, &fRRectDir); |
| 107 this->attemptToReduceFromRRect(); | 119 this->attemptToReduceFromRRect(); |
| 108 } | 120 } |
| 109 | 121 |
| 110 GrShape(const SkRect& rect, const SkPaint& paint) | 122 GrShape(const SkRect& rect, const SkPaint& paint) |
| 111 : fType(Type::kRRect) | 123 : fType(Type::kRRect) |
| 112 , fRRect(SkRRect::MakeRect(rect)) | 124 , fRRect(SkRRect::MakeRect(rect)) |
| 125 , fRRectIsInverted(false) |
| 113 , fStyle(paint) { | 126 , fStyle(paint) { |
| 114 fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(),
&fRRectDir); | 127 fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(),
&fRRectDir); |
| 115 this->attemptToReduceFromRRect(); | 128 this->attemptToReduceFromRRect(); |
| 116 } | 129 } |
| 117 | 130 |
| 118 GrShape(const GrShape&); | 131 GrShape(const GrShape&); |
| 119 GrShape& operator=(const GrShape& that); | 132 GrShape& operator=(const GrShape& that); |
| 120 | 133 |
| 121 ~GrShape() { | 134 ~GrShape() { |
| 122 if (Type::kPath == fType) { | 135 if (Type::kPath == fType) { |
| 123 fPath.reset(); | 136 fPath.reset(); |
| 124 } | 137 } |
| 125 } | 138 } |
| 126 | 139 |
| 127 const GrStyle& style() const { return fStyle; } | 140 const GrStyle& style() const { return fStyle; } |
| 128 | 141 |
| 129 /** | 142 /** |
| 130 * Returns a shape that has either applied the path effect or path effect an
d stroking | 143 * Returns a shape that has either applied the path effect or path effect an
d stroking |
| 131 * information from this shape's style to its geometry. Scale is used when a
pproximating the | 144 * information from this shape's style to its geometry. Scale is used when a
pproximating the |
| 132 * output geometry and typically is computed from the view matrix | 145 * output geometry and typically is computed from the view matrix |
| 133 */ | 146 */ |
| 134 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) { | 147 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) { |
| 135 return GrShape(*this, apply, scale); | 148 return GrShape(*this, apply, scale); |
| 136 } | 149 } |
| 137 | 150 |
| 138 /** Returns the unstyled geometry as a rrect if possible. */ | 151 /** Returns the unstyled geometry as a rrect if possible. */ |
| 139 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start) const
{ | 152 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start, bool*
inverted) const { |
| 140 if (Type::kRRect != fType) { | 153 if (Type::kRRect != fType) { |
| 141 return false; | 154 return false; |
| 142 } | 155 } |
| 143 if (rrect) { | 156 if (rrect) { |
| 144 *rrect = fRRect; | 157 *rrect = fRRect; |
| 145 } | 158 } |
| 146 if (dir) { | 159 if (dir) { |
| 147 *dir = fRRectDir; | 160 *dir = fRRectDir; |
| 148 } | 161 } |
| 149 if (start) { | 162 if (start) { |
| 150 *start = fRRectStart; | 163 *start = fRRectStart; |
| 151 } | 164 } |
| 165 if (inverted) { |
| 166 *inverted = fRRectIsInverted; |
| 167 } |
| 152 return true; | 168 return true; |
| 153 } | 169 } |
| 154 | 170 |
| 155 /** Returns the unstyled geometry as a path. */ | 171 /** Returns the unstyled geometry as a path. */ |
| 156 void asPath(SkPath* out) const { | 172 void asPath(SkPath* out) const { |
| 157 switch (fType) { | 173 switch (fType) { |
| 158 case Type::kEmpty: | 174 case Type::kEmpty: |
| 159 out->reset(); | 175 out->reset(); |
| 160 break; | 176 break; |
| 161 case Type::kRRect: | 177 case Type::kRRect: |
| 162 out->reset(); | 178 out->reset(); |
| 163 out->addRRect(fRRect, fRRectDir, fRRectStart); | 179 out->addRRect(fRRect, fRRectDir, fRRectStart); |
| 180 if (fRRectIsInverted) { |
| 181 out->setFillType(SkPath::kInverseWinding_FillType); |
| 182 } |
| 164 break; | 183 break; |
| 165 case Type::kPath: | 184 case Type::kPath: |
| 166 *out = *fPath.get(); | 185 *out = *fPath.get(); |
| 167 break; | 186 break; |
| 168 } | 187 } |
| 169 } | 188 } |
| 170 | 189 |
| 171 /** | 190 /** |
| 172 * Returns whether the geometry is empty. Note that applying the style could
produce a | 191 * Returns whether the geometry is empty. Note that applying the style could
produce a |
| 173 * non-empty shape. | 192 * non-empty shape. |
| 174 */ | 193 */ |
| 175 bool isEmpty() const { return Type::kEmpty == fType; } | 194 bool isEmpty() const { return Type::kEmpty == fType; } |
| 176 | 195 |
| 177 /** Gets the bounds of the geometry without reflecting the shape's styling.
*/ | 196 /** |
| 197 * Gets the bounds of the geometry without reflecting the shape's styling. T
his ignores |
| 198 * the inverse fill nature of the geometry. |
| 199 */ |
| 178 const SkRect& bounds() const; | 200 const SkRect& bounds() const; |
| 179 | 201 |
| 180 /** Gets the bounds of the geometry reflecting the shape's styling. */ | 202 /** |
| 203 * Gets the bounds of the geometry reflecting the shape's styling (ignoring
inverse fill |
| 204 * status). |
| 205 */ |
| 181 void styledBounds(SkRect* bounds) const; | 206 void styledBounds(SkRect* bounds) const; |
| 182 | 207 |
| 183 /** | 208 /** |
| 184 * Is it known that the unstyled geometry has no unclosed contours. This mea
ns that it will | 209 * Is it known that the unstyled geometry has no unclosed contours. This mea
ns that it will |
| 185 * not have any caps if stroked (modulo the effect of any path effect). | 210 * not have any caps if stroked (modulo the effect of any path effect). |
| 186 */ | 211 */ |
| 187 bool knownToBeClosed() const { | 212 bool knownToBeClosed() const { |
| 188 switch (fType) { | 213 switch (fType) { |
| 189 case Type::kEmpty: | 214 case Type::kEmpty: |
| 190 return true; | 215 return true; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 263 |
| 239 /** | 264 /** |
| 240 * Determines the key we should inherit from the input shape's geometry and
style when | 265 * Determines the key we should inherit from the input shape's geometry and
style when |
| 241 * we are applying the style to create a new shape. | 266 * we are applying the style to create a new shape. |
| 242 */ | 267 */ |
| 243 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc
ale); | 268 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc
ale); |
| 244 | 269 |
| 245 void attemptToReduceFromPath() { | 270 void attemptToReduceFromPath() { |
| 246 SkASSERT(Type::kPath == fType); | 271 SkASSERT(Type::kPath == fType); |
| 247 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, &
fRRectStart, | 272 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, &
fRRectStart, |
| 248 fStyle.pathEffect(), fStyle.strokeRe
c()); | 273 &fRRectIsInverted, fStyle.pathEffect
(), |
| 274 fStyle.strokeRec()); |
| 249 if (Type::kPath != fType) { | 275 if (Type::kPath != fType) { |
| 250 fPath.reset(); | 276 fPath.reset(); |
| 251 fInheritedKey.reset(0); | 277 fInheritedKey.reset(0); |
| 252 } | 278 } |
| 253 } | 279 } |
| 254 | 280 |
| 255 void attemptToReduceFromRRect() { | 281 void attemptToReduceFromRRect() { |
| 256 SkASSERT(Type::kRRect == fType); | 282 SkASSERT(Type::kRRect == fType); |
| 257 SkASSERT(!fInheritedKey.count()); | 283 SkASSERT(!fInheritedKey.count()); |
| 258 if (fRRect.isEmpty()) { | 284 if (fRRectIsInverted) { |
| 285 if (!fStyle.hasNonDashPathEffect()) { |
| 286 SkStrokeRec::Style recStyle = fStyle.strokeRec().getStyle(); |
| 287 if (SkStrokeRec::kStroke_Style == recStyle || |
| 288 SkStrokeRec::kHairline_Style == recStyle) { |
| 289 // stroking ignores the path fill rule. |
| 290 fRRectIsInverted = false; |
| 291 } |
| 292 } |
| 293 } else if (fRRect.isEmpty()) { |
| 259 fType = Type::kEmpty; | 294 fType = Type::kEmpty; |
| 260 } | 295 } |
| 261 } | 296 } |
| 262 | 297 |
| 263 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, | 298 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, |
| 264 SkPath::Direction* rrectDir, unsigne
d* rrectStart, | 299 SkPath::Direction* rrectDir, unsigne
d* rrectStart, |
| 265 const SkPathEffect* pe, const SkStro
keRec& strokeRec); | 300 bool* rrectIsInverted, const SkPathE
ffect* pe, |
| 301 const SkStrokeRec& strokeRec); |
| 266 | 302 |
| 267 static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction; | 303 static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction; |
| 268 static constexpr unsigned kDefaultRRectStart = 0; | 304 static constexpr unsigned kDefaultRRectStart = 0; |
| 269 | 305 |
| 270 static unsigned DefaultRectDirAndStartIndex(const SkRect& rect, bool hasPath
Effect, | 306 static unsigned DefaultRectDirAndStartIndex(const SkRect& rect, bool hasPath
Effect, |
| 271 SkPath::Direction* dir) { | 307 SkPath::Direction* dir) { |
| 272 *dir = kDefaultRRectDir; | 308 *dir = kDefaultRRectDir; |
| 273 // This comes from SkPath's interface. The default for adding a SkRect i
s counter clockwise | 309 // This comes from SkPath's interface. The default for adding a SkRect i
s counter clockwise |
| 274 // beginning at index 0 (which happens to correspond to rrect index 0 or
7). | 310 // beginning at index 0 (which happens to correspond to rrect index 0 or
7). |
| 275 if (!hasPathEffect) { | 311 if (!hasPathEffect) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 306 // It doesn't matter what start we use, just be consistent to avoid
redundant keys. | 342 // It doesn't matter what start we use, just be consistent to avoid
redundant keys. |
| 307 return kDefaultRRectStart; | 343 return kDefaultRRectStart; |
| 308 } | 344 } |
| 309 return kPathRRectStartIdx; | 345 return kPathRRectStartIdx; |
| 310 } | 346 } |
| 311 | 347 |
| 312 Type fType; | 348 Type fType; |
| 313 SkRRect fRRect; | 349 SkRRect fRRect; |
| 314 SkPath::Direction fRRectDir; | 350 SkPath::Direction fRRectDir; |
| 315 unsigned fRRectStart; | 351 unsigned fRRectStart; |
| 352 bool fRRectIsInverted; |
| 316 SkTLazy<SkPath> fPath; | 353 SkTLazy<SkPath> fPath; |
| 317 GrStyle fStyle; | 354 GrStyle fStyle; |
| 318 SkAutoSTArray<8, uint32_t> fInheritedKey; | 355 SkAutoSTArray<8, uint32_t> fInheritedKey; |
| 319 }; | 356 }; |
| 320 #endif | 357 #endif |
| OLD | NEW |