| Index: src/core/SkPictureData.cpp
|
| diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
|
| index ddd074e9a49882d6d762c5063aec8476c1d07c5e..87517e0d3dc3ed8e864e9742cf23991204191330 100644
|
| --- a/src/core/SkPictureData.cpp
|
| +++ b/src/core/SkPictureData.cpp
|
| @@ -68,6 +68,15 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
|
| fTextBlobRefs[i] = SkRef(blobs[i]);
|
| }
|
| }
|
| +
|
| + const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
|
| + fImageCount = imgs.count();
|
| + if (fImageCount > 0) {
|
| + fImageRefs = SkNEW_ARRAY(const SkImage*, fImageCount);
|
| + for (int i = 0; i < fImageCount; ++i) {
|
| + fImageRefs[i] = SkRef(imgs[i]);
|
| + }
|
| + }
|
| }
|
|
|
| void SkPictureData::init() {
|
| @@ -75,6 +84,8 @@ void SkPictureData::init() {
|
| fPictureCount = 0;
|
| fTextBlobRefs = NULL;
|
| fTextBlobCount = 0;
|
| + fImageRefs = NULL;
|
| + fImageCount = 0;
|
| fOpData = NULL;
|
| fFactoryPlayback = NULL;
|
| }
|
| @@ -91,12 +102,17 @@ SkPictureData::~SkPictureData() {
|
| fTextBlobRefs[i]->unref();
|
| }
|
| SkDELETE_ARRAY(fTextBlobRefs);
|
| -
|
| +
|
| + for (int i = 0; i < fImageCount; i++) {
|
| + fImageRefs[i]->unref();
|
| + }
|
| + SkDELETE_ARRAY(fImageRefs);
|
| +
|
| SkDELETE(fFactoryPlayback);
|
| }
|
|
|
| bool SkPictureData::containsBitmaps() const {
|
| - if (fBitmaps.count() > 0) {
|
| + if (fBitmaps.count() > 0 || fImageCount > 0) {
|
| return true;
|
| }
|
| for (int i = 0; i < fPictureCount; ++i) {
|
| @@ -217,6 +233,13 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
|
| fTextBlobRefs[i]->flatten(buffer);
|
| }
|
| }
|
| +
|
| + if (fImageCount > 0) {
|
| + write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
|
| + for (i = 0; i < fImageCount; ++i) {
|
| + buffer.writeImage(fImageRefs[i]);
|
| + }
|
| + }
|
| }
|
|
|
| void SkPictureData::serialize(SkWStream* stream,
|
| @@ -403,8 +426,67 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
| return true; // success
|
| }
|
|
|
| -bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
|
| - uint32_t tag, uint32_t size) {
|
| +static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) {
|
| + int width = buffer.read32();
|
| + int height = buffer.read32();
|
| + if (width <= 0 || height <= 0) { // SkImage never has a zero dimension
|
| + buffer.validate(false);
|
| + return NULL;
|
| + }
|
| +
|
| + SkAutoTUnref<SkData> encoded(buffer.readByteArrayAsData());
|
| + int originX = buffer.read32();
|
| + int originY = buffer.read32();
|
| + if (0 == encoded->size() || originX < 0 || originY < 0) {
|
| + buffer.validate(false);
|
| + return NULL;
|
| + }
|
| +
|
| + const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height);
|
| + return SkImage::NewFromEncoded(encoded, &subset);
|
| +}
|
| +
|
| +// Need a shallow wrapper to return const SkPicture* to match the other factories,
|
| +// as SkPicture::CreateFromBuffer() returns SkPicture*
|
| +static const SkPicture* create_picture_from_buffer(SkReadBuffer& buffer) {
|
| + return SkPicture::CreateFromBuffer(buffer);
|
| +}
|
| +
|
| +template <typename T>
|
| +bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
|
| + const T*** array, int* outCount, const T* (*factory)(SkReadBuffer&)) {
|
| + if (!buffer.validate((0 == *outCount) && (NULL == *array))) {
|
| + return false;
|
| + }
|
| + if (0 == inCount) {
|
| + return true;
|
| + }
|
| + *outCount = inCount;
|
| + *array = SkNEW_ARRAY(const T*, *outCount);
|
| + bool success = true;
|
| + int i = 0;
|
| + for (; i < *outCount; i++) {
|
| + (*array)[i] = factory(buffer);
|
| + if (NULL == (*array)[i]) {
|
| + success = false;
|
| + break;
|
| + }
|
| + }
|
| + if (!success) {
|
| + // Delete all of the blobs that were already created (up to but excluding i):
|
| + for (int j = 0; j < i; j++) {
|
| + (*array)[j]->unref();
|
| + }
|
| + // Delete the array
|
| + SkDELETE_ARRAY(*array);
|
| + *array = NULL;
|
| + *outCount = 0;
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
|
| switch (tag) {
|
| case SK_PICT_BITMAP_BUFFER_TAG: {
|
| const int count = SkToInt(size);
|
| @@ -433,33 +515,18 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
|
| buffer.readPath(&fPaths[i]);
|
| }
|
| } break;
|
| - case SK_PICT_TEXTBLOB_BUFFER_TAG: {
|
| - if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) {
|
| + case SK_PICT_TEXTBLOB_BUFFER_TAG:
|
| + if (!new_array_from_buffer(buffer, size, &fTextBlobRefs, &fTextBlobCount,
|
| + SkTextBlob::CreateFromBuffer)) {
|
| return false;
|
| }
|
| - fTextBlobCount = size;
|
| - fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
|
| - bool success = true;
|
| - int i = 0;
|
| - for ( ; i < fTextBlobCount; i++) {
|
| - fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer);
|
| - if (NULL == fTextBlobRefs[i]) {
|
| - success = false;
|
| - break;
|
| - }
|
| - }
|
| - if (!success) {
|
| - // Delete all of the blobs that were already created (up to but excluding i):
|
| - for (int j = 0; j < i; j++) {
|
| - fTextBlobRefs[j]->unref();
|
| - }
|
| - // Delete the array
|
| - SkDELETE_ARRAY(fTextBlobRefs);
|
| - fTextBlobRefs = NULL;
|
| - fTextBlobCount = 0;
|
| + break;
|
| + case SK_PICT_IMAGE_BUFFER_TAG:
|
| + if (!new_array_from_buffer(buffer, size, &fImageRefs, &fImageCount,
|
| + create_image_from_buffer)) {
|
| return false;
|
| }
|
| - } break;
|
| + break;
|
| case SK_PICT_READER_TAG: {
|
| SkAutoDataUnref data(SkData::NewUninitialized(size));
|
| if (!buffer.readByteArray(data->writable_data(), size) ||
|
| @@ -469,32 +536,11 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
|
| SkASSERT(NULL == fOpData);
|
| fOpData = data.detach();
|
| } break;
|
| - case SK_PICT_PICTURE_TAG: {
|
| - if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
|
| + case SK_PICT_PICTURE_TAG:
|
| + if (!new_array_from_buffer(buffer, size, &fPictureRefs, &fPictureCount,
|
| + create_picture_from_buffer)) {
|
| return false;
|
| }
|
| - fPictureCount = size;
|
| - fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
|
| - bool success = true;
|
| - int i = 0;
|
| - for ( ; i < fPictureCount; i++) {
|
| - fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
|
| - if (NULL == fPictureRefs[i]) {
|
| - success = false;
|
| - break;
|
| - }
|
| - }
|
| - if (!success) {
|
| - // Delete all of the pictures that were already created (up to but excluding i):
|
| - for (int j = 0; j < i; j++) {
|
| - fPictureRefs[j]->unref();
|
| - }
|
| - // Delete the array
|
| - SkDELETE_ARRAY(fPictureRefs);
|
| - fPictureCount = 0;
|
| - return false;
|
| - }
|
| - } break;
|
| default:
|
| // The tag was invalid.
|
| return false;
|
|
|