| 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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 SkTypefacePlayback* fTypefacePlayback; | 260 SkTypefacePlayback* fTypefacePlayback; |
| 261 SkNamedFactorySet* fFactorySet; | 261 SkNamedFactorySet* fFactorySet; |
| 262 uint32_t fWriteBufferFlags; | 262 uint32_t fWriteBufferFlags; |
| 263 | 263 |
| 264 typedef SkRefCnt INHERITED; | 264 typedef SkRefCnt INHERITED; |
| 265 }; | 265 }; |
| 266 | 266 |
| 267 class SkFlatData { | 267 class SkFlatData { |
| 268 public: | 268 public: |
| 269 // Flatten obj into an SkFlatData with this index. controller owns the SkFl
atData*. | 269 // Flatten obj into an SkFlatData with this index. controller owns the SkFl
atData*. |
| 270 static SkFlatData* Create(SkFlatController* controller, | 270 template <typename Traits, typename T> |
| 271 const void* obj, | 271 static SkFlatData* Create(SkFlatController* controller, const T& obj, int in
dex) { |
| 272 int index, | 272 // A buffer of 256 bytes should fit most paints, regions, and matrices. |
| 273 void (*flattenProc)(SkOrderedWriteBuffer&, const v
oid*)); | 273 uint32_t storage[64]; |
| 274 SkOrderedWriteBuffer buffer(256, storage, sizeof(storage)); |
| 274 | 275 |
| 275 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps
and fonts if given. | 276 buffer.setBitmapHeap(controller->getBitmapHeap()); |
| 276 void unflatten(void* result, | 277 buffer.setTypefaceRecorder(controller->getTypefaceSet()); |
| 277 void (*unflattenProc)(SkOrderedReadBuffer&, void*), | 278 buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); |
| 279 buffer.setFlags(controller->getWriteBufferFlags()); |
| 280 |
| 281 Traits::flatten(buffer, obj); |
| 282 uint32_t size = buffer.size(); |
| 283 SkASSERT(SkIsAlign4(size)); |
| 284 |
| 285 // Allocate enough memory to hold SkFlatData struct and the flat data it
self. |
| 286 size_t allocSize = sizeof(SkFlatData) + size; |
| 287 SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize); |
| 288 |
| 289 // Put the serialized contents into the data section of the new allocati
on. |
| 290 buffer.writeToMemory(result->data()); |
| 291 // Stamp the index, size and checksum in the header. |
| 292 result->stampHeader(index, size); |
| 293 return result; |
| 294 } |
| 295 |
| 296 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps
and fonts if given |
| 297 template <typename Traits, typename T> |
| 298 void unflatten(T* result, |
| 278 SkBitmapHeap* bitmapHeap = NULL, | 299 SkBitmapHeap* bitmapHeap = NULL, |
| 279 SkTypefacePlayback* facePlayback = NULL) const; | 300 SkTypefacePlayback* facePlayback = NULL) const { |
| 301 SkOrderedReadBuffer buffer(this->data(), fFlatSize); |
| 302 |
| 303 if (bitmapHeap) { |
| 304 buffer.setBitmapStorage(bitmapHeap); |
| 305 } |
| 306 if (facePlayback) { |
| 307 facePlayback->setupBuffer(buffer); |
| 308 } |
| 309 |
| 310 Traits::unflatten(buffer, result); |
| 311 SkASSERT(fFlatSize == (int32_t)buffer.offset()); |
| 312 } |
| 280 | 313 |
| 281 // Do these contain the same data? Ignores index() and topBot(). | 314 // Do these contain the same data? Ignores index() and topBot(). |
| 282 bool operator==(const SkFlatData& that) const { | 315 bool operator==(const SkFlatData& that) const { |
| 283 if (this->checksum() != that.checksum() || this->flatSize() != that.flat
Size()) { | 316 if (this->checksum() != that.checksum() || this->flatSize() != that.flat
Size()) { |
| 284 return false; | 317 return false; |
| 285 } | 318 } |
| 286 return memcmp(this->data(), that.data(), this->flatSize()) == 0; | 319 return memcmp(this->data(), that.data(), this->flatSize()) == 0; |
| 287 } | 320 } |
| 288 | 321 |
| 289 int index() const { return fIndex; } | 322 int index() const { return fIndex; } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten. | 359 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten. |
| 327 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size); | 360 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size); |
| 328 } | 361 } |
| 329 | 362 |
| 330 int fIndex; | 363 int fIndex; |
| 331 int32_t fFlatSize; | 364 int32_t fFlatSize; |
| 332 uint32_t fChecksum; | 365 uint32_t fChecksum; |
| 333 mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts
as [NaN,?]. | 366 mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts
as [NaN,?]. |
| 334 // uint32_t flattenedData[] implicitly hangs off the end. | 367 // uint32_t flattenedData[] implicitly hangs off the end. |
| 335 | 368 |
| 336 template <class T> friend class SkFlatDictionary; | 369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S
kFlatDictionary; |
| 337 }; | 370 }; |
| 338 | 371 |
| 339 template <class T> | 372 template <typename T, typename Traits, int kScratchSizeGuess=0> |
| 340 class SkFlatDictionary { | 373 class SkFlatDictionary { |
| 341 static const size_t kWriteBufferGrowthBytes = 1024; | 374 static const size_t kWriteBufferGrowthBytes = 1024; |
| 342 | 375 |
| 343 public: | 376 public: |
| 344 SkFlatDictionary(SkFlatController* controller, size_t scratchSizeGuess = 0) | 377 explicit SkFlatDictionary(SkFlatController* controller) |
| 345 : fFlattenProc(NULL) | 378 : fController(SkRef(controller)) |
| 346 , fUnflattenProc(NULL) | 379 , fScratchSize(kScratchSizeGuess) |
| 347 , fController(SkRef(controller)) | |
| 348 , fScratchSize(scratchSizeGuess) | |
| 349 , fScratch(AllocScratch(fScratchSize)) | 380 , fScratch(AllocScratch(fScratchSize)) |
| 350 , fWriteBuffer(kWriteBufferGrowthBytes) | 381 , fWriteBuffer(kWriteBufferGrowthBytes) |
| 351 , fWriteBufferReady(false) { | 382 , fWriteBufferReady(false) { |
| 352 this->reset(); | 383 this->reset(); |
| 353 } | 384 } |
| 354 | 385 |
| 355 /** | 386 /** |
| 356 * 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 |
| 357 * 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). |
| 358 */ | 389 */ |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 } | 495 } |
| 465 | 496 |
| 466 /** | 497 /** |
| 467 * Find or insert a flattened version of element into the dictionary. | 498 * Find or insert a flattened version of element into the dictionary. |
| 468 * Caller does not take ownership of the result. This will not return NULL. | 499 * Caller does not take ownership of the result. This will not return NULL. |
| 469 */ | 500 */ |
| 470 const SkFlatData* findAndReturnFlat(const T& element) { | 501 const SkFlatData* findAndReturnFlat(const T& element) { |
| 471 return this->findAndReturnMutableFlat(element); | 502 return this->findAndReturnMutableFlat(element); |
| 472 } | 503 } |
| 473 | 504 |
| 474 protected: | |
| 475 void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*); | |
| 476 void (*fUnflattenProc)(SkOrderedReadBuffer&, void*); | |
| 477 | |
| 478 private: | 505 private: |
| 479 // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] | 506 // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] |
| 480 static size_t SizeWithPadding(size_t flatDataSize) { | 507 static size_t SizeWithPadding(size_t flatDataSize) { |
| 481 SkASSERT(SkIsAlign4(flatDataSize)); | 508 SkASSERT(SkIsAlign4(flatDataSize)); |
| 482 return sizeof(SkFlatData) + flatDataSize; | 509 return sizeof(SkFlatData) + flatDataSize; |
| 483 } | 510 } |
| 484 | 511 |
| 485 // Allocate a new scratch SkFlatData. Must be sk_freed. | 512 // Allocate a new scratch SkFlatData. Must be sk_freed. |
| 486 static SkFlatData* AllocScratch(size_t scratchSize) { | 513 static SkFlatData* AllocScratch(size_t scratchSize) { |
| 487 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); | 514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 516 fNextIndex++; | 543 fNextIndex++; |
| 517 return detached; | 544 return detached; |
| 518 } | 545 } |
| 519 | 546 |
| 520 // This reference is valid only until the next call to resetScratch() or det
achScratch(). | 547 // This reference is valid only until the next call to resetScratch() or det
achScratch(). |
| 521 const SkFlatData& resetScratch(const T& element, int index) { | 548 const SkFlatData& resetScratch(const T& element, int index) { |
| 522 this->lazyWriteBufferInit(); | 549 this->lazyWriteBufferInit(); |
| 523 | 550 |
| 524 // Flatten element into fWriteBuffer (using fScratch as storage). | 551 // Flatten element into fWriteBuffer (using fScratch as storage). |
| 525 fWriteBuffer.reset(fScratch->data(), fScratchSize); | 552 fWriteBuffer.reset(fScratch->data(), fScratchSize); |
| 526 fFlattenProc(fWriteBuffer, &element); | 553 Traits::flatten(fWriteBuffer, element); |
| 527 const size_t bytesWritten = fWriteBuffer.bytesWritten(); | 554 const size_t bytesWritten = fWriteBuffer.bytesWritten(); |
| 528 | 555 |
| 529 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. | 556 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. |
| 530 if (!fWriteBuffer.wroteOnlyToStorage()) { | 557 if (!fWriteBuffer.wroteOnlyToStorage()) { |
| 531 SkASSERT(bytesWritten > fScratchSize); | 558 SkASSERT(bytesWritten > fScratchSize); |
| 532 // It didn't all fit. Copy into a larger replacement SkFlatData. | 559 // It didn't all fit. Copy into a larger replacement SkFlatData. |
| 533 // We can't just realloc because it might move the pointer and confu
se writeToMemory. | 560 // We can't just realloc because it might move the pointer and confu
se writeToMemory. |
| 534 SkFlatData* larger = AllocScratch(bytesWritten); | 561 SkFlatData* larger = AllocScratch(bytesWritten); |
| 535 fWriteBuffer.writeToMemory(larger->data()); | 562 fWriteBuffer.writeToMemory(larger->data()); |
| 536 | 563 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 554 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); | 581 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); |
| 555 | 582 |
| 556 // Copy scratch into the new SkFlatData. | 583 // Copy scratch into the new SkFlatData. |
| 557 memcpy(detached, fScratch, paddedSize); | 584 memcpy(detached, fScratch, paddedSize); |
| 558 | 585 |
| 559 // We can now reuse fScratch, and detached will live until fController d
ies. | 586 // We can now reuse fScratch, and detached will live until fController d
ies. |
| 560 return detached; | 587 return detached; |
| 561 } | 588 } |
| 562 | 589 |
| 563 void unflatten(T* dst, const SkFlatData* element) const { | 590 void unflatten(T* dst, const SkFlatData* element) const { |
| 564 element->unflatten(dst, | 591 element->unflatten<Traits>(dst, |
| 565 fUnflattenProc, | 592 fController->getBitmapHeap(), |
| 566 fController->getBitmapHeap(), | 593 fController->getTypefacePlayback()); |
| 567 fController->getTypefacePlayback()); | |
| 568 } | 594 } |
| 569 | 595 |
| 570 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. | 596 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. |
| 571 SkAutoTUnref<SkFlatController> fController; | 597 SkAutoTUnref<SkFlatController> fController; |
| 572 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. | 598 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. |
| 573 SkFlatData* fScratch; // Owned, must be freed with sk_free. | 599 SkFlatData* fScratch; // Owned, must be freed with sk_free. |
| 574 SkOrderedWriteBuffer fWriteBuffer; | 600 SkOrderedWriteBuffer fWriteBuffer; |
| 575 bool fWriteBufferReady; | 601 bool fWriteBufferReady; |
| 576 | 602 |
| 577 // We map between SkFlatData and a 1-based integer index. | 603 // We map between SkFlatData and a 1-based integer index. |
| 578 int fNextIndex; | 604 int fNextIndex; |
| 579 | 605 |
| 580 // For index -> SkFlatData. fIndexedData[0] is always NULL. | 606 // For index -> SkFlatData. fIndexedData[0] is always NULL. |
| 581 SkTDArray<const SkFlatData*> fIndexedData; | 607 SkTDArray<const SkFlatData*> fIndexedData; |
| 582 | 608 |
| 583 // For SkFlatData -> cached SkFlatData, which has index(). | 609 // For SkFlatData -> cached SkFlatData, which has index(). |
| 584 SkTDynamicHash<SkFlatData, SkFlatData, | 610 SkTDynamicHash<SkFlatData, SkFlatData, |
| 585 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; | 611 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; |
| 586 }; | 612 }; |
| 587 | 613 |
| 588 /////////////////////////////////////////////////////////////////////////////// | 614 /////////////////////////////////////////////////////////////////////////////// |
| 589 // Some common dictionaries are defined here for both reference and convenience | 615 // Some common dictionaries are defined here for both reference and convenience |
| 590 /////////////////////////////////////////////////////////////////////////////// | 616 /////////////////////////////////////////////////////////////////////////////// |
| 591 | 617 |
| 592 template <class T> | 618 struct SkMatrixTraits { |
| 593 static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) { | 619 static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) { |
| 594 ((T*)obj)->flatten(buffer); | 620 buffer.getWriter32()->writeMatrix(matrix); |
| 595 } | 621 } |
| 622 static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) { |
| 623 buffer.getReader32()->readMatrix(matrix); |
| 624 } |
| 625 }; |
| 626 typedef SkFlatDictionary<SkMatrix, SkMatrixTraits, 36> SkMatrixDictionary; |
| 596 | 627 |
| 597 template <class T> | 628 |
| 598 static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) { | 629 struct SkRegionTraits { |
| 599 ((T*)obj)->unflatten(buffer); | 630 static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) { |
| 600 } | 631 buffer.getWriter32()->writeRegion(region); |
| 632 } |
| 633 static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) { |
| 634 buffer.getReader32()->readRegion(region); |
| 635 } |
| 636 }; |
| 637 typedef SkFlatDictionary<SkRegion, SkRegionTraits> SkRegionDictionary; |
| 638 |
| 639 |
| 640 struct SkPaintTraits { |
| 641 static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) { |
| 642 paint.flatten(buffer); |
| 643 } |
| 644 static void unflatten(SkOrderedReadBuffer& buffer, SkPaint* paint) { |
| 645 paint->unflatten(buffer); |
| 646 } |
| 647 }; |
| 648 typedef SkFlatDictionary<SkPaint, SkPaintTraits, 512> SkPaintDictionary; |
| 601 | 649 |
| 602 class SkChunkFlatController : public SkFlatController { | 650 class SkChunkFlatController : public SkFlatController { |
| 603 public: | 651 public: |
| 604 SkChunkFlatController(size_t minSize) | 652 SkChunkFlatController(size_t minSize) |
| 605 : fHeap(minSize) | 653 : fHeap(minSize) |
| 606 , fTypefaceSet(SkNEW(SkRefCntSet)) | 654 , fTypefaceSet(SkNEW(SkRefCntSet)) |
| 607 , fLastAllocated(NULL) { | 655 , fLastAllocated(NULL) { |
| 608 this->setTypefaceSet(fTypefaceSet); | 656 this->setTypefaceSet(fTypefaceSet); |
| 609 this->setTypefacePlayback(&fTypefacePlayback); | 657 this->setTypefacePlayback(&fTypefacePlayback); |
| 610 } | 658 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 628 this->setBitmapHeap(heap); | 676 this->setBitmapHeap(heap); |
| 629 } | 677 } |
| 630 | 678 |
| 631 private: | 679 private: |
| 632 SkChunkAlloc fHeap; | 680 SkChunkAlloc fHeap; |
| 633 SkAutoTUnref<SkRefCntSet> fTypefaceSet; | 681 SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
| 634 void* fLastAllocated; | 682 void* fLastAllocated; |
| 635 mutable SkTypefacePlayback fTypefacePlayback; | 683 mutable SkTypefacePlayback fTypefacePlayback; |
| 636 }; | 684 }; |
| 637 | 685 |
| 638 class SkMatrixDictionary : public SkFlatDictionary<SkMatrix> { | |
| 639 public: | |
| 640 // All matrices fit in 36 bytes. | |
| 641 SkMatrixDictionary(SkFlatController* controller) | |
| 642 : SkFlatDictionary<SkMatrix>(controller, 36) { | |
| 643 fFlattenProc = &flattenMatrix; | |
| 644 fUnflattenProc = &unflattenMatrix; | |
| 645 } | |
| 646 | |
| 647 static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) { | |
| 648 buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj); | |
| 649 } | |
| 650 | |
| 651 static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) { | |
| 652 buffer.getReader32()->readMatrix((SkMatrix*)obj); | |
| 653 } | |
| 654 }; | |
| 655 | |
| 656 class SkPaintDictionary : public SkFlatDictionary<SkPaint> { | |
| 657 public: | |
| 658 // The largest paint across ~60 .skps was 500 bytes. | |
| 659 SkPaintDictionary(SkFlatController* controller) | |
| 660 : SkFlatDictionary<SkPaint>(controller, 512) { | |
| 661 fFlattenProc = &SkFlattenObjectProc<SkPaint>; | |
| 662 fUnflattenProc = &SkUnflattenObjectProc<SkPaint>; | |
| 663 } | |
| 664 }; | |
| 665 | |
| 666 class SkRegionDictionary : public SkFlatDictionary<SkRegion> { | |
| 667 public: | |
| 668 SkRegionDictionary(SkFlatController* controller) | |
| 669 : SkFlatDictionary<SkRegion>(controller) { | |
| 670 fFlattenProc = &flattenRegion; | |
| 671 fUnflattenProc = &unflattenRegion; | |
| 672 } | |
| 673 | |
| 674 static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) { | |
| 675 buffer.getWriter32()->writeRegion(*(SkRegion*)obj); | |
| 676 } | |
| 677 | |
| 678 static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) { | |
| 679 buffer.getReader32()->readRegion((SkRegion*)obj); | |
| 680 } | |
| 681 }; | |
| 682 | |
| 683 #endif | 686 #endif |
| OLD | NEW |