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 "SkOnce.h" | 9 #include "SkOnce.h" |
10 #include "SkPath.h" | 10 #include "SkPath.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 147 |
148 // resetToSize clears fSegmentMask and fIsOval | 148 // resetToSize clears fSegmentMask and fIsOval |
149 ref->fSegmentMask = segmentMask; | 149 ref->fSegmentMask = segmentMask; |
150 ref->fIsOval = isOval; | 150 ref->fIsOval = isOval; |
151 return ref; | 151 return ref; |
152 } | 152 } |
153 | 153 |
154 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { | 154 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { |
155 if ((*pathRef)->unique()) { | 155 if ((*pathRef)->unique()) { |
156 SkDEBUGCODE((*pathRef)->validate();) | 156 SkDEBUGCODE((*pathRef)->validate();) |
| 157 (*pathRef)->fLastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE; |
157 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite | 158 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite |
158 (*pathRef)->fVerbCnt = 0; | 159 (*pathRef)->fVerbCnt = 0; |
159 (*pathRef)->fPointCnt = 0; | 160 (*pathRef)->fPointCnt = 0; |
160 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); | 161 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); |
161 (*pathRef)->fGenerationID = 0; | 162 (*pathRef)->fGenerationID = 0; |
162 (*pathRef)->fConicWeights.rewind(); | 163 (*pathRef)->fConicWeights.rewind(); |
163 (*pathRef)->fSegmentMask = 0; | 164 (*pathRef)->fSegmentMask = 0; |
164 (*pathRef)->fIsOval = false; | 165 (*pathRef)->fIsOval = false; |
165 SkDEBUGCODE((*pathRef)->validate();) | 166 SkDEBUGCODE((*pathRef)->validate();) |
166 } else { | 167 } else { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 fBoundsIsDirty = ref.fBoundsIsDirty; | 270 fBoundsIsDirty = ref.fBoundsIsDirty; |
270 if (!fBoundsIsDirty) { | 271 if (!fBoundsIsDirty) { |
271 fBounds = ref.fBounds; | 272 fBounds = ref.fBounds; |
272 fIsFinite = ref.fIsFinite; | 273 fIsFinite = ref.fIsFinite; |
273 } | 274 } |
274 fSegmentMask = ref.fSegmentMask; | 275 fSegmentMask = ref.fSegmentMask; |
275 fIsOval = ref.fIsOval; | 276 fIsOval = ref.fIsOval; |
276 SkDEBUGCODE(this->validate();) | 277 SkDEBUGCODE(this->validate();) |
277 } | 278 } |
278 | 279 |
| 280 void SkPathRef::injectMoveToIfNeeded() { |
| 281 if (fLastMoveToIndex < 0) { |
| 282 SkScalar x, y; |
| 283 if (this->countVerbs() == 0) { |
| 284 x = y = 0; |
| 285 } else { |
| 286 const SkPoint& pt = this->atPoint(~fLastMoveToIndex); |
| 287 x = pt.fX; |
| 288 y = pt.fY; |
| 289 } |
| 290 this->growForVerb(SkPath::kMove_Verb, 0)->set(x, y); |
| 291 } |
| 292 } |
| 293 |
279 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb, | 294 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb, |
280 int numVbs, | 295 int numVbs, |
281 SkScalar** weights) { | 296 SkScalar** weights) { |
282 // This value is just made-up for now. When count is 4, calling memset was m
uch | 297 // This value is just made-up for now. When count is 4, calling memset was m
uch |
283 // slower than just writing the loop. This seems odd, and hopefully in the | 298 // slower than just writing the loop. This seems odd, and hopefully in the |
284 // future this will appear to have been a fluke... | 299 // future this will appear to have been a fluke... |
285 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16; | 300 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16; |
286 | 301 |
| 302 if (numVbs <= 0) { |
| 303 return NULL; |
| 304 } |
| 305 |
287 SkDEBUGCODE(this->validate();) | 306 SkDEBUGCODE(this->validate();) |
288 int pCnt; | 307 int pCnt; |
289 bool dirtyAfterEdit = true; | 308 bool dirtyAfterEdit = true; |
290 switch (verb) { | 309 switch (verb) { |
291 case SkPath::kMove_Verb: | 310 case SkPath::kMove_Verb: |
| 311 fLastMoveToIndex = fPointCnt + numVbs - 1; |
292 pCnt = numVbs; | 312 pCnt = numVbs; |
293 dirtyAfterEdit = false; | 313 dirtyAfterEdit = false; |
294 break; | 314 break; |
295 case SkPath::kLine_Verb: | 315 case SkPath::kLine_Verb: |
296 fSegmentMask |= SkPath::kLine_SegmentMask; | 316 fSegmentMask |= SkPath::kLine_SegmentMask; |
297 pCnt = numVbs; | 317 pCnt = numVbs; |
298 break; | 318 break; |
299 case SkPath::kQuad_Verb: | 319 case SkPath::kQuad_Verb: |
300 fSegmentMask |= SkPath::kQuad_SegmentMask; | 320 fSegmentMask |= SkPath::kQuad_SegmentMask; |
301 pCnt = 2 * numVbs; | 321 pCnt = 2 * numVbs; |
302 break; | 322 break; |
303 case SkPath::kConic_Verb: | 323 case SkPath::kConic_Verb: |
304 fSegmentMask |= SkPath::kConic_SegmentMask; | 324 fSegmentMask |= SkPath::kConic_SegmentMask; |
305 pCnt = 2 * numVbs; | 325 pCnt = 2 * numVbs; |
306 break; | 326 break; |
307 case SkPath::kCubic_Verb: | 327 case SkPath::kCubic_Verb: |
308 fSegmentMask |= SkPath::kCubic_SegmentMask; | 328 fSegmentMask |= SkPath::kCubic_SegmentMask; |
309 pCnt = 3 * numVbs; | 329 pCnt = 3 * numVbs; |
310 break; | 330 break; |
311 case SkPath::kClose_Verb: | 331 case SkPath::kClose_Verb: |
312 SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb"); | 332 SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb"); |
| 333 // signal that we need a moveTo to follow us (unless we're done) |
| 334 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToInde
x) - 1); |
313 pCnt = 0; | 335 pCnt = 0; |
314 dirtyAfterEdit = false; | 336 dirtyAfterEdit = false; |
315 break; | 337 break; |
316 case SkPath::kDone_Verb: | 338 case SkPath::kDone_Verb: |
317 SkDEBUGFAIL("growForRepeatedVerb called for kDone"); | 339 SkDEBUGFAIL("growForRepeatedVerb called for kDone"); |
318 // fall through | 340 // fall through |
319 default: | 341 default: |
320 SkDEBUGFAIL("default should not be reached"); | 342 SkDEBUGFAIL("default should not be reached"); |
321 pCnt = 0; | 343 pCnt = 0; |
322 dirtyAfterEdit = false; | 344 dirtyAfterEdit = false; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 SkDEBUGCODE(this->validate();) | 376 SkDEBUGCODE(this->validate();) |
355 return ret; | 377 return ret; |
356 } | 378 } |
357 | 379 |
358 SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) { | 380 SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) { |
359 SkDEBUGCODE(this->validate();) | 381 SkDEBUGCODE(this->validate();) |
360 int pCnt; | 382 int pCnt; |
361 bool dirtyAfterEdit = true; | 383 bool dirtyAfterEdit = true; |
362 switch (verb) { | 384 switch (verb) { |
363 case SkPath::kMove_Verb: | 385 case SkPath::kMove_Verb: |
| 386 // remember our index |
| 387 fLastMoveToIndex = fPointCnt; |
364 pCnt = 1; | 388 pCnt = 1; |
365 dirtyAfterEdit = false; | 389 dirtyAfterEdit = false; |
366 break; | 390 break; |
367 case SkPath::kLine_Verb: | 391 case SkPath::kLine_Verb: |
368 fSegmentMask |= SkPath::kLine_SegmentMask; | 392 fSegmentMask |= SkPath::kLine_SegmentMask; |
369 pCnt = 1; | 393 pCnt = 1; |
370 break; | 394 break; |
371 case SkPath::kQuad_Verb: | 395 case SkPath::kQuad_Verb: |
372 fSegmentMask |= SkPath::kQuad_SegmentMask; | 396 fSegmentMask |= SkPath::kQuad_SegmentMask; |
373 pCnt = 2; | 397 pCnt = 2; |
374 break; | 398 break; |
375 case SkPath::kConic_Verb: | 399 case SkPath::kConic_Verb: |
376 fSegmentMask |= SkPath::kConic_SegmentMask; | 400 fSegmentMask |= SkPath::kConic_SegmentMask; |
377 pCnt = 2; | 401 pCnt = 2; |
378 break; | 402 break; |
379 case SkPath::kCubic_Verb: | 403 case SkPath::kCubic_Verb: |
380 fSegmentMask |= SkPath::kCubic_SegmentMask; | 404 fSegmentMask |= SkPath::kCubic_SegmentMask; |
381 pCnt = 3; | 405 pCnt = 3; |
382 break; | 406 break; |
383 case SkPath::kClose_Verb: | 407 case SkPath::kClose_Verb: |
| 408 // signal that we need a moveTo to follow us (unless we're done) |
| 409 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToInde
x) - 1); |
384 pCnt = 0; | 410 pCnt = 0; |
385 dirtyAfterEdit = false; | 411 dirtyAfterEdit = false; |
386 break; | 412 break; |
387 case SkPath::kDone_Verb: | 413 case SkPath::kDone_Verb: |
388 SkDEBUGFAIL("growForVerb called for kDone"); | 414 SkDEBUGFAIL("growForVerb called for kDone"); |
389 // fall through | 415 // fall through |
390 default: | 416 default: |
391 SkDEBUGFAIL("default is not reached"); | 417 SkDEBUGFAIL("default is not reached"); |
392 dirtyAfterEdit = false; | 418 dirtyAfterEdit = false; |
393 pCnt = 0; | 419 pCnt = 0; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 fPoints[i].fY - fBounds.fBottom < SK_ScalarNearlyZero)); | 479 fPoints[i].fY - fBounds.fBottom < SK_ScalarNearlyZero)); |
454 if (!fPoints[i].isFinite()) { | 480 if (!fPoints[i].isFinite()) { |
455 isFinite = false; | 481 isFinite = false; |
456 } | 482 } |
457 } | 483 } |
458 SkASSERT(SkToBool(fIsFinite) == isFinite); | 484 SkASSERT(SkToBool(fIsFinite) == isFinite); |
459 } | 485 } |
460 | 486 |
461 #ifdef SK_DEBUG_PATH | 487 #ifdef SK_DEBUG_PATH |
462 uint32_t mask = 0; | 488 uint32_t mask = 0; |
| 489 int lastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE; |
| 490 int pointCnt = 0; |
463 for (int i = 0; i < fVerbCnt; ++i) { | 491 for (int i = 0; i < fVerbCnt; ++i) { |
464 switch (fVerbs[~i]) { | 492 switch (fVerbs[~i]) { |
465 case SkPath::kMove_Verb: | 493 case SkPath::kMove_Verb: |
| 494 lastMoveToIndex = pointCnt; |
| 495 ++pointCnt; |
466 break; | 496 break; |
467 case SkPath::kLine_Verb: | 497 case SkPath::kLine_Verb: |
468 mask |= SkPath::kLine_SegmentMask; | 498 mask |= SkPath::kLine_SegmentMask; |
| 499 ++pointCnt; |
469 break; | 500 break; |
470 case SkPath::kQuad_Verb: | 501 case SkPath::kQuad_Verb: |
471 mask |= SkPath::kQuad_SegmentMask; | 502 mask |= SkPath::kQuad_SegmentMask; |
| 503 pointCnt += 2; |
472 break; | 504 break; |
473 case SkPath::kConic_Verb: | 505 case SkPath::kConic_Verb: |
474 mask |= SkPath::kConic_SegmentMask; | 506 mask |= SkPath::kConic_SegmentMask; |
| 507 pointCnt += 2; |
475 break; | 508 break; |
476 case SkPath::kCubic_Verb: | 509 case SkPath::kCubic_Verb: |
477 mask |= SkPath::kCubic_SegmentMask; | 510 mask |= SkPath::kCubic_SegmentMask; |
| 511 pointCnt += 3; |
478 break; | 512 break; |
479 case SkPath::kClose_Verb: | 513 case SkPath::kClose_Verb: |
| 514 if (lastMoveToIndex >= 0) { |
| 515 lastMoveToIndex = ~lastMoveToIndex; |
| 516 } |
480 break; | 517 break; |
481 case SkPath::kDone_Verb: | 518 case SkPath::kDone_Verb: |
482 SkDEBUGFAIL("Done verb shouldn't be recorded."); | 519 SkDEBUGFAIL("Done verb shouldn't be recorded."); |
483 break; | 520 break; |
484 default: | 521 default: |
485 SkDEBUGFAIL("Unknown Verb"); | 522 SkDEBUGFAIL("Unknown Verb"); |
486 break; | 523 break; |
487 } | 524 } |
488 } | 525 } |
489 SkASSERT(mask == fSegmentMask); | 526 SkASSERT(mask == fSegmentMask); |
| 527 SkASSERT(lastMoveToIndex == fLastMoveToIndex); |
| 528 SkASSERT(pointCnt == fPointCnt); |
490 #endif // SK_DEBUG_PATH | 529 #endif // SK_DEBUG_PATH |
491 } | 530 } |
492 #endif | 531 #endif |
OLD | NEW |