Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include <new> | 7 #include <new> |
| 8 #include "SkPictureData.h" | 8 #include "SkPictureData.h" |
| 9 #include "SkPictureRecord.h" | 9 #include "SkPictureRecord.h" |
| 10 #include "SkReadBuffer.h" | 10 #include "SkReadBuffer.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 | 61 |
| 62 // templatize to consolidate with similar picture logic? | 62 // templatize to consolidate with similar picture logic? |
| 63 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs(); | 63 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs(); |
| 64 fTextBlobCount = blobs.count(); | 64 fTextBlobCount = blobs.count(); |
| 65 if (fTextBlobCount > 0) { | 65 if (fTextBlobCount > 0) { |
| 66 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); | 66 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); |
| 67 for (int i = 0; i < fTextBlobCount; ++i) { | 67 for (int i = 0; i < fTextBlobCount; ++i) { |
| 68 fTextBlobRefs[i] = SkRef(blobs[i]); | 68 fTextBlobRefs[i] = SkRef(blobs[i]); |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 | |
| 72 const SkTDArray<const SkImage*>& imgs = record.getImageRefs(); | |
| 73 fImageCount = imgs.count(); | |
| 74 if (fImageCount > 0) { | |
| 75 fImageRefs = SkNEW_ARRAY(const SkImage*, fImageCount); | |
| 76 for (int i = 0; i < fImageCount; ++i) { | |
| 77 fImageRefs[i] = SkRef(imgs[i]); | |
| 78 } | |
| 79 } | |
| 71 } | 80 } |
| 72 | 81 |
| 73 void SkPictureData::init() { | 82 void SkPictureData::init() { |
| 74 fPictureRefs = NULL; | 83 fPictureRefs = NULL; |
| 75 fPictureCount = 0; | 84 fPictureCount = 0; |
| 76 fTextBlobRefs = NULL; | 85 fTextBlobRefs = NULL; |
| 77 fTextBlobCount = 0; | 86 fTextBlobCount = 0; |
| 87 fImageRefs = NULL; | |
| 88 fImageCount = 0; | |
| 78 fOpData = NULL; | 89 fOpData = NULL; |
| 79 fFactoryPlayback = NULL; | 90 fFactoryPlayback = NULL; |
| 80 } | 91 } |
| 81 | 92 |
| 82 SkPictureData::~SkPictureData() { | 93 SkPictureData::~SkPictureData() { |
| 83 SkSafeUnref(fOpData); | 94 SkSafeUnref(fOpData); |
| 84 | 95 |
| 85 for (int i = 0; i < fPictureCount; i++) { | 96 for (int i = 0; i < fPictureCount; i++) { |
| 86 fPictureRefs[i]->unref(); | 97 fPictureRefs[i]->unref(); |
| 87 } | 98 } |
| 88 SkDELETE_ARRAY(fPictureRefs); | 99 SkDELETE_ARRAY(fPictureRefs); |
| 89 | 100 |
| 90 for (int i = 0; i < fTextBlobCount; i++) { | 101 for (int i = 0; i < fTextBlobCount; i++) { |
| 91 fTextBlobRefs[i]->unref(); | 102 fTextBlobRefs[i]->unref(); |
| 92 } | 103 } |
| 93 SkDELETE_ARRAY(fTextBlobRefs); | 104 SkDELETE_ARRAY(fTextBlobRefs); |
| 94 | 105 |
| 106 for (int i = 0; i < fImageCount; i++) { | |
| 107 fImageRefs[i]->unref(); | |
| 108 } | |
| 109 SkDELETE_ARRAY(fImageRefs); | |
| 110 | |
| 95 SkDELETE(fFactoryPlayback); | 111 SkDELETE(fFactoryPlayback); |
| 96 } | 112 } |
| 97 | 113 |
| 98 bool SkPictureData::containsBitmaps() const { | 114 bool SkPictureData::containsBitmaps() const { |
| 99 if (fBitmaps.count() > 0) { | 115 if (fBitmaps.count() > 0 || fImageCount > 0) { |
| 100 return true; | 116 return true; |
| 101 } | 117 } |
| 102 for (int i = 0; i < fPictureCount; ++i) { | 118 for (int i = 0; i < fPictureCount; ++i) { |
| 103 if (fPictureRefs[i]->willPlayBackBitmaps()) { | 119 if (fPictureRefs[i]->willPlayBackBitmaps()) { |
| 104 return true; | 120 return true; |
| 105 } | 121 } |
| 106 } | 122 } |
| 107 return false; | 123 return false; |
| 108 } | 124 } |
| 109 | 125 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 buffer.writePath(fPaths[i]); | 226 buffer.writePath(fPaths[i]); |
| 211 } | 227 } |
| 212 } | 228 } |
| 213 | 229 |
| 214 if (fTextBlobCount > 0) { | 230 if (fTextBlobCount > 0) { |
| 215 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount); | 231 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount); |
| 216 for (i = 0; i < fTextBlobCount; ++i) { | 232 for (i = 0; i < fTextBlobCount; ++i) { |
| 217 fTextBlobRefs[i]->flatten(buffer); | 233 fTextBlobRefs[i]->flatten(buffer); |
| 218 } | 234 } |
| 219 } | 235 } |
| 236 | |
| 237 if (fImageCount > 0) { | |
| 238 write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount); | |
| 239 for (i = 0; i < fImageCount; ++i) { | |
| 240 buffer.writeImage(fImageRefs[i]); | |
| 241 } | |
| 242 } | |
| 220 } | 243 } |
| 221 | 244 |
| 222 void SkPictureData::serialize(SkWStream* stream, | 245 void SkPictureData::serialize(SkWStream* stream, |
| 223 SkPixelSerializer* pixelSerializer) const { | 246 SkPixelSerializer* pixelSerializer) const { |
| 224 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); | 247 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); |
| 225 stream->write(fOpData->bytes(), fOpData->size()); | 248 stream->write(fOpData->bytes(), fOpData->size()); |
| 226 | 249 |
| 227 if (fPictureCount > 0) { | 250 if (fPictureCount > 0) { |
| 228 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); | 251 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); |
| 229 for (int i = 0; i < fPictureCount; i++) { | 252 for (int i = 0; i < fPictureCount; i++) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 } | 419 } |
| 397 if (!buffer.isValid()) { | 420 if (!buffer.isValid()) { |
| 398 return false; | 421 return false; |
| 399 } | 422 } |
| 400 SkDEBUGCODE(haveBuffer = true;) | 423 SkDEBUGCODE(haveBuffer = true;) |
| 401 } break; | 424 } break; |
| 402 } | 425 } |
| 403 return true; // success | 426 return true; // success |
| 404 } | 427 } |
| 405 | 428 |
| 406 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, | 429 static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) { |
| 407 uint32_t tag, uint32_t size) { | 430 int width = buffer.read32(); |
| 431 int height = buffer.read32(); | |
| 432 if (width < 0 || height < 0) { | |
|
scroggo
2015/06/22 17:40:01
I thought images had to have non-zero dimensions?
reed1
2015/06/22 18:41:50
Done.
| |
| 433 buffer.validate(false); | |
| 434 return NULL; | |
| 435 } | |
| 436 | |
| 437 SkAutoTUnref<SkData> encoded(buffer.readByteArrayAsData()); | |
| 438 int originX = buffer.read32(); | |
| 439 int originY = buffer.read32(); | |
| 440 if (!encoded || originX < 0 || originY < 0) { | |
|
scroggo
2015/06/22 17:40:01
It looks like readByteArrayAsData() always returns
reed1
2015/06/22 18:41:51
Done.
| |
| 441 buffer.validate(false); | |
| 442 return NULL; | |
| 443 } | |
| 444 | |
| 445 const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height); | |
| 446 return SkImage::NewFromEncoded(encoded, &subset); | |
| 447 } | |
| 448 | |
| 449 static const SkPicture* create_picture_from_buffer(SkReadBuffer& buffer) { | |
|
scroggo
2015/06/22 17:40:01
Can we not just use SkPicture::CreateFromBuffer di
reed1
2015/06/22 18:41:51
That is defined to return SkPicture*, but the othe
| |
| 450 return SkPicture::CreateFromBuffer(buffer); | |
| 451 } | |
| 452 | |
| 453 template <typename T> | |
| 454 bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t size, | |
|
scroggo
2015/06/22 17:40:01
I found this signature confusing until I found the
reed1
2015/06/22 18:41:50
Done.
| |
| 455 const T**& array, int& count, const T* (*factory)(SkR eadBuffer&)) { | |
|
scroggo
2015/06/22 17:40:01
nit: Don't we typically use pointers for variables
reed1
2015/06/22 18:41:51
Done.
| |
| 456 if (!buffer.validate((0 == count) && (NULL == array))) { | |
| 457 return false; | |
| 458 } | |
| 459 count = size; | |
| 460 array = SkNEW_ARRAY(const T*, count); | |
|
scroggo
2015/06/22 17:40:01
If size is 0, we dutifully create a 0 size array.
reed1
2015/06/22 18:41:50
Done.
| |
| 461 bool success = true; | |
| 462 int i = 0; | |
| 463 for (; i < count; i++) { | |
| 464 array[i] = factory(buffer); | |
| 465 if (NULL == array[i]) { | |
| 466 success = false; | |
| 467 break; | |
| 468 } | |
| 469 } | |
| 470 if (!success) { | |
| 471 // Delete all of the blobs that were already created (up to but excludin g i): | |
| 472 for (int j = 0; j < i; j++) { | |
| 473 array[j]->unref(); | |
| 474 } | |
| 475 // Delete the array | |
| 476 SkDELETE_ARRAY(array); | |
| 477 array = NULL; | |
| 478 count = 0; | |
| 479 return false; | |
|
scroggo
2015/06/22 17:40:01
Should we validate(false) the buffer? Or do we ass
reed1
2015/06/22 18:41:51
I think we assume the factories did it, if somethi
| |
| 480 } | |
| 481 return true; | |
| 482 } | |
| 483 | |
| 484 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) { | |
| 408 switch (tag) { | 485 switch (tag) { |
| 409 case SK_PICT_BITMAP_BUFFER_TAG: { | 486 case SK_PICT_BITMAP_BUFFER_TAG: { |
| 410 const int count = SkToInt(size); | 487 const int count = SkToInt(size); |
| 411 fBitmaps.reset(count); | 488 fBitmaps.reset(count); |
| 412 for (int i = 0; i < count; ++i) { | 489 for (int i = 0; i < count; ++i) { |
| 413 SkBitmap* bm = &fBitmaps[i]; | 490 SkBitmap* bm = &fBitmaps[i]; |
| 414 if (buffer.readBitmap(bm)) { | 491 if (buffer.readBitmap(bm)) { |
| 415 bm->setImmutable(); | 492 bm->setImmutable(); |
| 416 } else { | 493 } else { |
| 417 return false; | 494 return false; |
| 418 } | 495 } |
| 419 } | 496 } |
| 420 } break; | 497 } break; |
| 421 case SK_PICT_PAINT_BUFFER_TAG: { | 498 case SK_PICT_PAINT_BUFFER_TAG: { |
| 422 const int count = SkToInt(size); | 499 const int count = SkToInt(size); |
| 423 fPaints.reset(count); | 500 fPaints.reset(count); |
| 424 for (int i = 0; i < count; ++i) { | 501 for (int i = 0; i < count; ++i) { |
| 425 buffer.readPaint(&fPaints[i]); | 502 buffer.readPaint(&fPaints[i]); |
| 426 } | 503 } |
| 427 } break; | 504 } break; |
| 428 case SK_PICT_PATH_BUFFER_TAG: | 505 case SK_PICT_PATH_BUFFER_TAG: |
| 429 if (size > 0) { | 506 if (size > 0) { |
| 430 const int count = buffer.readInt(); | 507 const int count = buffer.readInt(); |
| 431 fPaths.reset(count); | 508 fPaths.reset(count); |
| 432 for (int i = 0; i < count; i++) { | 509 for (int i = 0; i < count; i++) { |
| 433 buffer.readPath(&fPaths[i]); | 510 buffer.readPath(&fPaths[i]); |
| 434 } | 511 } |
| 435 } break; | 512 } break; |
| 436 case SK_PICT_TEXTBLOB_BUFFER_TAG: { | 513 case SK_PICT_TEXTBLOB_BUFFER_TAG: |
| 437 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs ))) { | 514 if (!new_array_from_buffer(buffer, size, fTextBlobRefs, fTextBlobCou nt, |
| 515 SkTextBlob::CreateFromBuffer)) { | |
| 438 return false; | 516 return false; |
| 439 } | 517 } |
| 440 fTextBlobCount = size; | 518 break; |
| 441 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); | 519 case SK_PICT_IMAGE_BUFFER_TAG: |
| 442 bool success = true; | 520 if (!new_array_from_buffer(buffer, size, fImageRefs, fImageCount, |
| 443 int i = 0; | 521 create_image_from_buffer)) { |
| 444 for ( ; i < fTextBlobCount; i++) { | |
| 445 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer); | |
| 446 if (NULL == fTextBlobRefs[i]) { | |
| 447 success = false; | |
| 448 break; | |
| 449 } | |
| 450 } | |
| 451 if (!success) { | |
| 452 // Delete all of the blobs that were already created (up to but excluding i): | |
| 453 for (int j = 0; j < i; j++) { | |
| 454 fTextBlobRefs[j]->unref(); | |
| 455 } | |
| 456 // Delete the array | |
| 457 SkDELETE_ARRAY(fTextBlobRefs); | |
| 458 fTextBlobRefs = NULL; | |
| 459 fTextBlobCount = 0; | |
| 460 return false; | 522 return false; |
| 461 } | 523 } |
| 462 } break; | 524 break; |
| 463 case SK_PICT_READER_TAG: { | 525 case SK_PICT_READER_TAG: { |
| 464 SkAutoDataUnref data(SkData::NewUninitialized(size)); | 526 SkAutoDataUnref data(SkData::NewUninitialized(size)); |
| 465 if (!buffer.readByteArray(data->writable_data(), size) || | 527 if (!buffer.readByteArray(data->writable_data(), size) || |
| 466 !buffer.validate(NULL == fOpData)) { | 528 !buffer.validate(NULL == fOpData)) { |
| 467 return false; | 529 return false; |
| 468 } | 530 } |
| 469 SkASSERT(NULL == fOpData); | 531 SkASSERT(NULL == fOpData); |
| 470 fOpData = data.detach(); | 532 fOpData = data.detach(); |
| 471 } break; | 533 } break; |
| 472 case SK_PICT_PICTURE_TAG: { | 534 case SK_PICT_PICTURE_TAG: |
| 473 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs)) ) { | 535 if (!new_array_from_buffer(buffer, size, fPictureRefs, fPictureCount , |
| 536 create_picture_from_buffer)) { | |
| 474 return false; | 537 return false; |
| 475 } | 538 } |
| 476 fPictureCount = size; | |
| 477 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); | |
| 478 bool success = true; | |
| 479 int i = 0; | |
| 480 for ( ; i < fPictureCount; i++) { | |
| 481 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer); | |
| 482 if (NULL == fPictureRefs[i]) { | |
| 483 success = false; | |
| 484 break; | |
| 485 } | |
| 486 } | |
| 487 if (!success) { | |
| 488 // Delete all of the pictures that were already created (up to b ut excluding i): | |
| 489 for (int j = 0; j < i; j++) { | |
| 490 fPictureRefs[j]->unref(); | |
| 491 } | |
| 492 // Delete the array | |
| 493 SkDELETE_ARRAY(fPictureRefs); | |
| 494 fPictureCount = 0; | |
| 495 return false; | |
| 496 } | |
| 497 } break; | |
| 498 default: | 539 default: |
| 499 // The tag was invalid. | 540 // The tag was invalid. |
| 500 return false; | 541 return false; |
| 501 } | 542 } |
| 502 return true; // success | 543 return true; // success |
| 503 } | 544 } |
| 504 | 545 |
| 505 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream, | 546 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream, |
| 506 const SkPictInfo& info, | 547 const SkPictInfo& info, |
| 507 SkPicture::InstallPixelRefProc pr oc) { | 548 SkPicture::InstallPixelRefProc pr oc) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 } | 616 } |
| 576 } | 617 } |
| 577 | 618 |
| 578 bool SkPictureData::suitableForLayerOptimization() const { | 619 bool SkPictureData::suitableForLayerOptimization() const { |
| 579 return fContentInfo.numLayers() > 0; | 620 return fContentInfo.numLayers() > 0; |
| 580 } | 621 } |
| 581 #endif | 622 #endif |
| 582 /////////////////////////////////////////////////////////////////////////////// | 623 /////////////////////////////////////////////////////////////////////////////// |
| 583 | 624 |
| 584 | 625 |
| OLD | NEW |