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 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 // Put the serialized contents into the data section of the new allocati
on. | 289 // Put the serialized contents into the data section of the new allocati
on. |
290 buffer.writeToMemory(result->data()); | 290 buffer.writeToMemory(result->data()); |
291 // Stamp the index, size and checksum in the header. | 291 // Stamp the index, size and checksum in the header. |
292 result->stampHeader(index, SkToS32(size)); | 292 result->stampHeader(index, SkToS32(size)); |
293 return result; | 293 return result; |
294 } | 294 } |
295 | 295 |
296 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps
and fonts if given | 296 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps
and fonts if given |
297 template <typename Traits, typename T> | 297 template <typename Traits, typename T> |
298 void unflatten(T* result, | 298 void unflatten(T* result, |
299 SkBitmapHeap* bitmapHeap = NULL, | 299 SkBitmapHeap* bitmapHeap = nullptr, |
300 SkTypefacePlayback* facePlayback = NULL) const { | 300 SkTypefacePlayback* facePlayback = nullptr) const { |
301 SkReadBuffer buffer(this->data(), fFlatSize); | 301 SkReadBuffer buffer(this->data(), fFlatSize); |
302 | 302 |
303 if (bitmapHeap) { | 303 if (bitmapHeap) { |
304 buffer.setBitmapStorage(bitmapHeap); | 304 buffer.setBitmapStorage(bitmapHeap); |
305 } | 305 } |
306 if (facePlayback) { | 306 if (facePlayback) { |
307 facePlayback->setupBuffer(buffer); | 307 facePlayback->setupBuffer(buffer); |
308 } | 308 } |
309 | 309 |
310 Traits::Unflatten(buffer, result); | 310 Traits::Unflatten(buffer, result); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 * | 404 * |
405 */ | 405 */ |
406 int find(const T& element) { | 406 int find(const T& element) { |
407 return this->findAndReturnFlat(element)->index(); | 407 return this->findAndReturnFlat(element)->index(); |
408 } | 408 } |
409 | 409 |
410 /** | 410 /** |
411 * Similar to find. Allows the caller to specify an SkFlatData to replace in | 411 * Similar to find. Allows the caller to specify an SkFlatData to replace in |
412 * the case of an add. Also tells the caller whether a new SkFlatData was | 412 * the case of an add. Also tells the caller whether a new SkFlatData was |
413 * added and whether the old one was replaced. The parameters added and | 413 * added and whether the old one was replaced. The parameters added and |
414 * replaced are required to be non-NULL. Rather than returning the index of | 414 * replaced are required to be non-nullptr. Rather than returning the index
of |
415 * the entry in the dictionary, it returns the actual SkFlatData. | 415 * the entry in the dictionary, it returns the actual SkFlatData. |
416 */ | 416 */ |
417 const SkFlatData* findAndReplace(const T& element, | 417 const SkFlatData* findAndReplace(const T& element, |
418 const SkFlatData* toReplace, | 418 const SkFlatData* toReplace, |
419 bool* added, | 419 bool* added, |
420 bool* replaced) { | 420 bool* replaced) { |
421 SkASSERT(added != NULL && replaced != NULL); | 421 SkASSERT(added != nullptr && replaced != nullptr); |
422 | 422 |
423 const int oldCount = this->count(); | 423 const int oldCount = this->count(); |
424 SkFlatData* flat = this->findAndReturnMutableFlat(element); | 424 SkFlatData* flat = this->findAndReturnMutableFlat(element); |
425 *added = this->count() > oldCount; | 425 *added = this->count() > oldCount; |
426 | 426 |
427 // If we don't want to replace anything, we're done. | 427 // If we don't want to replace anything, we're done. |
428 if (!*added || toReplace == NULL) { | 428 if (!*added || toReplace == nullptr) { |
429 *replaced = false; | 429 *replaced = false; |
430 return flat; | 430 return flat; |
431 } | 431 } |
432 | 432 |
433 // If we don't have the thing to replace, we're done. | 433 // If we don't have the thing to replace, we're done. |
434 const SkFlatData* found = fHash.find(*toReplace); | 434 const SkFlatData* found = fHash.find(*toReplace); |
435 if (found == NULL) { | 435 if (found == nullptr) { |
436 *replaced = false; | 436 *replaced = false; |
437 return flat; | 437 return flat; |
438 } | 438 } |
439 | 439 |
440 // findAndReturnMutableFlat put flat at the back. Swap it into found->i
ndex() instead. | 440 // findAndReturnMutableFlat put flat at the back. Swap it into found->i
ndex() instead. |
441 // indices in SkFlatData are 1-based, while fIndexedData is 0-based. Wa
tch out! | 441 // indices in SkFlatData are 1-based, while fIndexedData is 0-based. Wa
tch out! |
442 SkASSERT(flat->index() == this->count()); | 442 SkASSERT(flat->index() == this->count()); |
443 flat->setIndex(found->index()); | 443 flat->setIndex(found->index()); |
444 fIndexedData.removeShuffle(found->index()-1); | 444 fIndexedData.removeShuffle(found->index()-1); |
445 SkASSERT(flat == fIndexedData[found->index()-1]); | 445 SkASSERT(flat == fIndexedData[found->index()-1]); |
(...skipping 16 matching lines...) Expand all Loading... |
462 const SkFlatData* element = fIndexedData[index-1]; | 462 const SkFlatData* element = fIndexedData[index-1]; |
463 SkASSERT(index == element->index()); | 463 SkASSERT(index == element->index()); |
464 | 464 |
465 T* dst = new T; | 465 T* dst = new T; |
466 this->unflatten(dst, element); | 466 this->unflatten(dst, element); |
467 return dst; | 467 return dst; |
468 } | 468 } |
469 | 469 |
470 /** | 470 /** |
471 * Find or insert a flattened version of element into the dictionary. | 471 * Find or insert a flattened version of element into the dictionary. |
472 * Caller does not take ownership of the result. This will not return NULL. | 472 * Caller does not take ownership of the result. This will not return nullp
tr. |
473 */ | 473 */ |
474 const SkFlatData* findAndReturnFlat(const T& element) { | 474 const SkFlatData* findAndReturnFlat(const T& element) { |
475 return this->findAndReturnMutableFlat(element); | 475 return this->findAndReturnMutableFlat(element); |
476 } | 476 } |
477 | 477 |
478 private: | 478 private: |
479 // We have to delay fScratch's initialization until its first use; fControll
er might not | 479 // We have to delay fScratch's initialization until its first use; fControll
er might not |
480 // be fully set up by the time we get it in the constructor. | 480 // be fully set up by the time we get it in the constructor. |
481 void lazyInit() { | 481 void lazyInit() { |
482 if (fReady) { | 482 if (fReady) { |
483 return; | 483 return; |
484 } | 484 } |
485 | 485 |
486 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. | 486 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. |
487 SkASSERT(fController->getBitmapHeap() != NULL); | 487 SkASSERT(fController->getBitmapHeap() != nullptr); |
488 fScratch.setBitmapHeap(fController->getBitmapHeap()); | 488 fScratch.setBitmapHeap(fController->getBitmapHeap()); |
489 fScratch.setTypefaceRecorder(fController->getTypefaceSet()); | 489 fScratch.setTypefaceRecorder(fController->getTypefaceSet()); |
490 fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet()); | 490 fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
491 fReady = true; | 491 fReady = true; |
492 } | 492 } |
493 | 493 |
494 // As findAndReturnFlat, but returns a mutable pointer for internal use. | 494 // As findAndReturnFlat, but returns a mutable pointer for internal use. |
495 SkFlatData* findAndReturnMutableFlat(const T& element) { | 495 SkFlatData* findAndReturnMutableFlat(const T& element) { |
496 // Only valid until the next call to resetScratch(). | 496 // Only valid until the next call to resetScratch(). |
497 const SkFlatData& scratch = this->resetScratch(element, this->count()+1)
; | 497 const SkFlatData& scratch = this->resetScratch(element, this->count()+1)
; |
498 | 498 |
499 SkFlatData* candidate = fHash.find(scratch); | 499 SkFlatData* candidate = fHash.find(scratch); |
500 if (candidate != NULL) { | 500 if (candidate != nullptr) { |
501 return candidate; | 501 return candidate; |
502 } | 502 } |
503 | 503 |
504 SkFlatData* detached = this->detachScratch(); | 504 SkFlatData* detached = this->detachScratch(); |
505 fHash.add(detached); | 505 fHash.add(detached); |
506 *fIndexedData.append() = detached; | 506 *fIndexedData.append() = detached; |
507 SkASSERT(fIndexedData.top()->index() == this->count()); | 507 SkASSERT(fIndexedData.top()->index() == this->count()); |
508 return detached; | 508 return detached; |
509 } | 509 } |
510 | 510 |
511 // This reference is valid only until the next call to resetScratch() or det
achScratch(). | 511 // This reference is valid only until the next call to resetScratch() or det
achScratch(). |
512 const SkFlatData& resetScratch(const T& element, int index) { | 512 const SkFlatData& resetScratch(const T& element, int index) { |
513 this->lazyInit(); | 513 this->lazyInit(); |
514 | 514 |
515 // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byt
e aligned ] | 515 // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byt
e aligned ] |
516 fScratch.reset(); | 516 fScratch.reset(); |
517 fScratch.reserve(sizeof(SkFlatData)); | 517 fScratch.reserve(sizeof(SkFlatData)); |
518 Traits::Flatten(fScratch, element); | 518 Traits::Flatten(fScratch, element); |
519 const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData); | 519 const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData); |
520 | 520 |
521 // Reinterpret data in fScratch as an SkFlatData. | 521 // Reinterpret data in fScratch as an SkFlatData. |
522 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr
ay(); | 522 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr
ay(); |
523 SkASSERT(scratch != NULL); | 523 SkASSERT(scratch != nullptr); |
524 scratch->stampHeader(index, SkToS32(dataSize)); | 524 scratch->stampHeader(index, SkToS32(dataSize)); |
525 return *scratch; | 525 return *scratch; |
526 } | 526 } |
527 | 527 |
528 // This result is owned by fController and lives as long as it does (unless
unalloc'd). | 528 // This result is owned by fController and lives as long as it does (unless
unalloc'd). |
529 SkFlatData* detachScratch() { | 529 SkFlatData* detachScratch() { |
530 // Allocate a new SkFlatData exactly big enough to hold our current scra
tch. | 530 // Allocate a new SkFlatData exactly big enough to hold our current scra
tch. |
531 // We use the controller for this allocation to extend the allocation's
lifetime and allow | 531 // We use the controller for this allocation to extend the allocation's
lifetime and allow |
532 // the controller to do whatever memory management it wants. | 532 // the controller to do whatever memory management it wants. |
533 SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.byt
esWritten()); | 533 SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.byt
esWritten()); |
534 | 534 |
535 // Copy scratch into the new SkFlatData. | 535 // Copy scratch into the new SkFlatData. |
536 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr
ay(); | 536 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr
ay(); |
537 SkASSERT(scratch != NULL); | 537 SkASSERT(scratch != nullptr); |
538 memcpy(detached, scratch, fScratch.bytesWritten()); | 538 memcpy(detached, scratch, fScratch.bytesWritten()); |
539 | 539 |
540 // We can now reuse fScratch, and detached will live until fController d
ies. | 540 // We can now reuse fScratch, and detached will live until fController d
ies. |
541 return detached; | 541 return detached; |
542 } | 542 } |
543 | 543 |
544 void unflatten(T* dst, const SkFlatData* element) const { | 544 void unflatten(T* dst, const SkFlatData* element) const { |
545 element->unflatten<Traits>(dst, | 545 element->unflatten<Traits>(dst, |
546 fController->getBitmapHeap(), | 546 fController->getBitmapHeap(), |
547 fController->getTypefacePlayback()); | 547 fController->getTypefacePlayback()); |
548 } | 548 } |
549 | 549 |
550 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. | 550 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. |
551 SkAutoTUnref<SkFlatController> fController; | 551 SkAutoTUnref<SkFlatController> fController; |
552 SkWriteBuffer fScratch; | 552 SkWriteBuffer fScratch; |
553 bool fReady; | 553 bool fReady; |
554 | 554 |
555 // For index -> SkFlatData. 0-based, while all indices in the API are 1-bas
ed. Careful! | 555 // For index -> SkFlatData. 0-based, while all indices in the API are 1-bas
ed. Careful! |
556 SkTDArray<const SkFlatData*> fIndexedData; | 556 SkTDArray<const SkFlatData*> fIndexedData; |
557 | 557 |
558 // For SkFlatData -> cached SkFlatData, which has index(). | 558 // For SkFlatData -> cached SkFlatData, which has index(). |
559 SkTDynamicHash<SkFlatData, SkFlatData, SkFlatData::HashTraits> fHash; | 559 SkTDynamicHash<SkFlatData, SkFlatData, SkFlatData::HashTraits> fHash; |
560 }; | 560 }; |
561 | 561 |
562 #endif | 562 #endif |
OLD | NEW |