| 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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S
kFlatDictionary; | 369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S
kFlatDictionary; |
| 370 }; | 370 }; |
| 371 | 371 |
| 372 template <typename T, typename Traits, int kScratchSizeGuess=0> | 372 template <typename T, typename Traits, int kScratchSizeGuess=0> |
| 373 class SkFlatDictionary { | 373 class SkFlatDictionary { |
| 374 static const size_t kWriteBufferGrowthBytes = 1024; | 374 static const size_t kWriteBufferGrowthBytes = 1024; |
| 375 | 375 |
| 376 public: | 376 public: |
| 377 explicit SkFlatDictionary(SkFlatController* controller) | 377 explicit SkFlatDictionary(SkFlatController* controller) |
| 378 : fController(SkRef(controller)) | 378 : fController(SkRef(controller)) |
| 379 , fScratchSize(kScratchSizeGuess) | 379 , fScratchSize(0) |
| 380 , fScratch(AllocScratch(fScratchSize)) | 380 , fScratch(NULL) |
| 381 , fWriteBuffer(kWriteBufferGrowthBytes) | 381 , fWriteBuffer(kWriteBufferGrowthBytes) |
| 382 , fWriteBufferReady(false) { | 382 , fReady(false) { |
| 383 this->reset(); | 383 this->reset(); |
| 384 } | 384 } |
| 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. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 SkASSERT(SkIsAlign4(flatDataSize)); | 508 SkASSERT(SkIsAlign4(flatDataSize)); |
| 509 return sizeof(SkFlatData) + flatDataSize; | 509 return sizeof(SkFlatData) + flatDataSize; |
| 510 } | 510 } |
| 511 | 511 |
| 512 // Allocate a new scratch SkFlatData. Must be sk_freed. | 512 // Allocate a new scratch SkFlatData. Must be sk_freed. |
| 513 static SkFlatData* AllocScratch(size_t scratchSize) { | 513 static SkFlatData* AllocScratch(size_t scratchSize) { |
| 514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); | 514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); |
| 515 } | 515 } |
| 516 | 516 |
| 517 // We have to delay fWriteBuffer's initialization until its first use; fCont
roller might not | 517 // We have to delay fWriteBuffer's initialization until its first use; fCont
roller might not |
| 518 // be fully set up by the time we get it in the constructor. | 518 // be fully set up by the time we get it in the constructor. We also delay a
llocating fScratch |
| 519 void lazyWriteBufferInit() { | 519 // to avoid unnecessary heap allocations, since we're paying the price of th
e conditional |
| 520 if (fWriteBufferReady) { | 520 // anyway. |
| 521 void lazyInit() { |
| 522 if (fReady) { |
| 521 return; | 523 return; |
| 522 } | 524 } |
| 525 |
| 526 fScratchSize = kScratchSizeGuess; |
| 527 fScratch = AllocScratch(fScratchSize); |
| 528 |
| 523 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. | 529 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. |
| 524 SkASSERT(fController->getBitmapHeap() != NULL); | 530 SkASSERT(fController->getBitmapHeap() != NULL); |
| 525 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); | 531 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); |
| 526 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); | 532 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); |
| 527 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); | 533 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
| 528 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); | 534 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); |
| 529 fWriteBufferReady = true; | 535 fReady = true; |
| 530 } | 536 } |
| 531 | 537 |
| 532 // As findAndReturnFlat, but returns a mutable pointer for internal use. | 538 // As findAndReturnFlat, but returns a mutable pointer for internal use. |
| 533 SkFlatData* findAndReturnMutableFlat(const T& element) { | 539 SkFlatData* findAndReturnMutableFlat(const T& element) { |
| 534 // Only valid until the next call to resetScratch(). | 540 // Only valid until the next call to resetScratch(). |
| 535 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); | 541 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); |
| 536 | 542 |
| 537 SkFlatData* candidate = fHash.find(scratch); | 543 SkFlatData* candidate = fHash.find(scratch); |
| 538 if (candidate != NULL) return candidate; | 544 if (candidate != NULL) return candidate; |
| 539 | 545 |
| 540 SkFlatData* detached = this->detachScratch(); | 546 SkFlatData* detached = this->detachScratch(); |
| 541 fHash.add(detached); | 547 fHash.add(detached); |
| 542 *fIndexedData.insert(fNextIndex) = detached; | 548 *fIndexedData.insert(fNextIndex) = detached; |
| 543 fNextIndex++; | 549 fNextIndex++; |
| 544 return detached; | 550 return detached; |
| 545 } | 551 } |
| 546 | 552 |
| 547 // This reference is valid only until the next call to resetScratch() or det
achScratch(). | 553 // This reference is valid only until the next call to resetScratch() or det
achScratch(). |
| 548 const SkFlatData& resetScratch(const T& element, int index) { | 554 const SkFlatData& resetScratch(const T& element, int index) { |
| 549 this->lazyWriteBufferInit(); | 555 this->lazyInit(); |
| 550 | 556 |
| 551 // Flatten element into fWriteBuffer (using fScratch as storage). | 557 // Flatten element into fWriteBuffer (using fScratch as storage). |
| 552 fWriteBuffer.reset(fScratch->data(), fScratchSize); | 558 fWriteBuffer.reset(fScratch->data(), fScratchSize); |
| 553 Traits::flatten(fWriteBuffer, element); | 559 Traits::flatten(fWriteBuffer, element); |
| 554 const size_t bytesWritten = fWriteBuffer.bytesWritten(); | 560 const size_t bytesWritten = fWriteBuffer.bytesWritten(); |
| 555 | 561 |
| 556 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. | 562 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. |
| 557 if (!fWriteBuffer.wroteOnlyToStorage()) { | 563 if (!fWriteBuffer.wroteOnlyToStorage()) { |
| 558 SkASSERT(bytesWritten > fScratchSize); | 564 SkASSERT(bytesWritten > fScratchSize); |
| 559 // It didn't all fit. Copy into a larger replacement SkFlatData. | 565 // It didn't all fit. Copy into a larger replacement SkFlatData. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 570 // The data is in fScratch now but we need to stamp its header. | 576 // The data is in fScratch now but we need to stamp its header. |
| 571 fScratch->stampHeader(index, bytesWritten); | 577 fScratch->stampHeader(index, bytesWritten); |
| 572 return *fScratch; | 578 return *fScratch; |
| 573 } | 579 } |
| 574 | 580 |
| 575 // This result is owned by fController and lives as long as it does (unless
unalloc'd). | 581 // This result is owned by fController and lives as long as it does (unless
unalloc'd). |
| 576 SkFlatData* detachScratch() { | 582 SkFlatData* detachScratch() { |
| 577 // Allocate a new SkFlatData exactly big enough to hold our current scra
tch. | 583 // Allocate a new SkFlatData exactly big enough to hold our current scra
tch. |
| 578 // We use the controller for this allocation to extend the allocation's
lifetime and allow | 584 // We use the controller for this allocation to extend the allocation's
lifetime and allow |
| 579 // the controller to do whatever memory management it wants. | 585 // the controller to do whatever memory management it wants. |
| 586 SkASSERT(fScratch != NULL); |
| 580 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); | 587 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); |
| 581 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); | 588 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); |
| 582 | 589 |
| 583 // Copy scratch into the new SkFlatData. | 590 // Copy scratch into the new SkFlatData. |
| 584 memcpy(detached, fScratch, paddedSize); | 591 memcpy(detached, fScratch, paddedSize); |
| 585 | 592 |
| 586 // We can now reuse fScratch, and detached will live until fController d
ies. | 593 // We can now reuse fScratch, and detached will live until fController d
ies. |
| 587 return detached; | 594 return detached; |
| 588 } | 595 } |
| 589 | 596 |
| 590 void unflatten(T* dst, const SkFlatData* element) const { | 597 void unflatten(T* dst, const SkFlatData* element) const { |
| 591 element->unflatten<Traits>(dst, | 598 element->unflatten<Traits>(dst, |
| 592 fController->getBitmapHeap(), | 599 fController->getBitmapHeap(), |
| 593 fController->getTypefacePlayback()); | 600 fController->getTypefacePlayback()); |
| 594 } | 601 } |
| 595 | 602 |
| 596 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. | 603 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. |
| 597 SkAutoTUnref<SkFlatController> fController; | 604 SkAutoTUnref<SkFlatController> fController; |
| 598 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. | 605 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. |
| 599 SkFlatData* fScratch; // Owned, must be freed with sk_free. | 606 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre
e. |
| 600 SkOrderedWriteBuffer fWriteBuffer; | 607 SkOrderedWriteBuffer fWriteBuffer; |
| 601 bool fWriteBufferReady; | 608 bool fReady; |
| 602 | 609 |
| 603 // We map between SkFlatData and a 1-based integer index. | 610 // We map between SkFlatData and a 1-based integer index. |
| 604 int fNextIndex; | 611 int fNextIndex; |
| 605 | 612 |
| 606 // For index -> SkFlatData. fIndexedData[0] is always NULL. | 613 // For index -> SkFlatData. fIndexedData[0] is always NULL. |
| 607 SkTDArray<const SkFlatData*> fIndexedData; | 614 SkTDArray<const SkFlatData*> fIndexedData; |
| 608 | 615 |
| 609 // For SkFlatData -> cached SkFlatData, which has index(). | 616 // For SkFlatData -> cached SkFlatData, which has index(). |
| 610 SkTDynamicHash<SkFlatData, SkFlatData, | 617 SkTDynamicHash<SkFlatData, SkFlatData, |
| 611 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; | 618 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 } | 684 } |
| 678 | 685 |
| 679 private: | 686 private: |
| 680 SkChunkAlloc fHeap; | 687 SkChunkAlloc fHeap; |
| 681 SkAutoTUnref<SkRefCntSet> fTypefaceSet; | 688 SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
| 682 void* fLastAllocated; | 689 void* fLastAllocated; |
| 683 mutable SkTypefacePlayback fTypefacePlayback; | 690 mutable SkTypefacePlayback fTypefacePlayback; |
| 684 }; | 691 }; |
| 685 | 692 |
| 686 #endif | 693 #endif |
| OLD | NEW |