Scrub SkPictureData/SkPictureRecord
- replace manual ref fiddling with smart types - remove unused SkPictureData::fBitmapImageRefs - remove the preallocation in new_array_from_buffer (to prevent fuzzer OOMs) Bug: skia:7937 Change-Id: I50f49fa8e594a138ea09c22f7bf73cf57ec006ff Reviewed-on: https://skia-review.googlesource.com/128309 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org> Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
parent
724afe8b2d
commit
8fd15d8c7e
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "SkAutoMalloc.h"
|
#include "SkAutoMalloc.h"
|
||||||
#include "SkImageGenerator.h"
|
#include "SkImageGenerator.h"
|
||||||
|
#include "SkMakeUnique.h"
|
||||||
#include "SkPictureData.h"
|
#include "SkPictureData.h"
|
||||||
#include "SkPictureRecord.h"
|
#include "SkPictureRecord.h"
|
||||||
#include "SkReadBuffer.h"
|
#include "SkReadBuffer.h"
|
||||||
@ -25,9 +26,7 @@ template <typename T> int SafeCount(const T* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkPictureData::SkPictureData(const SkPictInfo& info)
|
SkPictureData::SkPictureData(const SkPictInfo& info)
|
||||||
: fInfo(info) {
|
: fInfo(info) {}
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPictureData::initForPlayback() const {
|
void SkPictureData::initForPlayback() const {
|
||||||
// ensure that the paths bounds are pre-computed
|
// ensure that the paths bounds are pre-computed
|
||||||
@ -38,9 +37,12 @@ void SkPictureData::initForPlayback() const {
|
|||||||
|
|
||||||
SkPictureData::SkPictureData(const SkPictureRecord& record,
|
SkPictureData::SkPictureData(const SkPictureRecord& record,
|
||||||
const SkPictInfo& info)
|
const SkPictInfo& info)
|
||||||
: fInfo(info) {
|
: fPictures(record.getPictures())
|
||||||
|
, fDrawables(record.getDrawables())
|
||||||
this->init();
|
, fTextBlobs(record.getTextBlobs())
|
||||||
|
, fVertices(record.getVertices())
|
||||||
|
, fImages(record.getImages())
|
||||||
|
, fInfo(info) {
|
||||||
|
|
||||||
fOpData = record.opData();
|
fOpData = record.opData();
|
||||||
|
|
||||||
@ -54,102 +56,6 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
|
|||||||
});
|
});
|
||||||
|
|
||||||
this->initForPlayback();
|
this->initForPlayback();
|
||||||
|
|
||||||
const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
|
|
||||||
fPictureCount = pictures.count();
|
|
||||||
if (fPictureCount > 0) {
|
|
||||||
fPictureRefs = new const SkPicture* [fPictureCount];
|
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
|
||||||
fPictureRefs[i] = pictures[i];
|
|
||||||
fPictureRefs[i]->ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SkTDArray<SkDrawable* >& drawables = record.getDrawableRefs();
|
|
||||||
fDrawableCount = drawables.count();
|
|
||||||
if (fDrawableCount > 0) {
|
|
||||||
fDrawableRefs = new SkDrawable* [fDrawableCount];
|
|
||||||
for (int i = 0; i < fDrawableCount; i++) {
|
|
||||||
fDrawableRefs[i] = drawables[i];
|
|
||||||
fDrawableRefs[i]->ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// templatize to consolidate with similar picture logic?
|
|
||||||
const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
|
|
||||||
fTextBlobCount = blobs.count();
|
|
||||||
if (fTextBlobCount > 0) {
|
|
||||||
fTextBlobRefs = new const SkTextBlob* [fTextBlobCount];
|
|
||||||
for (int i = 0; i < fTextBlobCount; ++i) {
|
|
||||||
fTextBlobRefs[i] = SkRef(blobs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SkTDArray<const SkVertices*>& verts = record.getVerticesRefs();
|
|
||||||
fVerticesCount = verts.count();
|
|
||||||
if (fVerticesCount > 0) {
|
|
||||||
fVerticesRefs = new const SkVertices* [fVerticesCount];
|
|
||||||
for (int i = 0; i < fVerticesCount; ++i) {
|
|
||||||
fVerticesRefs[i] = SkRef(verts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
|
|
||||||
fImageCount = imgs.count();
|
|
||||||
if (fImageCount > 0) {
|
|
||||||
fImageRefs = new const SkImage* [fImageCount];
|
|
||||||
for (int i = 0; i < fImageCount; ++i) {
|
|
||||||
fImageRefs[i] = SkRef(imgs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPictureData::init() {
|
|
||||||
fPictureRefs = nullptr;
|
|
||||||
fPictureCount = 0;
|
|
||||||
fDrawableRefs = nullptr;
|
|
||||||
fDrawableCount = 0;
|
|
||||||
fTextBlobRefs = nullptr;
|
|
||||||
fTextBlobCount = 0;
|
|
||||||
fVerticesRefs = nullptr;
|
|
||||||
fVerticesCount = 0;
|
|
||||||
fImageRefs = nullptr;
|
|
||||||
fImageCount = 0;
|
|
||||||
fBitmapImageCount = 0;
|
|
||||||
fBitmapImageRefs = nullptr;
|
|
||||||
fFactoryPlayback = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkPictureData::~SkPictureData() {
|
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
|
||||||
fPictureRefs[i]->unref();
|
|
||||||
}
|
|
||||||
delete[] fPictureRefs;
|
|
||||||
|
|
||||||
for (int i = 0; i < fDrawableCount; i++) {
|
|
||||||
fDrawableRefs[i]->unref();
|
|
||||||
}
|
|
||||||
if (fDrawableCount > 0) {
|
|
||||||
SkASSERT(fDrawableRefs);
|
|
||||||
delete[] fDrawableRefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < fTextBlobCount; i++) {
|
|
||||||
fTextBlobRefs[i]->unref();
|
|
||||||
}
|
|
||||||
delete[] fTextBlobRefs;
|
|
||||||
|
|
||||||
for (int i = 0; i < fVerticesCount; i++) {
|
|
||||||
fVerticesRefs[i]->unref();
|
|
||||||
}
|
|
||||||
delete[] fVerticesRefs;
|
|
||||||
|
|
||||||
for (int i = 0; i < fImageCount; i++) {
|
|
||||||
fImageRefs[i]->unref();
|
|
||||||
}
|
|
||||||
delete[] fImageRefs;
|
|
||||||
|
|
||||||
delete fFactoryPlayback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -244,24 +150,24 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fTextBlobCount > 0) {
|
if (!fTextBlobs.empty()) {
|
||||||
write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
|
write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobs.count());
|
||||||
for (i = 0; i < fTextBlobCount; ++i) {
|
for (const auto& blob : fTextBlobs) {
|
||||||
fTextBlobRefs[i]->flatten(buffer);
|
blob->flatten(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fVerticesCount > 0) {
|
if (!fVertices.empty()) {
|
||||||
write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVerticesCount);
|
write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVertices.count());
|
||||||
for (i = 0; i < fVerticesCount; ++i) {
|
for (const auto& vert : fVertices) {
|
||||||
buffer.writeDataAsByteArray(fVerticesRefs[i]->encode().get());
|
buffer.writeDataAsByteArray(vert->encode().get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fImageCount > 0) {
|
if (!fImages.empty()) {
|
||||||
write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
|
write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImages.count());
|
||||||
for (i = 0; i < fImageCount; ++i) {
|
for (const auto& img : fImages) {
|
||||||
buffer.writeImage(fImageRefs[i]);
|
buffer.writeImage(img.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,8 +199,8 @@ void SkPictureData::serialize(SkWStream* stream, const SkSerialProcs& procs,
|
|||||||
bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
|
bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
|
||||||
size_t bytesWritten() const override { return fBytesWritten; }
|
size_t bytesWritten() const override { return fBytesWritten; }
|
||||||
} devnull;
|
} devnull;
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
for (const auto& pic : fPictures) {
|
||||||
fPictureRefs[i]->serialize(&devnull, nullptr, typefaceSet);
|
pic->serialize(&devnull, nullptr, typefaceSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to write factories before we write the buffer.
|
// We need to write factories before we write the buffer.
|
||||||
@ -309,10 +215,10 @@ void SkPictureData::serialize(SkWStream* stream, const SkSerialProcs& procs,
|
|||||||
buffer.writeToStream(stream);
|
buffer.writeToStream(stream);
|
||||||
|
|
||||||
// Write sub-pictures by calling serialize again.
|
// Write sub-pictures by calling serialize again.
|
||||||
if (fPictureCount > 0) {
|
if (!fPictures.empty()) {
|
||||||
write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
|
write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictures.count());
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
for (const auto& pic : fPictures) {
|
||||||
fPictureRefs[i]->serialize(stream, &procs, typefaceSet);
|
pic->serialize(stream, &procs, typefaceSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,17 +229,17 @@ void SkPictureData::flatten(SkWriteBuffer& buffer) const {
|
|||||||
write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
|
write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
|
||||||
buffer.writeByteArray(fOpData->bytes(), fOpData->size());
|
buffer.writeByteArray(fOpData->bytes(), fOpData->size());
|
||||||
|
|
||||||
if (fPictureCount > 0) {
|
if (!fPictures.empty()) {
|
||||||
write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
|
write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictures.count());
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
for (const auto& pic : fPictures) {
|
||||||
fPictureRefs[i]->flatten(buffer);
|
pic->flatten(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fDrawableCount > 0) {
|
if (!fDrawables.empty()) {
|
||||||
write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawableCount);
|
write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawables.count());
|
||||||
for (int i = 0; i < fDrawableCount; i++) {
|
for (const auto& draw : fDrawables) {
|
||||||
buffer.writeFlattenable(fDrawableRefs[i]);
|
buffer.writeFlattenable(draw.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +277,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
|||||||
case SK_PICT_FACTORY_TAG: {
|
case SK_PICT_FACTORY_TAG: {
|
||||||
SkASSERT(!haveBuffer);
|
SkASSERT(!haveBuffer);
|
||||||
size = stream->readU32();
|
size = stream->readU32();
|
||||||
fFactoryPlayback = new SkFactoryPlayback(size);
|
fFactoryPlayback = skstd::make_unique<SkFactoryPlayback>(size);
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
SkString str;
|
SkString str;
|
||||||
const size_t len = stream->readPackedUInt();
|
const size_t len = stream->readPackedUInt();
|
||||||
@ -397,14 +303,15 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case SK_PICT_PICTURE_TAG: {
|
case SK_PICT_PICTURE_TAG: {
|
||||||
fPictureCount = 0;
|
SkASSERT(fPictures.empty());
|
||||||
fPictureRefs = new const SkPicture* [size];
|
fPictures.reserve(SkToInt(size));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
fPictureRefs[i] = SkPicture::MakeFromStream(stream, &procs, topLevelTFPlayback).release();
|
auto pic = SkPicture::MakeFromStream(stream, &procs, topLevelTFPlayback);
|
||||||
if (!fPictureRefs[i]) {
|
if (!pic) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fPictureCount++;
|
fPictures.push_back(std::move(pic));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case SK_PICT_BUFFER_SIZE_TAG: {
|
case SK_PICT_BUFFER_SIZE_TAG: {
|
||||||
@ -456,41 +363,28 @@ static sk_sp<SkDrawable> create_drawable_from_buffer(SkReadBuffer& buffer) {
|
|||||||
return sk_sp<SkDrawable>((SkDrawable*)buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
|
return sk_sp<SkDrawable>((SkDrawable*)buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
// We need two types 'cause SkDrawable is const-variant.
|
||||||
|
template <typename T, typename U>
|
||||||
bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
|
bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
|
||||||
const T*** array, int* outCount, sk_sp<T> (*factory)(SkReadBuffer&)) {
|
SkTArray<sk_sp<T>>& array, sk_sp<U> (*factory)(SkReadBuffer&)) {
|
||||||
if (!buffer.validate((0 == *outCount) && (nullptr == *array))) {
|
if (!buffer.validate(array.empty() && SkTFitsIn<int>(inCount))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (0 == inCount) {
|
if (0 == inCount) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!buffer.validate(SkTFitsIn<int>(inCount))) {
|
|
||||||
return false;
|
for (uint32_t i = 0; i < inCount; ++i) {
|
||||||
|
auto obj = factory(buffer);
|
||||||
|
|
||||||
|
if (!buffer.validate(obj)) {
|
||||||
|
array.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
array.push_back(std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
*outCount = inCount;
|
|
||||||
*array = new const T* [*outCount];
|
|
||||||
bool success = true;
|
|
||||||
int i = 0;
|
|
||||||
for (; i < *outCount; i++) {
|
|
||||||
(*array)[i] = factory(buffer).release();
|
|
||||||
if (nullptr == (*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
|
|
||||||
delete[] * array;
|
|
||||||
*array = nullptr;
|
|
||||||
*outCount = 0;
|
|
||||||
return buffer.validate(false);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,16 +414,13 @@ void SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case SK_PICT_TEXTBLOB_BUFFER_TAG:
|
case SK_PICT_TEXTBLOB_BUFFER_TAG:
|
||||||
new_array_from_buffer(buffer, size, &fTextBlobRefs, &fTextBlobCount,
|
new_array_from_buffer(buffer, size, fTextBlobs, SkTextBlob::MakeFromBuffer);
|
||||||
SkTextBlob::MakeFromBuffer);
|
|
||||||
break;
|
break;
|
||||||
case SK_PICT_VERTICES_BUFFER_TAG:
|
case SK_PICT_VERTICES_BUFFER_TAG:
|
||||||
new_array_from_buffer(buffer, size, &fVerticesRefs, &fVerticesCount,
|
new_array_from_buffer(buffer, size, fVertices, create_vertices_from_buffer);
|
||||||
create_vertices_from_buffer);
|
|
||||||
break;
|
break;
|
||||||
case SK_PICT_IMAGE_BUFFER_TAG:
|
case SK_PICT_IMAGE_BUFFER_TAG:
|
||||||
new_array_from_buffer(buffer, size, &fImageRefs, &fImageCount,
|
new_array_from_buffer(buffer, size, fImages, create_image_from_buffer);
|
||||||
create_image_from_buffer);
|
|
||||||
break;
|
break;
|
||||||
case SK_PICT_READER_TAG: {
|
case SK_PICT_READER_TAG: {
|
||||||
auto data(SkData::MakeUninitialized(size));
|
auto data(SkData::MakeUninitialized(size));
|
||||||
@ -541,12 +432,10 @@ void SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
|
|||||||
fOpData = std::move(data);
|
fOpData = std::move(data);
|
||||||
} break;
|
} break;
|
||||||
case SK_PICT_PICTURE_TAG:
|
case SK_PICT_PICTURE_TAG:
|
||||||
new_array_from_buffer(buffer, size, &fPictureRefs, &fPictureCount,
|
new_array_from_buffer(buffer, size, fPictures, SkPicture::MakeFromBuffer);
|
||||||
SkPicture::MakeFromBuffer);
|
|
||||||
break;
|
break;
|
||||||
case SK_PICT_DRAWABLE_TAG:
|
case SK_PICT_DRAWABLE_TAG:
|
||||||
new_array_from_buffer(buffer, size, (const SkDrawable***)&fDrawableRefs,
|
new_array_from_buffer(buffer, size, fDrawables, create_drawable_from_buffer);
|
||||||
&fDrawableCount, create_drawable_from_buffer);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffer.validate(false); // The tag was invalid.
|
buffer.validate(false); // The tag was invalid.
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#include "SkDrawable.h"
|
#include "SkDrawable.h"
|
||||||
#include "SkPicture.h"
|
#include "SkPicture.h"
|
||||||
#include "SkPictureFlat.h"
|
#include "SkPictureFlat.h"
|
||||||
|
#include "SkTArray.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class SkData;
|
class SkData;
|
||||||
class SkPictureRecord;
|
class SkPictureRecord;
|
||||||
@ -65,9 +68,10 @@ public:
|
|||||||
// Always write this guy last (with no length field afterwards)
|
// Always write this guy last (with no length field afterwards)
|
||||||
#define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
|
#define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
|
||||||
|
|
||||||
template <typename T> T* read_index_base_1_or_null(SkReadBuffer* reader, int count, T* array[]) {
|
template <typename T>
|
||||||
|
T* read_index_base_1_or_null(SkReadBuffer* reader, const SkTArray<sk_sp<T>>& array) {
|
||||||
int index = reader->readInt();
|
int index = reader->readInt();
|
||||||
return reader->validate(index > 0 && index <= count) ? array[index - 1] : nullptr;
|
return reader->validate(index > 0 && index <= array.count()) ? array[index - 1].get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SkPictureData {
|
class SkPictureData {
|
||||||
@ -80,8 +84,6 @@ public:
|
|||||||
SkTypefacePlayback*);
|
SkTypefacePlayback*);
|
||||||
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
|
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
|
||||||
|
|
||||||
virtual ~SkPictureData();
|
|
||||||
|
|
||||||
void serialize(SkWStream*, const SkSerialProcs&, SkRefCntSet*) const;
|
void serialize(SkWStream*, const SkSerialProcs&, SkRefCntSet*) const;
|
||||||
void flatten(SkWriteBuffer&) const;
|
void flatten(SkWriteBuffer&) const;
|
||||||
|
|
||||||
@ -98,7 +100,7 @@ public:
|
|||||||
const SkImage* getImage(SkReadBuffer* reader) const {
|
const SkImage* getImage(SkReadBuffer* reader) const {
|
||||||
// images are written base-0, unlike paths, pictures, drawables, etc.
|
// images are written base-0, unlike paths, pictures, drawables, etc.
|
||||||
const int index = reader->readInt();
|
const int index = reader->readInt();
|
||||||
return reader->validateIndex(index, fImageCount) ? fImageRefs[index] : nullptr;
|
return reader->validateIndex(index, fImages.count()) ? fImages[index].get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkPath& getPath(SkReadBuffer* reader) const {
|
const SkPath& getPath(SkReadBuffer* reader) const {
|
||||||
@ -108,11 +110,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SkPicture* getPicture(SkReadBuffer* reader) const {
|
const SkPicture* getPicture(SkReadBuffer* reader) const {
|
||||||
return read_index_base_1_or_null(reader, fPictureCount, fPictureRefs);
|
return read_index_base_1_or_null(reader, fPictures);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkDrawable* getDrawable(SkReadBuffer* reader) const {
|
SkDrawable* getDrawable(SkReadBuffer* reader) const {
|
||||||
return read_index_base_1_or_null(reader, fDrawableCount, fDrawableRefs);
|
return read_index_base_1_or_null(reader, fDrawables);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkPaint* getPaint(SkReadBuffer* reader) const {
|
const SkPaint* getPaint(SkReadBuffer* reader) const {
|
||||||
@ -125,16 +127,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SkTextBlob* getTextBlob(SkReadBuffer* reader) const {
|
const SkTextBlob* getTextBlob(SkReadBuffer* reader) const {
|
||||||
return read_index_base_1_or_null(reader, fTextBlobCount, fTextBlobRefs);
|
return read_index_base_1_or_null(reader, fTextBlobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkVertices* getVertices(SkReadBuffer* reader) const {
|
const SkVertices* getVertices(SkReadBuffer* reader) const {
|
||||||
return read_index_base_1_or_null(reader, fVerticesCount, fVerticesRefs);
|
return read_index_base_1_or_null(reader, fVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
|
||||||
|
|
||||||
// these help us with reading/writing
|
// these help us with reading/writing
|
||||||
// Does not affect ownership of SkStream.
|
// Does not affect ownership of SkStream.
|
||||||
bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size,
|
bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size,
|
||||||
@ -150,21 +150,14 @@ private:
|
|||||||
const SkPath fEmptyPath;
|
const SkPath fEmptyPath;
|
||||||
const SkBitmap fEmptyBitmap;
|
const SkBitmap fEmptyBitmap;
|
||||||
|
|
||||||
const SkPicture** fPictureRefs;
|
SkTArray<sk_sp<const SkPicture>> fPictures;
|
||||||
int fPictureCount;
|
SkTArray<sk_sp<SkDrawable>> fDrawables;
|
||||||
SkDrawable** fDrawableRefs;
|
SkTArray<sk_sp<const SkTextBlob>> fTextBlobs;
|
||||||
int fDrawableCount;
|
SkTArray<sk_sp<const SkVertices>> fVertices;
|
||||||
const SkTextBlob** fTextBlobRefs;
|
SkTArray<sk_sp<const SkImage>> fImages;
|
||||||
int fTextBlobCount;
|
|
||||||
const SkVertices** fVerticesRefs;
|
|
||||||
int fVerticesCount;
|
|
||||||
const SkImage** fImageRefs;
|
|
||||||
int fImageCount;
|
|
||||||
const SkImage** fBitmapImageRefs;
|
|
||||||
int fBitmapImageCount;
|
|
||||||
|
|
||||||
SkTypefacePlayback fTFPlayback;
|
SkTypefacePlayback fTFPlayback;
|
||||||
SkFactoryPlayback* fFactoryPlayback;
|
std::unique_ptr<SkFactoryPlayback> fFactoryPlayback;
|
||||||
|
|
||||||
const SkPictInfo fInfo;
|
const SkPictInfo fInfo;
|
||||||
|
|
||||||
|
@ -34,14 +34,6 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
|
|||||||
, fInitialSaveCount(kNoInitialSave) {
|
, fInitialSaveCount(kNoInitialSave) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPictureRecord::~SkPictureRecord() {
|
|
||||||
fImageRefs.unrefAll();
|
|
||||||
fPictureRefs.unrefAll();
|
|
||||||
fDrawableRefs.unrefAll();
|
|
||||||
fTextBlobRefs.unrefAll();
|
|
||||||
fVerticesRefs.unrefAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SkPictureRecord::onFlush() {
|
void SkPictureRecord::onFlush() {
|
||||||
@ -804,15 +796,28 @@ void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkD
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
|
// De-duping helper.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool equals(T* a, T* b) { return a->uniqueID() == b->uniqueID(); }
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool equals(SkDrawable* a, SkDrawable* b) {
|
||||||
|
// SkDrawable's generationID is not a stable unique identifier.
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static int find_or_append(SkTArray<sk_sp<T>>& array, T* obj) {
|
||||||
for (int i = 0; i < array.count(); i++) {
|
for (int i = 0; i < array.count(); i++) {
|
||||||
if (array[i]->uniqueID() == obj->uniqueID()) {
|
if (equals(array[i].get(), obj)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i = array.count();
|
|
||||||
*array.append() = SkRef(obj);
|
array.push_back(sk_ref_sp(obj));
|
||||||
return i;
|
|
||||||
|
return array.count() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
|
sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
|
||||||
@ -821,7 +826,7 @@ sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const Sk
|
|||||||
|
|
||||||
void SkPictureRecord::addImage(const SkImage* image) {
|
void SkPictureRecord::addImage(const SkImage* image) {
|
||||||
// convention for images is 0-based index
|
// convention for images is 0-based index
|
||||||
this->addInt(find_or_append_uniqueID(fImageRefs, image));
|
this->addInt(find_or_append(fImages, image));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
|
void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
|
||||||
@ -856,18 +861,12 @@ void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
|
|||||||
|
|
||||||
void SkPictureRecord::addPicture(const SkPicture* picture) {
|
void SkPictureRecord::addPicture(const SkPicture* picture) {
|
||||||
// follow the convention of recording a 1-based index
|
// follow the convention of recording a 1-based index
|
||||||
this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
|
this->addInt(find_or_append(fPictures, picture) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureRecord::addDrawable(SkDrawable* drawable) {
|
void SkPictureRecord::addDrawable(SkDrawable* drawable) {
|
||||||
int index = fDrawableRefs.find(drawable);
|
|
||||||
if (index < 0) { // not found
|
|
||||||
index = fDrawableRefs.count();
|
|
||||||
*fDrawableRefs.append() = drawable;
|
|
||||||
drawable->ref();
|
|
||||||
}
|
|
||||||
// follow the convention of recording a 1-based index
|
// follow the convention of recording a 1-based index
|
||||||
this->addInt(index + 1);
|
this->addInt(find_or_append(fDrawables, drawable) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureRecord::addPoint(const SkPoint& point) {
|
void SkPictureRecord::addPoint(const SkPoint& point) {
|
||||||
@ -918,12 +917,12 @@ void SkPictureRecord::addText(const void* text, size_t byteLength) {
|
|||||||
|
|
||||||
void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
|
void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
|
||||||
// follow the convention of recording a 1-based index
|
// follow the convention of recording a 1-based index
|
||||||
this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
|
this->addInt(find_or_append(fTextBlobs, blob) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureRecord::addVertices(const SkVertices* vertices) {
|
void SkPictureRecord::addVertices(const SkVertices* vertices) {
|
||||||
// follow the convention of recording a 1-based index
|
// follow the convention of recording a 1-based index
|
||||||
this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
|
this->addInt(find_or_append(fVertices, vertices) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -31,26 +31,25 @@
|
|||||||
class SkPictureRecord : public SkCanvasVirtualEnforcer<SkCanvas> {
|
class SkPictureRecord : public SkCanvasVirtualEnforcer<SkCanvas> {
|
||||||
public:
|
public:
|
||||||
SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
|
SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
|
||||||
~SkPictureRecord() override;
|
|
||||||
|
|
||||||
const SkTDArray<const SkPicture* >& getPictureRefs() const {
|
const SkTArray<sk_sp<const SkPicture>>& getPictures() const {
|
||||||
return fPictureRefs;
|
return fPictures;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkTDArray<SkDrawable* >& getDrawableRefs() const {
|
const SkTArray<sk_sp<SkDrawable>>& getDrawables() const {
|
||||||
return fDrawableRefs;
|
return fDrawables;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkTDArray<const SkTextBlob* >& getTextBlobRefs() const {
|
const SkTArray<sk_sp<const SkTextBlob>>& getTextBlobs() const {
|
||||||
return fTextBlobRefs;
|
return fTextBlobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkTDArray<const SkVertices* >& getVerticesRefs() const {
|
const SkTArray<sk_sp<const SkVertices>>& getVertices() const {
|
||||||
return fVerticesRefs;
|
return fVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkTDArray<const SkImage* >& getImageRefs() const {
|
const SkTArray<sk_sp<const SkImage>>& getImages() const {
|
||||||
return fImageRefs;
|
return fImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkData> opData() const {
|
sk_sp<SkData> opData() const {
|
||||||
@ -251,12 +250,11 @@ private:
|
|||||||
|
|
||||||
SkWriter32 fWriter;
|
SkWriter32 fWriter;
|
||||||
|
|
||||||
// we ref each item in these arrays
|
SkTArray<sk_sp<const SkImage>> fImages;
|
||||||
SkTDArray<const SkImage*> fImageRefs;
|
SkTArray<sk_sp<const SkPicture>> fPictures;
|
||||||
SkTDArray<const SkPicture*> fPictureRefs;
|
SkTArray<sk_sp<SkDrawable>> fDrawables;
|
||||||
SkTDArray<SkDrawable*> fDrawableRefs;
|
SkTArray<sk_sp<const SkTextBlob>> fTextBlobs;
|
||||||
SkTDArray<const SkTextBlob*> fTextBlobRefs;
|
SkTArray<sk_sp<const SkVertices>> fVertices;
|
||||||
SkTDArray<const SkVertices*> fVerticesRefs;
|
|
||||||
|
|
||||||
uint32_t fRecordFlags;
|
uint32_t fRecordFlags;
|
||||||
int fInitialSaveCount;
|
int fInitialSaveCount;
|
||||||
|
Loading…
Reference in New Issue
Block a user