OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #ifndef SkPictureFlat_DEFINED | 8 #ifndef SkPictureFlat_DEFINED |
9 #define SkPictureFlat_DEFINED | 9 #define SkPictureFlat_DEFINED |
10 | 10 |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 385 |
386 /** | 386 /** |
387 * Clears the dictionary of all entries. However, it does NOT free the | 387 * Clears the dictionary of all entries. However, it does NOT free the |
388 * memory that was allocated for each entry (that's owned by controller). | 388 * memory that was allocated for each entry (that's owned by controller). |
389 */ | 389 */ |
390 void reset() { | 390 void reset() { |
391 fIndexedData.rewind(); | 391 fIndexedData.rewind(); |
392 // TODO(mtklein): There's no reason to have the index start from 1. Cle
an this up. | 392 // TODO(mtklein): There's no reason to have the index start from 1. Cle
an this up. |
393 // index 0 is always empty since it is used as a signal that find failed | 393 // index 0 is always empty since it is used as a signal that find failed |
394 fIndexedData.push(NULL); | 394 fIndexedData.push(NULL); |
395 fNextIndex = 1; | |
396 } | 395 } |
397 | 396 |
398 ~SkFlatDictionary() { | 397 ~SkFlatDictionary() { |
399 sk_free(fScratch); | 398 sk_free(fScratch); |
400 } | 399 } |
401 | 400 |
402 int count() const { | 401 int count() const { |
403 SkASSERT(fIndexedData.count() == fNextIndex); | 402 SkASSERT(fHash.count() == fIndexedData.count() - 1); |
404 SkASSERT(fHash.count() == fNextIndex - 1); | 403 return fHash.count(); |
405 return fNextIndex - 1; | |
406 } | 404 } |
407 | 405 |
408 // For testing only. Index is zero-based. | 406 // For testing only. Index is zero-based. |
409 const SkFlatData* operator[](int index) { | 407 const SkFlatData* operator[](int index) { |
410 return fIndexedData[index+1]; | 408 return fIndexedData[index+1]; |
411 } | 409 } |
412 | 410 |
413 /** | 411 /** |
414 * Given an element of type T return its 1-based index in the dictionary. If | 412 * Given an element of type T return its 1-based index in the dictionary. If |
415 * the element wasn't previously in the dictionary it is automatically | 413 * the element wasn't previously in the dictionary it is automatically |
(...skipping 27 matching lines...) Expand all Loading... |
443 return flat; | 441 return flat; |
444 } | 442 } |
445 | 443 |
446 // If we don't have the thing to replace, we're done. | 444 // If we don't have the thing to replace, we're done. |
447 const SkFlatData* found = fHash.find(*toReplace); | 445 const SkFlatData* found = fHash.find(*toReplace); |
448 if (found == NULL) { | 446 if (found == NULL) { |
449 *replaced = false; | 447 *replaced = false; |
450 return flat; | 448 return flat; |
451 } | 449 } |
452 | 450 |
453 // findAndReturnMutableFlat gave us index (fNextIndex-1), but we'll use
the old one. | 451 // findAndReturnMutableFlat put flat at the back. Swap it into found->i
ndex() instead. |
454 fIndexedData.remove(flat->index()); | 452 SkASSERT(flat->index() == this->count()); |
455 fNextIndex--; | |
456 flat->setIndex(found->index()); | 453 flat->setIndex(found->index()); |
457 fIndexedData[flat->index()] = flat; | 454 fIndexedData.removeShuffle(found->index()); |
| 455 SkASSERT(flat == fIndexedData[found->index()]); |
458 | 456 |
459 // findAndReturnMutableFlat already called fHash.add(), so we just clean
up the old entry. | 457 // findAndReturnMutableFlat already called fHash.add(), so we just clean
up the old entry. |
460 fHash.remove(*found); | 458 fHash.remove(*found); |
461 fController->unalloc((void*)found); | 459 fController->unalloc((void*)found); |
462 SkASSERT(this->count() == oldCount); | 460 SkASSERT(this->count() == oldCount); |
463 | 461 |
464 *replaced = true; | 462 *replaced = true; |
465 return flat; | 463 return flat; |
466 } | 464 } |
467 | 465 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); | 529 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); |
532 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); | 530 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); |
533 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); | 531 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
534 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); | 532 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); |
535 fReady = true; | 533 fReady = true; |
536 } | 534 } |
537 | 535 |
538 // As findAndReturnFlat, but returns a mutable pointer for internal use. | 536 // As findAndReturnFlat, but returns a mutable pointer for internal use. |
539 SkFlatData* findAndReturnMutableFlat(const T& element) { | 537 SkFlatData* findAndReturnMutableFlat(const T& element) { |
540 // Only valid until the next call to resetScratch(). | 538 // Only valid until the next call to resetScratch(). |
541 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); | 539 const SkFlatData& scratch = this->resetScratch(element, this->count()+1)
; |
542 | 540 |
543 SkFlatData* candidate = fHash.find(scratch); | 541 SkFlatData* candidate = fHash.find(scratch); |
544 if (candidate != NULL) return candidate; | 542 if (candidate != NULL) return candidate; |
545 | 543 |
546 SkFlatData* detached = this->detachScratch(); | 544 SkFlatData* detached = this->detachScratch(); |
547 fHash.add(detached); | 545 fHash.add(detached); |
548 *fIndexedData.insert(fNextIndex) = detached; | 546 *fIndexedData.append() = detached; |
549 fNextIndex++; | 547 SkASSERT(fIndexedData.top()->index() == this->count()); |
550 return detached; | 548 return detached; |
551 } | 549 } |
552 | 550 |
553 // This reference is valid only until the next call to resetScratch() or det
achScratch(). | 551 // This reference is valid only until the next call to resetScratch() or det
achScratch(). |
554 const SkFlatData& resetScratch(const T& element, int index) { | 552 const SkFlatData& resetScratch(const T& element, int index) { |
555 this->lazyInit(); | 553 this->lazyInit(); |
556 | 554 |
557 // Flatten element into fWriteBuffer (using fScratch as storage). | 555 // Flatten element into fWriteBuffer (using fScratch as storage). |
558 fWriteBuffer.reset(fScratch->data(), fScratchSize); | 556 fWriteBuffer.reset(fScratch->data(), fScratchSize); |
559 Traits::flatten(fWriteBuffer, element); | 557 Traits::flatten(fWriteBuffer, element); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 fController->getTypefacePlayback()); | 598 fController->getTypefacePlayback()); |
601 } | 599 } |
602 | 600 |
603 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. | 601 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. |
604 SkAutoTUnref<SkFlatController> fController; | 602 SkAutoTUnref<SkFlatController> fController; |
605 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. | 603 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. |
606 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre
e. | 604 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre
e. |
607 SkOrderedWriteBuffer fWriteBuffer; | 605 SkOrderedWriteBuffer fWriteBuffer; |
608 bool fReady; | 606 bool fReady; |
609 | 607 |
610 // We map between SkFlatData and a 1-based integer index. | |
611 int fNextIndex; | |
612 | |
613 // For index -> SkFlatData. fIndexedData[0] is always NULL. | 608 // For index -> SkFlatData. fIndexedData[0] is always NULL. |
614 SkTDArray<const SkFlatData*> fIndexedData; | 609 SkTDArray<const SkFlatData*> fIndexedData; |
615 | 610 |
616 // For SkFlatData -> cached SkFlatData, which has index(). | 611 // For SkFlatData -> cached SkFlatData, which has index(). |
617 SkTDynamicHash<SkFlatData, SkFlatData, | 612 SkTDynamicHash<SkFlatData, SkFlatData, |
618 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; | 613 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; |
619 }; | 614 }; |
620 | 615 |
621 /////////////////////////////////////////////////////////////////////////////// | 616 /////////////////////////////////////////////////////////////////////////////// |
622 // Some common dictionaries are defined here for both reference and convenience | 617 // Some common dictionaries are defined here for both reference and convenience |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 } | 679 } |
685 | 680 |
686 private: | 681 private: |
687 SkChunkAlloc fHeap; | 682 SkChunkAlloc fHeap; |
688 SkAutoTUnref<SkRefCntSet> fTypefaceSet; | 683 SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
689 void* fLastAllocated; | 684 void* fLastAllocated; |
690 mutable SkTypefacePlayback fTypefacePlayback; | 685 mutable SkTypefacePlayback fTypefacePlayback; |
691 }; | 686 }; |
692 | 687 |
693 #endif | 688 #endif |
OLD | NEW |