diff options
author | Mike Reed <reed@google.com> | 2017-12-13 11:38:57 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-13 17:02:10 +0000 |
commit | 45ab630045ec72dcc0c4546cc1e96ac518897896 (patch) | |
tree | 28f1de8bb01374e1adbb5af96969d130172d57de /src/core/SkPicture.cpp | |
parent | dde37e5f6613bec240b8ea9336e56f58ba63e418 (diff) |
Revert "Revert "impl SkSerial picture procs""
This reverts commit 2a3009931d7bb0f5ca31490c4cf19eef205e4e7a.
Implement SkSerialProcs for pictures
Bug: skia:
Change-Id: Icde2d912941a19999e204ac5213f519ed5387e12
Reviewed-on: https://skia-review.googlesource.com/84480
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkPicture.cpp')
-rw-r--r-- | src/core/SkPicture.cpp | 116 |
1 files changed, 104 insertions, 12 deletions
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 5442738368..2761c417a6 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -8,6 +8,7 @@ #include "SkAtomics.h" #include "SkImageDeserializer.h" #include "SkImageGenerator.h" +#include "SkMathPriv.h" #include "SkPicture.h" #include "SkPictureCommon.h" #include "SkPictureData.h" @@ -23,6 +24,18 @@ static bool g_AllPictureIOSecurityPrecautionsEnabled = true; static bool g_AllPictureIOSecurityPrecautionsEnabled = false; #endif +// When we read/write the SkPictInfo via a stream, we have a sentinel byte right after the info. +// Note: in the read/write buffer versions, we have a slightly different convention: +// We have a sentinel int32_t: +// 0 : failure +// 1 : PictureData +// <0 : -size of the custom data +enum { + kFailure_TrailingStreamByteAfterPictInfo = 0, // nothing follows + kPictureData_TrailingStreamByteAfterPictInfo = 1, // SkPictureData follows + kCustom_TrailingStreamByteAfterPictInfo = 2, // -size32 follows +}; + /* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */ SkPicture::SkPicture() : fUniqueID(0) {} @@ -175,20 +188,54 @@ sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialPro sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs& procs, SkTypefacePlayback* typefaces) { SkPictInfo info; - if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) { + if (!InternalOnly_StreamIsSKP(stream, &info)) { return nullptr; } - std::unique_ptr<SkPictureData> data( - SkPictureData::CreateFromStream(stream, info, procs, typefaces)); - return Forwardport(info, data.get(), nullptr); + + switch (stream->readU8()) { + case kPictureData_TrailingStreamByteAfterPictInfo: { + std::unique_ptr<SkPictureData> data( + SkPictureData::CreateFromStream(stream, info, procs, typefaces)); + return Forwardport(info, data.get(), nullptr); + } + case kCustom_TrailingStreamByteAfterPictInfo: { + int32_t ssize = stream->readS32(); + if (ssize >= 0 || !procs.fPictureProc) { + return nullptr; + } + size_t size = sk_negate_to_size_t(ssize); + auto data = SkData::MakeUninitialized(size); + if (stream->read(data->writable_data(), size) != size) { + return nullptr; + } + return procs.fPictureProc(data->data(), size, procs.fPictureCtx); + } + default: // fall through to error return + break; + } + return nullptr; } sk_sp<SkPicture> SkPicture::MakeFromBuffer(SkReadBuffer& buffer) { SkPictInfo info; - if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) { + if (!InternalOnly_BufferIsSKP(&buffer, &info)) { return nullptr; } - std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info)); + // size should be 0, 1, or negative + int32_t ssize = buffer.read32(); + if (ssize < 0) { + const SkDeserialProcs& procs = buffer.fProcs; + if (!procs.fPictureProc) { + return nullptr; + } + size_t size = sk_negate_to_size_t(ssize); + return procs.fPictureProc(buffer.skip(size), size, procs.fPictureCtx); + } + if (ssize != 1) { + // 1 is the magic 'size' that means SkPictureData follows + return nullptr; + } + std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info)); return Forwardport(info, data.get(), &buffer); } @@ -222,17 +269,54 @@ sk_sp<SkData> SkPicture::serialize(const SkSerialProcs& procs) const { return stream.detachAsData(); } +static sk_sp<SkData> custom_serialize(const SkPicture* picture, const SkSerialProcs& procs) { + if (procs.fPictureProc) { + auto data = procs.fPictureProc(const_cast<SkPicture*>(picture), procs.fPictureCtx); + if (data) { + size_t size = data->size(); + if (!sk_64_isS32(size) || size <= 1) { + return SkData::MakeEmpty(); + } + return data; + } + } + return nullptr; +} + +static bool write_pad32(SkWStream* stream, const void* data, size_t size) { + if (!stream->write(data, size)) { + return false; + } + if (size & 3) { + uint32_t zero = 0; + return stream->write(&zero, 4 - (size & 3)); + } + return true; +} + void SkPicture::serialize(SkWStream* stream, const SkSerialProcs& procs, SkRefCntSet* typefaceSet) const { SkPictInfo info = this->createHeader(); - std::unique_ptr<SkPictureData> data(this->backport()); - stream->write(&info, sizeof(info)); + + if (auto custom = custom_serialize(this, procs)) { + int32_t size = SkToS32(custom->size()); + if (size == 0) { + stream->write8(kFailure_TrailingStreamByteAfterPictInfo); + return; + } + stream->write8(kCustom_TrailingStreamByteAfterPictInfo); + stream->write32(-size); // negative for custom format + write_pad32(stream, custom->data(), size); + return; + } + + std::unique_ptr<SkPictureData> data(this->backport()); if (data) { - stream->writeBool(true); + stream->write8(kPictureData_TrailingStreamByteAfterPictInfo); data->serialize(stream, procs, typefaceSet); } else { - stream->writeBool(false); + stream->write8(kFailure_TrailingStreamByteAfterPictInfo); } } @@ -244,11 +328,19 @@ void SkPicture::flatten(SkWriteBuffer& buffer) const { buffer.writeUInt(info.getVersion()); buffer.writeRect(info.fCullRect); buffer.writeUInt(info.fFlags); + + if (auto custom = custom_serialize(this, buffer.fProcs)) { + int32_t size = SkToS32(custom->size()); + buffer.write32(-size); // negative for custom format + buffer.writePad32(custom->data(), size); + return; + } + if (data) { - buffer.writeBool(true); + buffer.write32(1); // special size meaning SkPictureData data->flatten(buffer); } else { - buffer.writeBool(false); + buffer.write32(0); // signal no content } } |