| Index: src/core/SkPictureData.cpp
|
| diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
|
| index 4f3ac37066f9197c362d9b0f7b6ac533306d070e..6ae03a3f2ea8e81bb74a37b461237eec5524ad95 100644
|
| --- a/src/core/SkPictureData.cpp
|
| +++ b/src/core/SkPictureData.cpp
|
| @@ -68,7 +68,7 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
|
| fTextBlobRefs[i] = SkRef(blobs[i]);
|
| }
|
| }
|
| -
|
| +
|
| const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
|
| fImageCount = imgs.count();
|
| if (fImageCount > 0) {
|
| @@ -102,12 +102,12 @@ SkPictureData::~SkPictureData() {
|
| fTextBlobRefs[i]->unref();
|
| }
|
| SkDELETE_ARRAY(fTextBlobRefs);
|
| -
|
| +
|
| for (int i = 0; i < fImageCount; i++) {
|
| fImageRefs[i]->unref();
|
| }
|
| SkDELETE_ARRAY(fImageRefs);
|
| -
|
| +
|
| SkDELETE(fFactoryPlayback);
|
| }
|
|
|
| @@ -233,7 +233,7 @@ 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) {
|
| @@ -243,38 +243,54 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
|
| }
|
|
|
| void SkPictureData::serialize(SkWStream* stream,
|
| - SkPixelSerializer* pixelSerializer) const {
|
| + SkPixelSerializer* pixelSerializer,
|
| + SkRefCntSet* topLevelTypeFaceSet) const {
|
| + // This can happen at pretty much any time, so might as well do it first.
|
| write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
|
| stream->write(fOpData->bytes(), fOpData->size());
|
|
|
| - if (fPictureCount > 0) {
|
| - write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
|
| - for (int i = 0; i < fPictureCount; i++) {
|
| - fPictureRefs[i]->serialize(stream, pixelSerializer);
|
| - }
|
| - }
|
| -
|
| - // Write some of our data into a writebuffer, and then serialize that
|
| - // into our stream
|
| - {
|
| - SkRefCntSet typefaceSet;
|
| - SkFactorySet factSet;
|
| + // We serialize all typefaces into the typeface section of the top-level picture.
|
| + SkRefCntSet localTypefaceSet;
|
| + SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
|
| +
|
| + // We delay serializing the bulk of our data until after we've serialized
|
| + // factories and typefaces by first serializing to an in-memory write buffer.
|
| + SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
|
| + SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
|
| + buffer.setFactoryRecorder(&factSet);
|
| + buffer.setPixelSerializer(pixelSerializer);
|
| + buffer.setTypefaceRecorder(typefaceSet);
|
| + this->flattenToBuffer(buffer);
|
|
|
| - SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
|
| - buffer.setTypefaceRecorder(&typefaceSet);
|
| - buffer.setFactoryRecorder(&factSet);
|
| - buffer.setPixelSerializer(pixelSerializer);
|
| + // Dummy serialize our sub-pictures for the side effect of filling
|
| + // typefaceSet with typefaces from sub-pictures.
|
| + struct DevNull: public SkWStream {
|
| + DevNull() : fBytesWritten(0) {}
|
| + size_t fBytesWritten;
|
| + bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
|
| + size_t bytesWritten() const override { return fBytesWritten; }
|
| + } devnull;
|
| + for (int i = 0; i < fPictureCount; i++) {
|
| + fPictureRefs[i]->serialize(&devnull, pixelSerializer, typefaceSet);
|
| + }
|
|
|
| - this->flattenToBuffer(buffer);
|
| + // We need to write factories before we write the buffer.
|
| + // We need to write typefaces before we write the buffer or any sub-picture.
|
| + WriteFactories(stream, factSet);
|
| + if (typefaceSet == &localTypefaceSet) {
|
| + WriteTypefaces(stream, *typefaceSet);
|
| + }
|
|
|
| - // We have to write these two sets into the stream *before* we write
|
| - // the buffer, since parsing that buffer will require that we already
|
| - // have these sets available to use.
|
| - WriteFactories(stream, factSet);
|
| - WriteTypefaces(stream, typefaceSet);
|
| + // Write the buffer.
|
| + write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
|
| + buffer.writeToStream(stream);
|
|
|
| - write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
|
| - buffer.writeToStream(stream);
|
| + // Write sub-pictures by calling serialize again.
|
| + if (fPictureCount > 0) {
|
| + write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
|
| + for (int i = 0; i < fPictureCount; i++) {
|
| + fPictureRefs[i]->serialize(stream, pixelSerializer, typefaceSet);
|
| + }
|
| }
|
|
|
| stream->write32(SK_PICT_EOF_TAG);
|
| @@ -324,7 +340,8 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
|
| bool SkPictureData::parseStreamTag(SkStream* stream,
|
| uint32_t tag,
|
| uint32_t size,
|
| - SkPicture::InstallPixelRefProc proc) {
|
| + SkPicture::InstallPixelRefProc proc,
|
| + SkTypefacePlayback* topLevelTFPlayback) {
|
| /*
|
| * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
|
| * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
|
| @@ -376,7 +393,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
| fPictureCount = 0;
|
| fPictureRefs = SkNEW_ARRAY(const SkPicture*, size);
|
| for (uint32_t i = 0; i < size; i++) {
|
| - fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
|
| + fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc, topLevelTFPlayback);
|
| if (!fPictureRefs[i]) {
|
| return false;
|
| }
|
| @@ -395,9 +412,16 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
| buffer.setVersion(fInfo.fVersion);
|
|
|
| fFactoryPlayback->setupBuffer(buffer);
|
| - fTFPlayback.setupBuffer(buffer);
|
| buffer.setBitmapDecoder(proc);
|
|
|
| + if (fTFPlayback.count() > 0) {
|
| + // .skp files <= v43 have typefaces serialized with each sub picture.
|
| + fTFPlayback.setupBuffer(buffer);
|
| + } else {
|
| + // Newer .skp files serialize all typefaces with the top picture.
|
| + topLevelTFPlayback->setupBuffer(buffer);
|
| + }
|
| +
|
| while (!buffer.eof() && buffer.isValid()) {
|
| tag = buffer.readUInt();
|
| size = buffer.readUInt();
|
| @@ -539,10 +563,14 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
|
|
|
| SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
|
| const SkPictInfo& info,
|
| - SkPicture::InstallPixelRefProc proc) {
|
| + SkPicture::InstallPixelRefProc proc,
|
| + SkTypefacePlayback* topLevelTFPlayback) {
|
| SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
|
| + if (!topLevelTFPlayback) {
|
| + topLevelTFPlayback = &data->fTFPlayback;
|
| + }
|
|
|
| - if (!data->parseStream(stream, proc)) {
|
| + if (!data->parseStream(stream, proc, topLevelTFPlayback)) {
|
| return NULL;
|
| }
|
| return data.detach();
|
| @@ -560,7 +588,8 @@ SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
|
| }
|
|
|
| bool SkPictureData::parseStream(SkStream* stream,
|
| - SkPicture::InstallPixelRefProc proc) {
|
| + SkPicture::InstallPixelRefProc proc,
|
| + SkTypefacePlayback* topLevelTFPlayback) {
|
| for (;;) {
|
| uint32_t tag = stream->readU32();
|
| if (SK_PICT_EOF_TAG == tag) {
|
| @@ -568,7 +597,7 @@ bool SkPictureData::parseStream(SkStream* stream,
|
| }
|
|
|
| uint32_t size = stream->readU32();
|
| - if (!this->parseStreamTag(stream, tag, size, proc)) {
|
| + if (!this->parseStreamTag(stream, tag, size, proc, topLevelTFPlayback)) {
|
| return false; // we're invalid
|
| }
|
| }
|
|
|