diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkPicture.cpp | 17 | ||||
-rw-r--r-- | src/core/SkPictureData.cpp | 101 | ||||
-rw-r--r-- | src/core/SkPictureData.h | 12 |
3 files changed, 87 insertions, 43 deletions
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 02d495e4c6..26ec76184e 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -139,11 +139,18 @@ SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d } SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) { + return CreateFromStream(stream, proc, nullptr); +} + +SkPicture* SkPicture::CreateFromStream(SkStream* stream, + InstallPixelRefProc proc, + SkTypefacePlayback* typefaces) { SkPictInfo info; if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) { return nullptr; } - SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, info, proc)); + SkAutoTDelete<SkPictureData> data( + SkPictureData::CreateFromStream(stream, info, proc, typefaces)); return Forwardport(info, data); } @@ -166,13 +173,19 @@ SkPictureData* SkPicture::backport() const { } void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const { + this->serialize(stream, pixelSerializer, nullptr); +} + +void SkPicture::serialize(SkWStream* stream, + SkPixelSerializer* pixelSerializer, + SkRefCntSet* typefaceSet) const { SkPictInfo info = this->createHeader(); SkAutoTDelete<SkPictureData> data(this->backport()); stream->write(&info, sizeof(info)); if (data) { stream->writeBool(true); - data->serialize(stream, pixelSerializer); + data->serialize(stream, pixelSerializer, typefaceSet); } else { stream->writeBool(false); } diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp index 4f3ac37066..6ae03a3f2e 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 } } diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h index 1a490ce6e4..a68a8c8317 100644 --- a/src/core/SkPictureData.h +++ b/src/core/SkPictureData.h @@ -62,12 +62,13 @@ public: // Does not affect ownership of SkStream. static SkPictureData* CreateFromStream(SkStream*, const SkPictInfo&, - SkPicture::InstallPixelRefProc); + SkPicture::InstallPixelRefProc, + SkTypefacePlayback*); static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&); virtual ~SkPictureData(); - void serialize(SkWStream*, SkPixelSerializer*) const; + void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet*) const; void flatten(SkWriteBuffer&) const; bool containsBitmaps() const; @@ -82,7 +83,7 @@ protected: explicit SkPictureData(const SkPictInfo& info); // Does not affect ownership of SkStream. - bool parseStream(SkStream*, SkPicture::InstallPixelRefProc); + bool parseStream(SkStream*, SkPicture::InstallPixelRefProc, SkTypefacePlayback*); bool parseBuffer(SkReadBuffer& buffer); public: @@ -95,7 +96,7 @@ public: const int index = reader->readInt(); return fImageRefs[index]; } - + const SkPath& getPath(SkReader32* reader) const { int index = reader->readInt() - 1; return fPaths[index]; @@ -144,7 +145,8 @@ private: // these help us with reading/writing // Does not affect ownership of SkStream. - bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc); + bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, + SkPicture::InstallPixelRefProc, SkTypefacePlayback*); bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size); void flattenToBuffer(SkWriteBuffer&) const; |