| 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 |