| 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 bool wasPath = Type::kPath == fType; | 11 bool wasPath = Type::kPath == fType; |
| 12 fStyle = that.fStyle; | 12 fStyle = that.fStyle; |
| 13 fType = that.fType; | 13 fType = that.fType; |
| 14 switch (fType) { | 14 switch (fType) { |
| 15 case Type::kEmpty: | 15 case Type::kEmpty: |
| 16 if (wasPath) { | 16 if (wasPath) { |
| 17 fPath.reset(); | 17 fPath.reset(); |
| 18 } | 18 } |
| 19 break; | 19 break; |
| 20 case Type::kRRect: | 20 case Type::kRRect: |
| 21 if (wasPath) { | 21 if (wasPath) { |
| 22 fPath.reset(); | 22 fPath.reset(); |
| 23 } | 23 } |
| 24 fRRect = that.fRRect; | 24 fRRect = that.fRRect; |
| 25 fRRectDir = that.fRRectDir; |
| 26 fRRectStart = that.fRRectStart; |
| 25 break; | 27 break; |
| 26 case Type::kPath: | 28 case Type::kPath: |
| 27 if (wasPath) { | 29 if (wasPath) { |
| 28 *fPath.get() = *that.fPath.get(); | 30 *fPath.get() = *that.fPath.get(); |
| 29 } else { | 31 } else { |
| 30 fPath.set(*that.fPath.get()); | 32 fPath.set(*that.fPath.get()); |
| 31 } | 33 } |
| 32 break; | 34 break; |
| 33 } | 35 } |
| 34 fInheritedKey.reset(that.fInheritedKey.count()); | 36 fInheritedKey.reset(that.fInheritedKey.count()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 62 int GrShape::unstyledKeySize() const { | 64 int GrShape::unstyledKeySize() const { |
| 63 if (fInheritedKey.count()) { | 65 if (fInheritedKey.count()) { |
| 64 return fInheritedKey.count(); | 66 return fInheritedKey.count(); |
| 65 } | 67 } |
| 66 switch (fType) { | 68 switch (fType) { |
| 67 case Type::kEmpty: | 69 case Type::kEmpty: |
| 68 return 1; | 70 return 1; |
| 69 case Type::kRRect: | 71 case Type::kRRect: |
| 70 SkASSERT(!fInheritedKey.count()); | 72 SkASSERT(!fInheritedKey.count()); |
| 71 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); | 73 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); |
| 72 return SkRRect::kSizeInMemory / sizeof(uint32_t); | 74 // + 1 for the direction + start index. |
| 75 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; |
| 73 case Type::kPath: | 76 case Type::kPath: |
| 74 if (fPath.get()->isVolatile()) { | 77 if (fPath.get()->isVolatile()) { |
| 75 return -1; | 78 return -1; |
| 76 } else { | 79 } else { |
| 77 return 1; | 80 return 1; |
| 78 } | 81 } |
| 79 } | 82 } |
| 80 SkFAIL("Should never get here."); | 83 SkFAIL("Should never get here."); |
| 81 return 0; | 84 return 0; |
| 82 } | 85 } |
| 83 | 86 |
| 84 void GrShape::writeUnstyledKey(uint32_t* key) const { | 87 void GrShape::writeUnstyledKey(uint32_t* key) const { |
| 85 SkASSERT(this->unstyledKeySize()); | 88 SkASSERT(this->unstyledKeySize()); |
| 86 SkDEBUGCODE(uint32_t* origKey = key;) | 89 SkDEBUGCODE(uint32_t* origKey = key;) |
| 87 if (fInheritedKey.count()) { | 90 if (fInheritedKey.count()) { |
| 88 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count(
)); | 91 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count(
)); |
| 89 SkDEBUGCODE(key += fInheritedKey.count();) | 92 SkDEBUGCODE(key += fInheritedKey.count();) |
| 90 } else { | 93 } else { |
| 91 switch (fType) { | 94 switch (fType) { |
| 92 case Type::kEmpty: | 95 case Type::kEmpty: |
| 93 *key++ = 1; | 96 *key++ = 1; |
| 94 break; | 97 break; |
| 95 case Type::kRRect: | 98 case Type::kRRect: |
| 96 fRRect.writeToMemory(key); | 99 fRRect.writeToMemory(key); |
| 97 key += SkRRect::kSizeInMemory / sizeof(uint32_t); | 100 key += SkRRect::kSizeInMemory / sizeof(uint32_t); |
| 101 *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; |
| 102 *key++ |= fRRectStart; |
| 103 SkASSERT(fRRectStart < 8); |
| 98 break; | 104 break; |
| 99 case Type::kPath: | 105 case Type::kPath: |
| 100 SkASSERT(!fPath.get()->isVolatile()); | 106 SkASSERT(!fPath.get()->isVolatile()); |
| 101 *key++ = fPath.get()->getGenerationID(); | 107 *key++ = fPath.get()->getGenerationID(); |
| 102 break; | 108 break; |
| 103 } | 109 } |
| 104 } | 110 } |
| 105 SkASSERT(key - origKey == this->unstyledKeySize()); | 111 SkASSERT(key - origKey == this->unstyledKeySize()); |
| 106 } | 112 } |
| 107 | 113 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { | 216 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { |
| 211 if (strokeRec.needToApply()) { | 217 if (strokeRec.needToApply()) { |
| 212 // The intermediate shape may not be a general path. If we we're
just applying | 218 // The intermediate shape may not be a general path. If we we're
just applying |
| 213 // the path effect then attemptToReduceFromPath would catch it.
This means that | 219 // the path effect then attemptToReduceFromPath would catch it.
This means that |
| 214 // when we subsequently applied the remaining strokeRec we would
have a non-path | 220 // when we subsequently applied the remaining strokeRec we would
have a non-path |
| 215 // parent shape that would be used to determine the the stroked
path's key. | 221 // parent shape that would be used to determine the the stroked
path's key. |
| 216 // We detect that case here and change parentForKey to a tempora
ry that represents | 222 // We detect that case here and change parentForKey to a tempora
ry that represents |
| 217 // the simpler shape so that applying both path effect and the s
trokerec all at | 223 // the simpler shape so that applying both path effect and the s
trokerec all at |
| 218 // once produces the same key. | 224 // once produces the same key. |
| 219 SkRRect rrect; | 225 SkRRect rrect; |
| 220 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre
ct, nullptr, | 226 SkPath::Direction dir; |
| 221 strokeRec); | 227 unsigned start; |
| 228 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre
ct, &dir, &start, |
| 229 nullptr, strokeRec
); |
| 222 switch (parentType) { | 230 switch (parentType) { |
| 223 case Type::kEmpty: | 231 case Type::kEmpty: |
| 224 tmpParent.init(); | 232 tmpParent.init(); |
| 225 parentForKey = tmpParent.get(); | 233 parentForKey = tmpParent.get(); |
| 226 break; | 234 break; |
| 227 case Type::kRRect: | 235 case Type::kRRect: |
| 228 tmpParent.init(rrect, GrStyle(strokeRec, nullptr)); | 236 tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nul
lptr)); |
| 229 parentForKey = tmpParent.get(); | 237 parentForKey = tmpParent.get(); |
| 230 case Type::kPath: | 238 case Type::kPath: |
| 231 break; | 239 break; |
| 232 } | 240 } |
| 233 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; | 241 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; |
| 234 } else { | 242 } else { |
| 235 fStyle = GrStyle(strokeRec, nullptr); | 243 fStyle = GrStyle(strokeRec, nullptr); |
| 236 } | 244 } |
| 237 } else { | 245 } else { |
| 238 fStyle = GrStyle(strokeRec, nullptr); | 246 fStyle = GrStyle(strokeRec, nullptr); |
| 239 } | 247 } |
| 240 } else { | 248 } else { |
| 241 const SkPath* srcForParentStyle; | 249 const SkPath* srcForParentStyle; |
| 242 if (parent.fType == Type::kPath) { | 250 if (parent.fType == Type::kPath) { |
| 243 srcForParentStyle = parent.fPath.get(); | 251 srcForParentStyle = parent.fPath.get(); |
| 244 } else { | 252 } else { |
| 245 srcForParentStyle = tmpPath.init(); | 253 srcForParentStyle = tmpPath.init(); |
| 246 parent.asPath(tmpPath.get()); | 254 parent.asPath(tmpPath.get()); |
| 247 } | 255 } |
| 248 SkStrokeRec::InitStyle fillOrHairline; | 256 SkStrokeRec::InitStyle fillOrHairline; |
| 249 SkASSERT(parent.fStyle.applies()); | 257 SkASSERT(parent.fStyle.applies()); |
| 250 SkASSERT(!parent.fStyle.pathEffect()); | 258 SkASSERT(!parent.fStyle.pathEffect()); |
| 251 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *
srcForParentStyle, | 259 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *
srcForParentStyle, |
| 252 scale)); | 260 scale)); |
| 253 fStyle.resetToInitStyle(fillOrHairline); | 261 fStyle.resetToInitStyle(fillOrHairline); |
| 254 } | 262 } |
| 255 this->attemptToReduceFromPath(); | 263 this->attemptToReduceFromPath(); |
| 256 this->setInheritedKey(*parentForKey, apply, scale); | 264 this->setInheritedKey(*parentForKey, apply, scale); |
| 257 } | 265 } |
| 266 |
| 267 GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
rrect, |
| 268 SkPath::Direction* rrectDir, |
| 269 unsigned* rrectStart, |
| 270 const SkPathEffect* pe, |
| 271 const SkStrokeRec& strokeRec)
{ |
| 272 if (path.isEmpty()) { |
| 273 return Type::kEmpty; |
| 274 } |
| 275 if (path.isRRect(rrect, rrectDir, rrectStart)) { |
| 276 // Currently SkPath does not acknowledge that empty, rect, or oval subty
pes as rrects. |
| 277 SkASSERT(!rrect->isEmpty()); |
| 278 SkASSERT(rrect->getType() != SkRRect::kRect_Type); |
| 279 SkASSERT(rrect->getType() != SkRRect::kOval_Type); |
| 280 if (!pe) { |
| 281 *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir); |
| 282 } |
| 283 return Type::kRRect; |
| 284 } |
| 285 SkRect rect; |
| 286 if (path.isOval(&rect, rrectDir, rrectStart)) { |
| 287 rrect->setOval(rect); |
| 288 if (!pe) { |
| 289 *rrectDir = kDefaultRRectDir; |
| 290 *rrectStart = kDefaultRRectStart; |
| 291 } else { |
| 292 // convert from oval indexing to rrect indexiing. |
| 293 *rrectStart *= 2; |
| 294 } |
| 295 return Type::kRRect; |
| 296 } |
| 297 // When there is a path effect we restrict rect detection to the narrower AP
I that |
| 298 // gives us the starting position. Otherwise, we will retry with the more ag
gressive isRect(). |
| 299 if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) { |
| 300 if (!pe) { |
| 301 *rrectDir = kDefaultRRectDir; |
| 302 *rrectStart = kDefaultRRectStart; |
| 303 } else { |
| 304 // convert from rect indexing to rrect indexiing. |
| 305 *rrectStart *= 2; |
| 306 } |
| 307 rrect->setRect(rect); |
| 308 return Type::kRRect; |
| 309 } |
| 310 if (!pe) { |
| 311 bool closed; |
| 312 if (path.isRect(&rect, &closed, nullptr)) { |
| 313 if (closed || strokeRec.isFillStyle()) { |
| 314 rrect->setRect(rect); |
| 315 // Since there is no path effect the dir and start index is imma
terial. |
| 316 *rrectDir = kDefaultRRectDir; |
| 317 *rrectStart = kDefaultRRectStart; |
| 318 return Type::kRRect; |
| 319 } |
| 320 } |
| 321 } |
| 322 return Type::kPath; |
| 323 } |
| OLD | NEW |