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 |