Chromium Code Reviews| 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 #include "GrShape.h" | 8 #include "GrShape.h" |
| 9 | 9 |
| 10 GrShape& GrShape::operator=(const GrShape& that) { | 10 GrShape& GrShape::operator=(const GrShape& that) { |
| 11 fStyle = that.fStyle; | 11 fStyle = that.fStyle; |
| 12 this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : null ptr); | 12 this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : null ptr); |
| 13 switch (fType) { | 13 switch (fType) { |
| 14 case Type::kEmpty: | 14 case Type::kEmpty: |
| 15 break; | 15 break; |
| 16 case Type::kRRect: | 16 case Type::kRRect: |
| 17 fRRectData.fRRect = that.fRRectData.fRRect; | 17 fRRectData = that.fRRectData; |
| 18 fRRectData.fDir = that.fRRectData.fDir; | |
| 19 fRRectData.fStart = that.fRRectData.fStart; | |
| 20 fRRectData.fInverted = that.fRRectData.fInverted; | |
| 21 break; | 18 break; |
| 19 case Type::kLine: | |
| 20 fLineData = that.fLineData; | |
|
robertphillips
2016/06/28 17:04:05
break here ?!
bsalomon
2016/06/28 17:13:02
Yikes, done.
| |
| 22 case Type::kPath: | 21 case Type::kPath: |
| 23 fPathData.fGenID = that.fPathData.fGenID; | 22 fPathData.fGenID = that.fPathData.fGenID; |
| 24 break; | 23 break; |
| 25 } | 24 } |
| 26 fInheritedKey.reset(that.fInheritedKey.count()); | 25 fInheritedKey.reset(that.fInheritedKey.count()); |
| 27 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 26 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
| 28 sizeof(uint32_t) * fInheritedKey.count()); | 27 sizeof(uint32_t) * fInheritedKey.count()); |
| 29 return *this; | 28 return *this; |
| 30 } | 29 } |
| 31 | 30 |
| 32 const SkRect& GrShape::bounds() const { | 31 SkRect GrShape::bounds() const { |
| 33 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); | 32 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); |
| 34 switch (fType) { | 33 switch (fType) { |
| 35 case Type::kEmpty: | 34 case Type::kEmpty: |
| 36 return kEmpty; | 35 return kEmpty; |
| 36 case Type::kLine: { | |
| 37 SkRect bounds; | |
| 38 if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) { | |
| 39 bounds.fLeft = fLineData.fPts[0].fX; | |
| 40 bounds.fRight = fLineData.fPts[1].fX; | |
| 41 } else { | |
| 42 bounds.fLeft = fLineData.fPts[1].fX; | |
| 43 bounds.fRight = fLineData.fPts[0].fX; | |
| 44 } | |
| 45 if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) { | |
| 46 bounds.fTop = fLineData.fPts[0].fY; | |
| 47 bounds.fBottom = fLineData.fPts[1].fY; | |
| 48 } else { | |
| 49 bounds.fTop = fLineData.fPts[1].fY; | |
| 50 bounds.fBottom = fLineData.fPts[0].fY; | |
| 51 } | |
| 52 return bounds; | |
| 53 } | |
| 37 case Type::kRRect: | 54 case Type::kRRect: |
| 38 return fRRectData.fRRect.getBounds(); | 55 return fRRectData.fRRect.getBounds(); |
| 39 case Type::kPath: | 56 case Type::kPath: |
| 40 return this->path().getBounds(); | 57 return this->path().getBounds(); |
| 41 } | 58 } |
| 42 SkFAIL("Unknown shape type"); | 59 SkFAIL("Unknown shape type"); |
| 43 return kEmpty; | 60 return kEmpty; |
| 44 } | 61 } |
| 45 | 62 |
| 46 void GrShape::styledBounds(SkRect* bounds) const { | 63 SkRect GrShape::styledBounds() const { |
| 47 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { | 64 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { |
| 48 *bounds = SkRect::MakeEmpty(); | 65 return SkRect::MakeEmpty(); |
| 49 } else { | |
| 50 fStyle.adjustBounds(bounds, this->bounds()); | |
| 51 } | 66 } |
| 67 SkRect bounds; | |
| 68 fStyle.adjustBounds(&bounds, this->bounds()); | |
| 69 return bounds; | |
| 52 } | 70 } |
| 53 | 71 |
| 54 int GrShape::unstyledKeySize() const { | 72 int GrShape::unstyledKeySize() const { |
| 55 if (fInheritedKey.count()) { | 73 if (fInheritedKey.count()) { |
| 56 return fInheritedKey.count(); | 74 return fInheritedKey.count(); |
| 57 } | 75 } |
| 58 switch (fType) { | 76 switch (fType) { |
| 59 case Type::kEmpty: | 77 case Type::kEmpty: |
| 60 return 1; | 78 return 1; |
| 61 case Type::kRRect: | 79 case Type::kRRect: |
| 62 SkASSERT(!fInheritedKey.count()); | 80 SkASSERT(!fInheritedKey.count()); |
| 63 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); | 81 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); |
| 64 // + 1 for the direction, start index, and inverseness. | 82 // + 1 for the direction, start index, and inverseness. |
| 65 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; | 83 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; |
| 84 case Type::kLine: | |
| 85 GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint)); | |
| 86 // 4 for the end points and 1 for the inverseness | |
| 87 return 5; | |
| 66 case Type::kPath: | 88 case Type::kPath: |
| 67 if (0 == fPathData.fGenID) { | 89 if (0 == fPathData.fGenID) { |
| 68 return -1; | 90 return -1; |
| 69 } else { | 91 } else { |
| 70 // The key is the path ID and fill type. | 92 // The key is the path ID and fill type. |
| 71 return 2; | 93 return 2; |
| 72 } | 94 } |
| 73 } | 95 } |
| 74 SkFAIL("Should never get here."); | 96 SkFAIL("Should never get here."); |
| 75 return 0; | 97 return 0; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 87 *key++ = 1; | 109 *key++ = 1; |
| 88 break; | 110 break; |
| 89 case Type::kRRect: | 111 case Type::kRRect: |
| 90 fRRectData.fRRect.writeToMemory(key); | 112 fRRectData.fRRect.writeToMemory(key); |
| 91 key += SkRRect::kSizeInMemory / sizeof(uint32_t); | 113 key += SkRRect::kSizeInMemory / sizeof(uint32_t); |
| 92 *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; | 114 *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; |
| 93 *key |= fRRectData.fInverted ? (1 << 30) : 0; | 115 *key |= fRRectData.fInverted ? (1 << 30) : 0; |
| 94 *key++ |= fRRectData.fStart; | 116 *key++ |= fRRectData.fStart; |
| 95 SkASSERT(fRRectData.fStart < 8); | 117 SkASSERT(fRRectData.fStart < 8); |
| 96 break; | 118 break; |
| 119 case Type::kLine: | |
| 120 memcpy(key, fLineData.fPts, 2 * sizeof(SkPoint)); | |
| 121 key += 4; | |
| 122 *key++ = fLineData.fInverted ? 1 : 0; | |
| 123 break; | |
| 97 case Type::kPath: | 124 case Type::kPath: |
| 98 SkASSERT(fPathData.fGenID); | 125 SkASSERT(fPathData.fGenID); |
| 99 *key++ = fPathData.fGenID; | 126 *key++ = fPathData.fGenID; |
| 100 // We could canonicalize the fill rule for paths that don't diff erentiate between | 127 // We could canonicalize the fill rule for paths that don't diff erentiate between |
| 101 // even/odd or winding fill (e.g. convex). | 128 // even/odd or winding fill (e.g. convex). |
| 102 *key++ = this->path().getFillType(); | 129 *key++ = this->path().getFillType(); |
| 103 break; | 130 break; |
| 104 } | 131 } |
| 105 } | 132 } |
| 106 SkASSERT(key - origKey == this->unstyledKeySize()); | 133 SkASSERT(key - origKey == this->unstyledKeySize()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 } | 179 } |
| 153 } | 180 } |
| 154 | 181 |
| 155 GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { | 182 GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { |
| 156 const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr; | 183 const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr; |
| 157 this->initType(that.fType, thatPath); | 184 this->initType(that.fType, thatPath); |
| 158 switch (fType) { | 185 switch (fType) { |
| 159 case Type::kEmpty: | 186 case Type::kEmpty: |
| 160 break; | 187 break; |
| 161 case Type::kRRect: | 188 case Type::kRRect: |
| 162 fRRectData.fRRect = that.fRRectData.fRRect; | 189 fRRectData = that.fRRectData; |
| 163 fRRectData.fDir = that.fRRectData.fDir; | |
| 164 fRRectData.fStart = that.fRRectData.fStart; | |
| 165 fRRectData.fInverted = that.fRRectData.fInverted; | |
| 166 break; | 190 break; |
| 191 case Type::kLine: | |
| 192 fLineData = that.fLineData; | |
|
robertphillips
2016/06/28 17:04:05
break here ?!
bsalomon
2016/06/28 17:13:02
Done.
| |
| 167 case Type::kPath: | 193 case Type::kPath: |
| 168 fPathData.fGenID = that.fPathData.fGenID; | 194 fPathData.fGenID = that.fPathData.fGenID; |
| 169 break; | 195 break; |
| 170 } | 196 } |
| 171 fInheritedKey.reset(that.fInheritedKey.count()); | 197 fInheritedKey.reset(that.fInheritedKey.count()); |
| 172 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 198 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
| 173 sizeof(uint32_t) * fInheritedKey.count()); | 199 sizeof(uint32_t) * fInheritedKey.count()); |
| 174 } | 200 } |
| 175 | 201 |
| 176 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { | 202 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 this->attemptToSimplifyPath(); | 285 this->attemptToSimplifyPath(); |
| 260 this->setInheritedKey(*parentForKey, apply, scale); | 286 this->setInheritedKey(*parentForKey, apply, scale); |
| 261 } | 287 } |
| 262 | 288 |
| 263 void GrShape::attemptToSimplifyPath() { | 289 void GrShape::attemptToSimplifyPath() { |
| 264 SkRect rect; | 290 SkRect rect; |
| 265 SkRRect rrect; | 291 SkRRect rrect; |
| 266 SkPath::Direction rrectDir; | 292 SkPath::Direction rrectDir; |
| 267 unsigned rrectStart; | 293 unsigned rrectStart; |
| 268 bool inverted = this->path().isInverseFillType(); | 294 bool inverted = this->path().isInverseFillType(); |
| 295 SkPoint pts[2]; | |
| 269 if (this->path().isEmpty()) { | 296 if (this->path().isEmpty()) { |
| 270 this->changeType(Type::kEmpty); | 297 this->changeType(Type::kEmpty); |
| 298 } else if (this->path().isLine(pts)) { | |
| 299 this->changeType(Type::kLine); | |
| 300 fLineData.fPts[0] = pts[0]; | |
| 301 fLineData.fPts[1] = pts[1]; | |
| 302 fLineData.fInverted = inverted; | |
| 271 } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { | 303 } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { |
| 272 this->changeType(Type::kRRect); | 304 this->changeType(Type::kRRect); |
| 273 fRRectData.fRRect = rrect; | 305 fRRectData.fRRect = rrect; |
| 274 fRRectData.fDir = rrectDir; | 306 fRRectData.fDir = rrectDir; |
| 275 fRRectData.fStart = rrectStart; | 307 fRRectData.fStart = rrectStart; |
| 276 fRRectData.fInverted = inverted; | 308 fRRectData.fInverted = inverted; |
| 277 // Currently SkPath does not acknowledge that empty, rect, or oval subty pes as rrects. | 309 // Currently SkPath does not acknowledge that empty, rect, or oval subty pes as rrects. |
| 278 SkASSERT(!fRRectData.fRRect.isEmpty()); | 310 SkASSERT(!fRRectData.fRRect.isEmpty()); |
| 279 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type); | 311 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type); |
| 280 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type); | 312 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 306 fRRectData.fStart = kDefaultRRectStart; | 338 fRRectData.fStart = kDefaultRRectStart; |
| 307 // There isn't dashing so we will have to preserver inverseness. | 339 // There isn't dashing so we will have to preserver inverseness. |
| 308 fRRectData.fInverted = inverted; | 340 fRRectData.fInverted = inverted; |
| 309 } | 341 } |
| 310 } | 342 } |
| 311 } | 343 } |
| 312 if (Type::kPath != fType) { | 344 if (Type::kPath != fType) { |
| 313 fInheritedKey.reset(0); | 345 fInheritedKey.reset(0); |
| 314 if (Type::kRRect == fType) { | 346 if (Type::kRRect == fType) { |
| 315 this->attemptToSimplifyRRect(); | 347 this->attemptToSimplifyRRect(); |
| 348 } else if (Type::kLine == fType) { | |
| 349 this->attemptToSimplifyLine(); | |
| 316 } | 350 } |
| 317 } else { | 351 } else { |
| 318 if (fInheritedKey.count() || this->path().isVolatile()) { | 352 if (fInheritedKey.count() || this->path().isVolatile()) { |
| 319 fPathData.fGenID = 0; | 353 fPathData.fGenID = 0; |
| 320 } else { | 354 } else { |
| 321 fPathData.fGenID = this->path().getGenerationID(); | 355 fPathData.fGenID = this->path().getGenerationID(); |
| 322 } | 356 } |
| 323 if (this->style().isSimpleFill()) { | 357 if (this->style().isSimpleFill()) { |
| 324 // Filled paths are treated as though all their contours were closed . | 358 this->path().close(); |
| 325 // Since SkPath doesn't track individual contours, this will only cl ose the last. :( | 359 this->path().setIsVolatile(true); |
| 326 // There is no point in closing lines, though, since they loose thei r line-ness. | |
| 327 if (!this->path().isLine(nullptr)) { | |
| 328 this->path().close(); | |
| 329 this->path().setIsVolatile(true); | |
| 330 } | |
| 331 } | 360 } |
| 332 if (!this->style().hasNonDashPathEffect()) { | 361 if (!this->style().hasNonDashPathEffect()) { |
| 333 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty le || | 362 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty le || |
| 334 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S tyle) { | 363 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S tyle) { |
| 335 // Stroke styles don't differentiate between winding and even/od d. | 364 // Stroke styles don't differentiate between winding and even/od d. |
| 336 // Moreover, dashing ignores inverseness (skbug.com/5421) | 365 // Moreover, dashing ignores inverseness (skbug.com/5421) |
| 337 bool inverse = !this->style().isDashed() && this->path().isInver seFillType(); | 366 bool inverse = !this->style().isDashed() && this->path().isInver seFillType(); |
| 338 if (inverse) { | 367 if (inverse) { |
| 339 this->path().setFillType(kDefaultPathInverseFillType); | 368 this->path().setFillType(kDefaultPathInverseFillType); |
| 340 } else { | 369 } else { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 361 return; | 390 return; |
| 362 } | 391 } |
| 363 if (!this->style().hasPathEffect()) { | 392 if (!this->style().hasPathEffect()) { |
| 364 fRRectData.fDir = kDefaultRRectDir; | 393 fRRectData.fDir = kDefaultRRectDir; |
| 365 fRRectData.fStart = kDefaultRRectStart; | 394 fRRectData.fStart = kDefaultRRectStart; |
| 366 } else if (fStyle.isDashed()) { | 395 } else if (fStyle.isDashed()) { |
| 367 // Dashing ignores the inverseness (currently). skbug.com/5421 | 396 // Dashing ignores the inverseness (currently). skbug.com/5421 |
| 368 fRRectData.fInverted = false; | 397 fRRectData.fInverted = false; |
| 369 } | 398 } |
| 370 } | 399 } |
| 400 | |
| 401 void GrShape::attemptToSimplifyLine() { | |
| 402 if (fStyle.isSimpleFill() && !fLineData.fInverted) { | |
| 403 this->changeType(Type::kEmpty); | |
| 404 } else { | |
| 405 // Only path effects could care about the order of the points. Otherwise canonicalize | |
| 406 // the point order | |
| 407 if (!fStyle.hasPathEffect()) { | |
| 408 SkPoint* pts = fLineData.fPts; | |
| 409 if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].fX)) { | |
| 410 SkTSwap(pts[0], pts[1]); | |
| 411 } | |
| 412 } else if (fStyle.isDashed()) { | |
|
robertphillips
2016/06/28 17:04:05
// dashing ignores inverseness
?
bsalomon
2016/06/28 17:13:02
Done.
| |
| 413 fLineData.fInverted = false; | |
| 414 } | |
| 415 } | |
| 416 } | |
| OLD | NEW |