| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "SkBuffer.h" | 8 #include "SkBuffer.h" |
| 9 #include "SkLazyPtr.h" | 9 #include "SkLazyPtr.h" |
| 10 #include "SkPath.h" | 10 #include "SkPath.h" |
| 11 #include "SkPathRef.h" | 11 #include "SkPathRef.h" |
| 12 | 12 |
| 13 ////////////////////////////////////////////////////////////////////////////// | 13 ////////////////////////////////////////////////////////////////////////////// |
| 14 SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef, | 14 SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef, |
| 15 int incReserveVerbs, | 15 int incReserveVerbs, |
| 16 int incReservePoints) | 16 int incReservePoints) |
| 17 { | 17 { |
| 18 if ((*pathRef)->unique()) { | 18 if ((*pathRef)->unique()) { |
| 19 (*pathRef)->incReserve(incReserveVerbs, incReservePoints); | 19 (*pathRef)->incReserve(incReserveVerbs, incReservePoints); |
| 20 } else { | 20 } else { |
| 21 SkPathRef* copy = SkNEW(SkPathRef); | 21 SkPathRef* copy = SkNEW(SkPathRef); |
| 22 copy->copy(**pathRef, incReserveVerbs, incReservePoints); | 22 copy->copy(**pathRef, incReserveVerbs, incReservePoints); |
| 23 pathRef->reset(copy); | 23 pathRef->reset(copy); |
| 24 } | 24 } |
| 25 fPathRef = *pathRef; | 25 fPathRef = *pathRef; |
| 26 fPathRef->callGenIDChangeListeners(); |
| 26 fPathRef->fGenerationID = 0; | 27 fPathRef->fGenerationID = 0; |
| 27 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) | 28 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) |
| 28 } | 29 } |
| 29 | 30 |
| 30 ////////////////////////////////////////////////////////////////////////////// | 31 ////////////////////////////////////////////////////////////////////////////// |
| 31 | 32 |
| 33 SkPathRef::~SkPathRef() { |
| 34 this->callGenIDChangeListeners(); |
| 35 SkDEBUGCODE(this->validate();) |
| 36 sk_free(fPoints); |
| 37 |
| 38 SkDEBUGCODE(fPoints = NULL;) |
| 39 SkDEBUGCODE(fVerbs = NULL;) |
| 40 SkDEBUGCODE(fVerbCnt = 0x9999999;) |
| 41 SkDEBUGCODE(fPointCnt = 0xAAAAAAA;) |
| 42 SkDEBUGCODE(fPointCnt = 0xBBBBBBB;) |
| 43 SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;) |
| 44 SkDEBUGCODE(fEditorsAttached = 0x7777777;) |
| 45 } |
| 46 |
| 32 // As a template argument, this must have external linkage. | 47 // As a template argument, this must have external linkage. |
| 33 SkPathRef* sk_create_empty_pathref() { | 48 SkPathRef* sk_create_empty_pathref() { |
| 34 SkPathRef* empty = SkNEW(SkPathRef); | 49 SkPathRef* empty = SkNEW(SkPathRef); |
| 35 empty->computeBounds(); // Avoids races later to be the first to do this. | 50 empty->computeBounds(); // Avoids races later to be the first to do this. |
| 36 return empty; | 51 return empty; |
| 37 } | 52 } |
| 38 | 53 |
| 39 SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, sk_create_empty_pathref); | 54 SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, sk_create_empty_pathref); |
| 40 | 55 |
| 41 SkPathRef* SkPathRef::CreateEmpty() { | 56 SkPathRef* SkPathRef::CreateEmpty() { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 | 162 |
| 148 // resetToSize clears fSegmentMask and fIsOval | 163 // resetToSize clears fSegmentMask and fIsOval |
| 149 ref->fSegmentMask = segmentMask; | 164 ref->fSegmentMask = segmentMask; |
| 150 ref->fIsOval = isOval; | 165 ref->fIsOval = isOval; |
| 151 return ref; | 166 return ref; |
| 152 } | 167 } |
| 153 | 168 |
| 154 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { | 169 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { |
| 155 if ((*pathRef)->unique()) { | 170 if ((*pathRef)->unique()) { |
| 156 SkDEBUGCODE((*pathRef)->validate();) | 171 SkDEBUGCODE((*pathRef)->validate();) |
| 172 (*pathRef)->callGenIDChangeListeners(); |
| 157 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite | 173 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite |
| 158 (*pathRef)->fVerbCnt = 0; | 174 (*pathRef)->fVerbCnt = 0; |
| 159 (*pathRef)->fPointCnt = 0; | 175 (*pathRef)->fPointCnt = 0; |
| 160 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); | 176 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); |
| 161 (*pathRef)->fGenerationID = 0; | 177 (*pathRef)->fGenerationID = 0; |
| 162 (*pathRef)->fConicWeights.rewind(); | 178 (*pathRef)->fConicWeights.rewind(); |
| 163 (*pathRef)->fSegmentMask = 0; | 179 (*pathRef)->fSegmentMask = 0; |
| 164 (*pathRef)->fIsOval = false; | 180 (*pathRef)->fIsOval = false; |
| 165 SkDEBUGCODE((*pathRef)->validate();) | 181 SkDEBUGCODE((*pathRef)->validate();) |
| 166 } else { | 182 } else { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 if (0 != memcmp(this->points(), | 224 if (0 != memcmp(this->points(), |
| 209 ref.points(), | 225 ref.points(), |
| 210 ref.fPointCnt * sizeof(SkPoint))) { | 226 ref.fPointCnt * sizeof(SkPoint))) { |
| 211 SkASSERT(!genIDMatch); | 227 SkASSERT(!genIDMatch); |
| 212 return false; | 228 return false; |
| 213 } | 229 } |
| 214 if (fConicWeights != ref.fConicWeights) { | 230 if (fConicWeights != ref.fConicWeights) { |
| 215 SkASSERT(!genIDMatch); | 231 SkASSERT(!genIDMatch); |
| 216 return false; | 232 return false; |
| 217 } | 233 } |
| 218 // We've done the work to determine that these are equal. If either has a ze
ro genID, copy | |
| 219 // the other's. If both are 0 then genID() will compute the next ID. | |
| 220 if (0 == fGenerationID) { | |
| 221 fGenerationID = ref.genID(); | |
| 222 } else if (0 == ref.fGenerationID) { | |
| 223 ref.fGenerationID = this->genID(); | |
| 224 } | |
| 225 return true; | 234 return true; |
| 226 } | 235 } |
| 227 | 236 |
| 228 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { | 237 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { |
| 229 SkDEBUGCODE(this->validate();) | 238 SkDEBUGCODE(this->validate();) |
| 230 SkDEBUGCODE(size_t beforePos = buffer->pos();) | 239 SkDEBUGCODE(size_t beforePos = buffer->pos();) |
| 231 | 240 |
| 232 // Call getBounds() to ensure (as a side-effect) that fBounds | 241 // Call getBounds() to ensure (as a side-effect) that fBounds |
| 233 // and fIsFinite are computed. | 242 // and fIsFinite are computed. |
| 234 const SkRect& bounds = this->getBounds(); | 243 const SkRect& bounds = this->getBounds(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 262 | 271 |
| 263 void SkPathRef::copy(const SkPathRef& ref, | 272 void SkPathRef::copy(const SkPathRef& ref, |
| 264 int additionalReserveVerbs, | 273 int additionalReserveVerbs, |
| 265 int additionalReservePoints) { | 274 int additionalReservePoints) { |
| 266 SkDEBUGCODE(this->validate();) | 275 SkDEBUGCODE(this->validate();) |
| 267 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), | 276 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), |
| 268 additionalReserveVerbs, additionalReservePoints); | 277 additionalReserveVerbs, additionalReservePoints); |
| 269 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(
uint8_t)); | 278 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(
uint8_t)); |
| 270 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); | 279 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); |
| 271 fConicWeights = ref.fConicWeights; | 280 fConicWeights = ref.fConicWeights; |
| 272 // We could call genID() here to force a real ID (instead of 0). However, if
we're making | |
| 273 // a copy then presumably we intend to make a modification immediately after
wards. | |
| 274 fGenerationID = ref.fGenerationID; | |
| 275 fBoundsIsDirty = ref.fBoundsIsDirty; | 281 fBoundsIsDirty = ref.fBoundsIsDirty; |
| 276 if (!fBoundsIsDirty) { | 282 if (!fBoundsIsDirty) { |
| 277 fBounds = ref.fBounds; | 283 fBounds = ref.fBounds; |
| 278 fIsFinite = ref.fIsFinite; | 284 fIsFinite = ref.fIsFinite; |
| 279 } | 285 } |
| 280 fSegmentMask = ref.fSegmentMask; | 286 fSegmentMask = ref.fSegmentMask; |
| 281 fIsOval = ref.fIsOval; | 287 fIsOval = ref.fIsOval; |
| 282 SkDEBUGCODE(this->validate();) | 288 SkDEBUGCODE(this->validate();) |
| 283 } | 289 } |
| 284 | 290 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 // do a loop in case our global wraps around, as we never want to re
turn a 0 or the | 435 // do a loop in case our global wraps around, as we never want to re
turn a 0 or the |
| 430 // empty ID | 436 // empty ID |
| 431 do { | 437 do { |
| 432 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa
sk; | 438 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa
sk; |
| 433 } while (fGenerationID <= kEmptyGenID); | 439 } while (fGenerationID <= kEmptyGenID); |
| 434 } | 440 } |
| 435 } | 441 } |
| 436 return fGenerationID; | 442 return fGenerationID; |
| 437 } | 443 } |
| 438 | 444 |
| 445 void SkPathRef::addGenIDChangeListener(GenIDChangeListener* listener) { |
| 446 if (NULL == listener || this == empty.get()) { |
| 447 SkDELETE(listener); |
| 448 return; |
| 449 } |
| 450 *fGenIDChangeListeners.append() = listener; |
| 451 } |
| 452 |
| 453 // we need to be called *before* the genID gets changed or zerod |
| 454 void SkPathRef::callGenIDChangeListeners() { |
| 455 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { |
| 456 fGenIDChangeListeners[i]->onChange(); |
| 457 } |
| 458 |
| 459 // Listeners get at most one shot, so whether these triggered or not, blow t
hem away. |
| 460 fGenIDChangeListeners.deleteAll(); |
| 461 } |
| 462 |
| 439 #ifdef SK_DEBUG | 463 #ifdef SK_DEBUG |
| 440 void SkPathRef::validate() const { | 464 void SkPathRef::validate() const { |
| 441 this->INHERITED::validate(); | 465 this->INHERITED::validate(); |
| 442 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); | 466 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); |
| 443 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo
ints) >= 0); | 467 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo
ints) >= 0); |
| 444 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); | 468 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); |
| 445 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 469 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
| 446 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 470 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
| 447 SkASSERT(!(NULL == fPoints && fPointCnt)); | 471 SkASSERT(!(NULL == fPoints && fPointCnt)); |
| 448 SkASSERT(!(NULL == fVerbs && fVerbCnt)); | 472 SkASSERT(!(NULL == fVerbs && fVerbCnt)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 break; | 526 break; |
| 503 default: | 527 default: |
| 504 SkDEBUGFAIL("Unknown Verb"); | 528 SkDEBUGFAIL("Unknown Verb"); |
| 505 break; | 529 break; |
| 506 } | 530 } |
| 507 } | 531 } |
| 508 SkASSERT(mask == fSegmentMask); | 532 SkASSERT(mask == fSegmentMask); |
| 509 #endif // SK_DEBUG_PATH | 533 #endif // SK_DEBUG_PATH |
| 510 } | 534 } |
| 511 #endif | 535 #endif |
| OLD | NEW |