aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkPicture.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-12-13 11:38:57 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-13 17:02:10 +0000
commit45ab630045ec72dcc0c4546cc1e96ac518897896 (patch)
tree28f1de8bb01374e1adbb5af96969d130172d57de /src/core/SkPicture.cpp
parentdde37e5f6613bec240b8ea9336e56f58ba63e418 (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.cpp116
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
}
}