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 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; | |
|
egdaniel
2016/06/06 18:34:36
So obviously fRRectStart will be less than 2^31, b
bsalomon
2016/06/06 19:41:29
Added SkASSERT(fRRectStart < 8)
| |
| 98 break; | 103 break; |
| 99 case Type::kPath: | 104 case Type::kPath: |
| 100 SkASSERT(!fPath.get()->isVolatile()); | 105 SkASSERT(!fPath.get()->isVolatile()); |
| 101 *key++ = fPath.get()->getGenerationID(); | 106 *key++ = fPath.get()->getGenerationID(); |
| 102 break; | 107 break; |
| 103 } | 108 } |
| 104 } | 109 } |
| 105 SkASSERT(key - origKey == this->unstyledKeySize()); | 110 SkASSERT(key - origKey == this->unstyledKeySize()); |
| 106 } | 111 } |
| 107 | 112 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { | 215 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { |
| 211 if (strokeRec.needToApply()) { | 216 if (strokeRec.needToApply()) { |
| 212 // The intermediate shape may not be a general path. If we we're just applying | 217 // 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 | 218 // 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 | 219 // 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. | 220 // 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 | 221 // 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 | 222 // the simpler shape so that applying both path effect and the s trokerec all at |
| 218 // once produces the same key. | 223 // once produces the same key. |
| 219 SkRRect rrect; | 224 SkRRect rrect; |
| 220 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre ct, nullptr, | 225 SkPath::Direction dir; |
| 221 strokeRec); | 226 unsigned start; |
| 227 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre ct, &dir, &start, | |
| 228 nullptr, strokeRec ); | |
| 222 switch (parentType) { | 229 switch (parentType) { |
| 223 case Type::kEmpty: | 230 case Type::kEmpty: |
| 224 tmpParent.init(); | 231 tmpParent.init(); |
| 225 parentForKey = tmpParent.get(); | 232 parentForKey = tmpParent.get(); |
| 226 break; | 233 break; |
| 227 case Type::kRRect: | 234 case Type::kRRect: |
| 228 tmpParent.init(rrect, GrStyle(strokeRec, nullptr)); | 235 tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nul lptr)); |
| 229 parentForKey = tmpParent.get(); | 236 parentForKey = tmpParent.get(); |
| 230 case Type::kPath: | 237 case Type::kPath: |
| 231 break; | 238 break; |
| 232 } | 239 } |
| 233 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())) ; | 240 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())) ; |
| 234 } else { | 241 } else { |
| 235 fStyle = GrStyle(strokeRec, nullptr); | 242 fStyle = GrStyle(strokeRec, nullptr); |
| 236 } | 243 } |
| 237 } else { | 244 } else { |
| 238 fStyle = GrStyle(strokeRec, nullptr); | 245 fStyle = GrStyle(strokeRec, nullptr); |
| 239 } | 246 } |
| 240 } else { | 247 } else { |
| 241 const SkPath* srcForParentStyle; | 248 const SkPath* srcForParentStyle; |
| 242 if (parent.fType == Type::kPath) { | 249 if (parent.fType == Type::kPath) { |
| 243 srcForParentStyle = parent.fPath.get(); | 250 srcForParentStyle = parent.fPath.get(); |
| 244 } else { | 251 } else { |
| 245 srcForParentStyle = tmpPath.init(); | 252 srcForParentStyle = tmpPath.init(); |
| 246 parent.asPath(tmpPath.get()); | 253 parent.asPath(tmpPath.get()); |
| 247 } | 254 } |
| 248 SkStrokeRec::InitStyle fillOrHairline; | 255 SkStrokeRec::InitStyle fillOrHairline; |
| 249 SkASSERT(parent.fStyle.applies()); | 256 SkASSERT(parent.fStyle.applies()); |
| 250 SkASSERT(!parent.fStyle.pathEffect()); | 257 SkASSERT(!parent.fStyle.pathEffect()); |
| 251 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, * srcForParentStyle, | 258 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, * srcForParentStyle, |
| 252 scale)); | 259 scale)); |
| 253 fStyle.resetToInitStyle(fillOrHairline); | 260 fStyle.resetToInitStyle(fillOrHairline); |
| 254 } | 261 } |
| 255 this->attemptToReduceFromPath(); | 262 this->attemptToReduceFromPath(); |
| 256 this->setInheritedKey(*parentForKey, apply, scale); | 263 this->setInheritedKey(*parentForKey, apply, scale); |
| 257 } | 264 } |
| 265 | |
| 266 GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, | |
| 267 SkPath::Direction* rrectDir, | |
| 268 unsigned* rrectStart, | |
| 269 const SkPathEffect* pe, | |
| 270 const SkStrokeRec& strokeRec) { | |
| 271 if (path.isEmpty()) { | |
| 272 return Type::kEmpty; | |
| 273 } | |
| 274 if (path.isRRect(rrect, rrectDir, rrectStart)) { | |
| 275 SkASSERT(!rrect->isEmpty()); | |
| 276 if (!pe) { | |
| 277 *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir); | |
| 278 } else { | |
| 279 // For oval and rect subtypes of rrects pairs of start indices colla pse to the same | |
| 280 // point. Here ,we canonicalize which of the start points we use. | |
| 281 if (rrect->getType() == SkRRect::kOval_Type) { | |
| 282 *rrectStart |= ~0b1; | |
| 283 } else if (rrect->getType() == SkRRect::kRect_Type) { | |
| 284 *rrectStart = ((*rrectStart + 1) & 0b110); | |
| 285 } | |
| 286 } | |
| 287 return Type::kRRect; | |
| 288 } | |
| 289 SkRect rect; | |
| 290 if (path.isOval(&rect, rrectDir, rrectStart)) { | |
| 291 rrect->setOval(rect); | |
| 292 if (!pe) { | |
| 293 *rrectDir = kDefaultRRectDir; | |
| 294 *rrectStart = kDefaultRRectStart; | |
| 295 } else { | |
| 296 // convert from oval indexing to rrect indexiing. | |
| 297 *rrectStart *= 2; | |
| 298 } | |
| 299 return Type::kRRect; | |
| 300 } | |
| 301 // When there is a path effect we restrict rect detection to the narrower AP I that | |
| 302 // gives us the starting position. Otherwise, we will retry with the more ag gressive isRect(). | |
| 303 if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) { | |
| 304 if (!pe) { | |
| 305 *rrectDir = kDefaultRRectDir; | |
| 306 *rrectStart = kDefaultRRectStart; | |
| 307 } else { | |
| 308 // convert from rect indexing to rrect indexiing. | |
| 309 *rrectStart *= 2; | |
| 310 } | |
| 311 rrect->setRect(rect); | |
| 312 return Type::kRRect; | |
| 313 } | |
| 314 if (!pe) { | |
| 315 bool closed; | |
| 316 if (path.isRect(&rect, &closed, nullptr)) { | |
| 317 if (closed || strokeRec.isFillStyle()) { | |
| 318 rrect->setRect(rect); | |
| 319 // Since there is no path effect the dir and start index is imma terial. | |
| 320 *rrectDir = kDefaultRRectDir; | |
| 321 *rrectStart = kDefaultRRectStart; | |
| 322 return Type::kRRect; | |
| 323 } | |
| 324 } | |
| 325 } | |
| 326 return Type::kPath; | |
| 327 } | |
| OLD | NEW |