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(); | |
27 fPathRef->fGenerationID = 0; | 26 fPathRef->fGenerationID = 0; |
28 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) | 27 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) |
29 } | 28 } |
30 | 29 |
31 ////////////////////////////////////////////////////////////////////////////// | 30 ////////////////////////////////////////////////////////////////////////////// |
32 | 31 |
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 | |
47 // As a template argument, this must have external linkage. | 32 // As a template argument, this must have external linkage. |
48 SkPathRef* sk_create_empty_pathref() { | 33 SkPathRef* sk_create_empty_pathref() { |
49 SkPathRef* empty = SkNEW(SkPathRef); | 34 SkPathRef* empty = SkNEW(SkPathRef); |
50 empty->computeBounds(); // Avoids races later to be the first to do this. | 35 empty->computeBounds(); // Avoids races later to be the first to do this. |
51 return empty; | 36 return empty; |
52 } | 37 } |
53 | 38 |
54 SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, sk_create_empty_pathref); | 39 SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, sk_create_empty_pathref); |
55 | 40 |
56 SkPathRef* SkPathRef::CreateEmpty() { | 41 SkPathRef* SkPathRef::CreateEmpty() { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 147 |
163 // resetToSize clears fSegmentMask and fIsOval | 148 // resetToSize clears fSegmentMask and fIsOval |
164 ref->fSegmentMask = segmentMask; | 149 ref->fSegmentMask = segmentMask; |
165 ref->fIsOval = isOval; | 150 ref->fIsOval = isOval; |
166 return ref; | 151 return ref; |
167 } | 152 } |
168 | 153 |
169 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { | 154 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { |
170 if ((*pathRef)->unique()) { | 155 if ((*pathRef)->unique()) { |
171 SkDEBUGCODE((*pathRef)->validate();) | 156 SkDEBUGCODE((*pathRef)->validate();) |
172 (*pathRef)->callGenIDChangeListeners(); | |
173 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite | 157 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite |
174 (*pathRef)->fVerbCnt = 0; | 158 (*pathRef)->fVerbCnt = 0; |
175 (*pathRef)->fPointCnt = 0; | 159 (*pathRef)->fPointCnt = 0; |
176 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); | 160 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); |
177 (*pathRef)->fGenerationID = 0; | 161 (*pathRef)->fGenerationID = 0; |
178 (*pathRef)->fConicWeights.rewind(); | 162 (*pathRef)->fConicWeights.rewind(); |
179 (*pathRef)->fSegmentMask = 0; | 163 (*pathRef)->fSegmentMask = 0; |
180 (*pathRef)->fIsOval = false; | 164 (*pathRef)->fIsOval = false; |
181 SkDEBUGCODE((*pathRef)->validate();) | 165 SkDEBUGCODE((*pathRef)->validate();) |
182 } else { | 166 } else { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 if (0 != memcmp(this->points(), | 208 if (0 != memcmp(this->points(), |
225 ref.points(), | 209 ref.points(), |
226 ref.fPointCnt * sizeof(SkPoint))) { | 210 ref.fPointCnt * sizeof(SkPoint))) { |
227 SkASSERT(!genIDMatch); | 211 SkASSERT(!genIDMatch); |
228 return false; | 212 return false; |
229 } | 213 } |
230 if (fConicWeights != ref.fConicWeights) { | 214 if (fConicWeights != ref.fConicWeights) { |
231 SkASSERT(!genIDMatch); | 215 SkASSERT(!genIDMatch); |
232 return false; | 216 return false; |
233 } | 217 } |
| 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 } |
234 return true; | 225 return true; |
235 } | 226 } |
236 | 227 |
237 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { | 228 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { |
238 SkDEBUGCODE(this->validate();) | 229 SkDEBUGCODE(this->validate();) |
239 SkDEBUGCODE(size_t beforePos = buffer->pos();) | 230 SkDEBUGCODE(size_t beforePos = buffer->pos();) |
240 | 231 |
241 // Call getBounds() to ensure (as a side-effect) that fBounds | 232 // Call getBounds() to ensure (as a side-effect) that fBounds |
242 // and fIsFinite are computed. | 233 // and fIsFinite are computed. |
243 const SkRect& bounds = this->getBounds(); | 234 const SkRect& bounds = this->getBounds(); |
(...skipping 27 matching lines...) Expand all Loading... |
271 | 262 |
272 void SkPathRef::copy(const SkPathRef& ref, | 263 void SkPathRef::copy(const SkPathRef& ref, |
273 int additionalReserveVerbs, | 264 int additionalReserveVerbs, |
274 int additionalReservePoints) { | 265 int additionalReservePoints) { |
275 SkDEBUGCODE(this->validate();) | 266 SkDEBUGCODE(this->validate();) |
276 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), | 267 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), |
277 additionalReserveVerbs, additionalReservePoints); | 268 additionalReserveVerbs, additionalReservePoints); |
278 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(
uint8_t)); | 269 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(
uint8_t)); |
279 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); | 270 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); |
280 fConicWeights = ref.fConicWeights; | 271 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; |
281 fBoundsIsDirty = ref.fBoundsIsDirty; | 275 fBoundsIsDirty = ref.fBoundsIsDirty; |
282 if (!fBoundsIsDirty) { | 276 if (!fBoundsIsDirty) { |
283 fBounds = ref.fBounds; | 277 fBounds = ref.fBounds; |
284 fIsFinite = ref.fIsFinite; | 278 fIsFinite = ref.fIsFinite; |
285 } | 279 } |
286 fSegmentMask = ref.fSegmentMask; | 280 fSegmentMask = ref.fSegmentMask; |
287 fIsOval = ref.fIsOval; | 281 fIsOval = ref.fIsOval; |
288 SkDEBUGCODE(this->validate();) | 282 SkDEBUGCODE(this->validate();) |
289 } | 283 } |
290 | 284 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 // do a loop in case our global wraps around, as we never want to re
turn a 0 or the | 429 // do a loop in case our global wraps around, as we never want to re
turn a 0 or the |
436 // empty ID | 430 // empty ID |
437 do { | 431 do { |
438 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa
sk; | 432 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa
sk; |
439 } while (fGenerationID <= kEmptyGenID); | 433 } while (fGenerationID <= kEmptyGenID); |
440 } | 434 } |
441 } | 435 } |
442 return fGenerationID; | 436 return fGenerationID; |
443 } | 437 } |
444 | 438 |
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 | |
463 #ifdef SK_DEBUG | 439 #ifdef SK_DEBUG |
464 void SkPathRef::validate() const { | 440 void SkPathRef::validate() const { |
465 this->INHERITED::validate(); | 441 this->INHERITED::validate(); |
466 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); | 442 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); |
467 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo
ints) >= 0); | 443 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo
ints) >= 0); |
468 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); | 444 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); |
469 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 445 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
470 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 446 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
471 SkASSERT(!(NULL == fPoints && fPointCnt)); | 447 SkASSERT(!(NULL == fPoints && fPointCnt)); |
472 SkASSERT(!(NULL == fVerbs && fVerbCnt)); | 448 SkASSERT(!(NULL == fVerbs && fVerbCnt)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 break; | 502 break; |
527 default: | 503 default: |
528 SkDEBUGFAIL("Unknown Verb"); | 504 SkDEBUGFAIL("Unknown Verb"); |
529 break; | 505 break; |
530 } | 506 } |
531 } | 507 } |
532 SkASSERT(mask == fSegmentMask); | 508 SkASSERT(mask == fSegmentMask); |
533 #endif // SK_DEBUG_PATH | 509 #endif // SK_DEBUG_PATH |
534 } | 510 } |
535 #endif | 511 #endif |
OLD | NEW |