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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 | 234 // 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. | 235 // the other's. If both are 0 then genID() will compute the next ID. |
220 if (0 == fGenerationID) { | 236 if (0 == fGenerationID) { |
bsalomon
2015/07/28 21:27:40
Let's kill this code. It can lead to two owners of
Stephen White
2015/07/28 22:11:23
Done.
| |
221 fGenerationID = ref.genID(); | 237 fGenerationID = ref.genID(); |
222 } else if (0 == ref.fGenerationID) { | 238 } else if (0 == ref.fGenerationID) { |
223 ref.fGenerationID = this->genID(); | 239 ref.fGenerationID = this->genID(); |
224 } | 240 } |
225 return true; | 241 return true; |
226 } | 242 } |
227 | 243 |
228 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { | 244 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { |
229 SkDEBUGCODE(this->validate();) | 245 SkDEBUGCODE(this->validate();) |
230 SkDEBUGCODE(size_t beforePos = buffer->pos();) | 246 SkDEBUGCODE(size_t beforePos = buffer->pos();) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 int additionalReserveVerbs, | 280 int additionalReserveVerbs, |
265 int additionalReservePoints) { | 281 int additionalReservePoints) { |
266 SkDEBUGCODE(this->validate();) | 282 SkDEBUGCODE(this->validate();) |
267 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), | 283 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), |
268 additionalReserveVerbs, additionalReservePoints); | 284 additionalReserveVerbs, additionalReservePoints); |
269 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t)); | 285 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t)); |
270 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); | 286 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); |
271 fConicWeights = ref.fConicWeights; | 287 fConicWeights = ref.fConicWeights; |
272 // We could call genID() here to force a real ID (instead of 0). However, if we're making | 288 // 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. | 289 // a copy then presumably we intend to make a modification immediately after wards. |
274 fGenerationID = ref.fGenerationID; | 290 fGenerationID = ref.fGenerationID; |
bsalomon
2015/07/28 21:27:40
Same.. based on the above comment it is unlikely t
Stephen White
2015/07/28 22:11:23
Done. Looks like resetToSize() above will leave it
| |
275 fBoundsIsDirty = ref.fBoundsIsDirty; | 291 fBoundsIsDirty = ref.fBoundsIsDirty; |
276 if (!fBoundsIsDirty) { | 292 if (!fBoundsIsDirty) { |
277 fBounds = ref.fBounds; | 293 fBounds = ref.fBounds; |
278 fIsFinite = ref.fIsFinite; | 294 fIsFinite = ref.fIsFinite; |
279 } | 295 } |
280 fSegmentMask = ref.fSegmentMask; | 296 fSegmentMask = ref.fSegmentMask; |
281 fIsOval = ref.fIsOval; | 297 fIsOval = ref.fIsOval; |
282 SkDEBUGCODE(this->validate();) | 298 SkDEBUGCODE(this->validate();) |
283 } | 299 } |
284 | 300 |
(...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 | 445 // do a loop in case our global wraps around, as we never want to re turn a 0 or the |
430 // empty ID | 446 // empty ID |
431 do { | 447 do { |
432 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa sk; | 448 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMa sk; |
433 } while (fGenerationID <= kEmptyGenID); | 449 } while (fGenerationID <= kEmptyGenID); |
434 } | 450 } |
435 } | 451 } |
436 return fGenerationID; | 452 return fGenerationID; |
437 } | 453 } |
438 | 454 |
455 void SkPathRef::addGenIDChangeListener(GenIDChangeListener* listener) { | |
456 if (NULL == listener || this == empty.get()) { | |
457 SkDELETE(listener); | |
458 return; | |
459 } | |
460 *fGenIDChangeListeners.append() = listener; | |
461 } | |
462 | |
463 // we need to be called *before* the genID gets changed or zerod | |
464 void SkPathRef::callGenIDChangeListeners() { | |
465 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { | |
466 fGenIDChangeListeners[i]->onChange(); | |
467 } | |
468 | |
469 // Listeners get at most one shot, so whether these triggered or not, blow t hem away. | |
470 fGenIDChangeListeners.deleteAll(); | |
471 } | |
472 | |
439 #ifdef SK_DEBUG | 473 #ifdef SK_DEBUG |
440 void SkPathRef::validate() const { | 474 void SkPathRef::validate() const { |
441 this->INHERITED::validate(); | 475 this->INHERITED::validate(); |
442 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); | 476 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); |
443 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo ints) >= 0); | 477 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo ints) >= 0); |
444 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); | 478 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); |
445 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 479 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
446 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); | 480 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); |
447 SkASSERT(!(NULL == fPoints && fPointCnt)); | 481 SkASSERT(!(NULL == fPoints && fPointCnt)); |
448 SkASSERT(!(NULL == fVerbs && fVerbCnt)); | 482 SkASSERT(!(NULL == fVerbs && fVerbCnt)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 break; | 536 break; |
503 default: | 537 default: |
504 SkDEBUGFAIL("Unknown Verb"); | 538 SkDEBUGFAIL("Unknown Verb"); |
505 break; | 539 break; |
506 } | 540 } |
507 } | 541 } |
508 SkASSERT(mask == fSegmentMask); | 542 SkASSERT(mask == fSegmentMask); |
509 #endif // SK_DEBUG_PATH | 543 #endif // SK_DEBUG_PATH |
510 } | 544 } |
511 #endif | 545 #endif |
OLD | NEW |