add serial procs to pictures
Bug: skia:7380 Change-Id: Ic1b7e437316c7913711cf5cb119e3fe904cd2c05 Reviewed-on: https://skia-review.googlesource.com/76980 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
c8037dc5ed
commit
60691a5127
@ -203,6 +203,7 @@ tests_sources = [
|
|||||||
"$_tests/ScalarTest.cpp",
|
"$_tests/ScalarTest.cpp",
|
||||||
"$_tests/ScaleToSidesTest.cpp",
|
"$_tests/ScaleToSidesTest.cpp",
|
||||||
"$_tests/SerializationTest.cpp",
|
"$_tests/SerializationTest.cpp",
|
||||||
|
"$_tests/SerialProcsTest.cpp",
|
||||||
"$_tests/ShaderOpacityTest.cpp",
|
"$_tests/ShaderOpacityTest.cpp",
|
||||||
"$_tests/ShaderTest.cpp",
|
"$_tests/ShaderTest.cpp",
|
||||||
"$_tests/ShadowTest.cpp",
|
"$_tests/ShadowTest.cpp",
|
||||||
|
@ -17,6 +17,7 @@ class SkBigPicture;
|
|||||||
class SkBitmap;
|
class SkBitmap;
|
||||||
class SkCanvas;
|
class SkCanvas;
|
||||||
class SkData;
|
class SkData;
|
||||||
|
struct SkDeserialProcs;
|
||||||
class SkImage;
|
class SkImage;
|
||||||
class SkImageDeserializer;
|
class SkImageDeserializer;
|
||||||
class SkPath;
|
class SkPath;
|
||||||
@ -24,6 +25,7 @@ class SkPictureData;
|
|||||||
class SkPixelSerializer;
|
class SkPixelSerializer;
|
||||||
class SkReadBuffer;
|
class SkReadBuffer;
|
||||||
class SkRefCntSet;
|
class SkRefCntSet;
|
||||||
|
struct SkSerialProcs;
|
||||||
class SkStream;
|
class SkStream;
|
||||||
class SkTypefacePlayback;
|
class SkTypefacePlayback;
|
||||||
class SkWStream;
|
class SkWStream;
|
||||||
@ -62,6 +64,10 @@ public:
|
|||||||
SkImageDeserializer* = nullptr);
|
SkImageDeserializer* = nullptr);
|
||||||
static sk_sp<SkPicture> MakeFromData(const SkData* data, SkImageDeserializer* = nullptr);
|
static sk_sp<SkPicture> MakeFromData(const SkData* data, SkImageDeserializer* = nullptr);
|
||||||
|
|
||||||
|
static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs& procs);
|
||||||
|
static sk_sp<SkPicture> MakeFromData(const SkData* data, const SkDeserialProcs& procs);
|
||||||
|
static sk_sp<SkPicture> MakeFromData(sk_sp<SkData> data, const SkDeserialProcs& procs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recreate a picture that was serialized into a buffer. If the creation requires bitmap
|
* Recreate a picture that was serialized into a buffer. If the creation requires bitmap
|
||||||
* decoding, the decoder must be set on the SkReadBuffer parameter by calling
|
* decoding, the decoder must be set on the SkReadBuffer parameter by calling
|
||||||
@ -112,6 +118,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
sk_sp<SkData> serialize(SkPixelSerializer* = nullptr) const;
|
sk_sp<SkData> serialize(SkPixelSerializer* = nullptr) const;
|
||||||
|
|
||||||
|
sk_sp<SkData> serialize(const SkSerialProcs&) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize to a stream. If non nullptr, pixel-serializer will be used to
|
* Serialize to a stream. If non nullptr, pixel-serializer will be used to
|
||||||
* customize how images reference by the picture are serialized/compressed.
|
* customize how images reference by the picture are serialized/compressed.
|
||||||
@ -169,8 +177,8 @@ private:
|
|||||||
friend class SkEmptyPicture;
|
friend class SkEmptyPicture;
|
||||||
template <typename> friend class SkMiniPicture;
|
template <typename> friend class SkMiniPicture;
|
||||||
|
|
||||||
void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet* typefaces) const;
|
void serialize(SkWStream*, const SkSerialProcs&, SkRefCntSet* typefaces) const;
|
||||||
static sk_sp<SkPicture> MakeFromStream(SkStream*, SkImageDeserializer*, SkTypefacePlayback*);
|
static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs&, SkTypefacePlayback*);
|
||||||
friend class SkPictureData;
|
friend class SkPictureData;
|
||||||
|
|
||||||
virtual int numSlowPaths() const = 0;
|
virtual int numSlowPaths() const = 0;
|
||||||
|
60
include/core/SkSerialProcs.h
Normal file
60
include/core/SkSerialProcs.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkSerialProcs_DEFINED
|
||||||
|
#define SkSerialProcs_DEFINED
|
||||||
|
|
||||||
|
#include "SkImage.h"
|
||||||
|
#include "SkPicture.h"
|
||||||
|
#include "SkTypeface.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serial-proc is asked to serialize the specified object (e.g. picture or image), by writing
|
||||||
|
* its serialized form into the specified stream. If the proc does this, it returns true.
|
||||||
|
*
|
||||||
|
* If the proc chooses to have Skia perform its default action, it ignores the stream parameter
|
||||||
|
* and just returns false.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef bool (*SkSerialPictureProc)(SkPicture*, SkWStream*, void* ctx);
|
||||||
|
typedef bool (*SkSerialImageProc)(SkImage*, SkWStream*, void* ctx);
|
||||||
|
typedef bool (*SkSerialTypefaceProc)(SkTypeface*, SkWStream*, void* ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A deserial-proc is given the serialized form previously returned by the corresponding
|
||||||
|
* serial-proc, and should return the re-constituted object. In case of an error, the proc
|
||||||
|
* can return nullptr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef sk_sp<SkPicture> (*SkDeserialPictureProc)(const void* data, size_t length, void* ctx);
|
||||||
|
typedef sk_sp<SkImage> (*SkDeserialImageProc)(const void* data, size_t length, void* ctx);
|
||||||
|
typedef sk_sp<SkTypeface> (*SkDeserialTypefaceProc)(const void* data, size_t length, void* ctx);
|
||||||
|
|
||||||
|
struct SkSerialProcs {
|
||||||
|
SkSerialPictureProc fPictureProc = nullptr;
|
||||||
|
void* fPictureCtx = nullptr;
|
||||||
|
|
||||||
|
SkSerialImageProc fImageProc = nullptr;
|
||||||
|
void* fImageCtx = nullptr;
|
||||||
|
|
||||||
|
SkSerialTypefaceProc fTypefaceProc = nullptr;
|
||||||
|
void* fTypefaceCtx = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkDeserialProcs {
|
||||||
|
SkDeserialPictureProc fPictureProc = nullptr;
|
||||||
|
void* fPictureCtx = nullptr;
|
||||||
|
|
||||||
|
SkDeserialImageProc fImageProc = nullptr;
|
||||||
|
void* fImageCtx = nullptr;
|
||||||
|
|
||||||
|
SkDeserialTypefaceProc fTypefaceProc = nullptr;
|
||||||
|
void* fTypefaceCtx = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -9,15 +9,21 @@
|
|||||||
#ifndef SkWriteBuffer_DEFINED
|
#ifndef SkWriteBuffer_DEFINED
|
||||||
#define SkWriteBuffer_DEFINED
|
#define SkWriteBuffer_DEFINED
|
||||||
|
|
||||||
|
#define SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
|
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
#include "SkImage.h"
|
#include "SkImage.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
#include "SkPicture.h"
|
#include "SkPicture.h"
|
||||||
#include "SkPixelSerializer.h"
|
|
||||||
#include "SkRefCnt.h"
|
#include "SkRefCnt.h"
|
||||||
|
#include "SkSerialProcs.h"
|
||||||
#include "SkWriter32.h"
|
#include "SkWriter32.h"
|
||||||
#include "../private/SkTHash.h"
|
#include "../private/SkTHash.h"
|
||||||
|
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
|
#include "SkPixelSerializer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class SkBitmap;
|
class SkBitmap;
|
||||||
class SkDeduper;
|
class SkDeduper;
|
||||||
class SkFactorySet;
|
class SkFactorySet;
|
||||||
@ -102,6 +108,9 @@ public:
|
|||||||
void write(const void* buffer, size_t bytes) {
|
void write(const void* buffer, size_t bytes) {
|
||||||
fWriter.write(buffer, bytes);
|
fWriter.write(buffer, bytes);
|
||||||
}
|
}
|
||||||
|
void writePad32(const void* buffer, size_t bytes) {
|
||||||
|
fWriter.writePad(buffer, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
void reset(void* storage = nullptr, size_t storageSize = 0) {
|
void reset(void* storage = nullptr, size_t storageSize = 0) {
|
||||||
fWriter.reset(storage, storageSize);
|
fWriter.reset(storage, storageSize);
|
||||||
@ -141,26 +150,26 @@ public:
|
|||||||
SkFactorySet* setFactoryRecorder(SkFactorySet*);
|
SkFactorySet* setFactoryRecorder(SkFactorySet*);
|
||||||
SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
|
SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
|
||||||
|
|
||||||
/**
|
void setSerialProcs(const SkSerialProcs& procs) { fProcs = procs; }
|
||||||
* Set an SkPixelSerializer to store an encoded representation of pixels,
|
|
||||||
* e.g. SkBitmaps.
|
#ifdef SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
*
|
|
||||||
* TODO: Encode SkImage pixels as well.
|
|
||||||
*/
|
|
||||||
void setPixelSerializer(sk_sp<SkPixelSerializer>);
|
void setPixelSerializer(sk_sp<SkPixelSerializer>);
|
||||||
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer.get(); }
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint32_t fFlags;
|
const uint32_t fFlags;
|
||||||
SkFactorySet* fFactorySet;
|
SkFactorySet* fFactorySet;
|
||||||
SkWriter32 fWriter;
|
SkWriter32 fWriter;
|
||||||
|
|
||||||
SkRefCntSet* fTFSet;
|
SkRefCntSet* fTFSet;
|
||||||
|
SkSerialProcs fProcs;
|
||||||
sk_sp<SkPixelSerializer> fPixelSerializer;
|
|
||||||
|
|
||||||
// Only used if we do not have an fFactorySet
|
// Only used if we do not have an fFactorySet
|
||||||
SkTHashMap<SkString, uint32_t> fFlattenableDict;
|
SkTHashMap<SkString, uint32_t> fFlattenableDict;
|
||||||
|
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
|
sk_sp<SkPixelSerializer> fPS;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SkWriteBuffer_DEFINED
|
#endif // SkWriteBuffer_DEFINED
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
#include "SkImageDeserializer.h"
|
#include "SkImageDeserializer.h"
|
||||||
#include "SkImageGenerator.h"
|
#include "SkImageGenerator.h"
|
||||||
#include "SkPicture.h"
|
#include "SkPicture.h"
|
||||||
|
#include "SkPictureCommon.h"
|
||||||
#include "SkPictureData.h"
|
#include "SkPictureData.h"
|
||||||
#include "SkPicturePlayback.h"
|
#include "SkPicturePlayback.h"
|
||||||
#include "SkPictureRecord.h"
|
#include "SkPictureRecord.h"
|
||||||
#include "SkPictureRecorder.h"
|
#include "SkPictureRecorder.h"
|
||||||
|
#include "SkSerialProcs.h"
|
||||||
|
|
||||||
#if defined(SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS) || \
|
#if defined(SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS) || \
|
||||||
defined(SK_ENABLE_PICTURE_IO_SECURITY_PRECAUTIONS)
|
defined(SK_ENABLE_PICTURE_IO_SECURITY_PRECAUTIONS)
|
||||||
@ -129,7 +131,10 @@ sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) {
|
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) {
|
||||||
return MakeFromStream(stream, factory, nullptr);
|
SkDeserialProcs procs;
|
||||||
|
procs.fImageProc = ImageDeserializer_SkDeserialImageProc;
|
||||||
|
procs.fImageCtx = factory;
|
||||||
|
return MakeFromStream(stream, procs, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
|
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
|
||||||
@ -140,7 +145,7 @@ sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
|
|||||||
sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size,
|
sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size,
|
||||||
SkImageDeserializer* factory) {
|
SkImageDeserializer* factory) {
|
||||||
SkMemoryStream stream(data, size);
|
SkMemoryStream stream(data, size);
|
||||||
return MakeFromStream(&stream, factory, nullptr);
|
return MakeFromStream(&stream, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, SkImageDeserializer* factory) {
|
sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, SkImageDeserializer* factory) {
|
||||||
@ -148,17 +153,33 @@ sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, SkImageDeserializer
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
SkMemoryStream stream(data->data(), data->size());
|
SkMemoryStream stream(data->data(), data->size());
|
||||||
return MakeFromStream(&stream, factory, nullptr);
|
return MakeFromStream(&stream, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory,
|
sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, const SkDeserialProcs& procs) {
|
||||||
|
if (!data) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
SkMemoryStream stream(data->data(), data->size());
|
||||||
|
return MakeFromStream(&stream, procs, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_sp<SkPicture> SkPicture::MakeFromData(sk_sp<SkData> data, const SkDeserialProcs& procs) {
|
||||||
|
return MakeFromData(data.get(), procs);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs& procs) {
|
||||||
|
return MakeFromStream(stream, procs, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs& procs,
|
||||||
SkTypefacePlayback* typefaces) {
|
SkTypefacePlayback* typefaces) {
|
||||||
SkPictInfo info;
|
SkPictInfo info;
|
||||||
if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
|
if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::unique_ptr<SkPictureData> data(
|
std::unique_ptr<SkPictureData> data(
|
||||||
SkPictureData::CreateFromStream(stream, info, factory, typefaces));
|
SkPictureData::CreateFromStream(stream, info, procs, typefaces));
|
||||||
return Forwardport(info, data.get(), nullptr);
|
return Forwardport(info, data.get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,17 +202,27 @@ SkPictureData* SkPicture::backport() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
|
void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
|
||||||
this->serialize(stream, pixelSerializer, nullptr);
|
SkSerialProcs procs;
|
||||||
|
if (pixelSerializer) {
|
||||||
|
procs.fImageProc = PixelSerializer_SkSerialImageProc;
|
||||||
|
procs.fImageCtx = pixelSerializer;
|
||||||
|
}
|
||||||
|
this->serialize(stream, procs, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkData> SkPicture::serialize(SkPixelSerializer* pixelSerializer) const {
|
sk_sp<SkData> SkPicture::serialize(SkPixelSerializer* pixelSerializer) const {
|
||||||
SkDynamicMemoryWStream stream;
|
SkDynamicMemoryWStream stream;
|
||||||
this->serialize(&stream, pixelSerializer, nullptr);
|
this->serialize(&stream, pixelSerializer);
|
||||||
return stream.detachAsData();
|
return stream.detachAsData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPicture::serialize(SkWStream* stream,
|
sk_sp<SkData> SkPicture::serialize(const SkSerialProcs& procs) const {
|
||||||
SkPixelSerializer* pixelSerializer,
|
SkDynamicMemoryWStream stream;
|
||||||
|
this->serialize(&stream, procs, nullptr);
|
||||||
|
return stream.detachAsData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkPicture::serialize(SkWStream* stream, const SkSerialProcs& procs,
|
||||||
SkRefCntSet* typefaceSet) const {
|
SkRefCntSet* typefaceSet) const {
|
||||||
SkPictInfo info = this->createHeader();
|
SkPictInfo info = this->createHeader();
|
||||||
std::unique_ptr<SkPictureData> data(this->backport());
|
std::unique_ptr<SkPictureData> data(this->backport());
|
||||||
@ -199,7 +230,7 @@ void SkPicture::serialize(SkWStream* stream,
|
|||||||
stream->write(&info, sizeof(info));
|
stream->write(&info, sizeof(info));
|
||||||
if (data) {
|
if (data) {
|
||||||
stream->writeBool(true);
|
stream->writeBool(true);
|
||||||
data->serialize(stream, pixelSerializer, typefaceSet);
|
data->serialize(stream, procs, typefaceSet);
|
||||||
} else {
|
} else {
|
||||||
stream->writeBool(false);
|
stream->writeBool(false);
|
||||||
}
|
}
|
||||||
@ -239,3 +270,51 @@ void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) {
|
|||||||
bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
|
bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
|
||||||
return g_AllPictureIOSecurityPrecautionsEnabled;
|
return g_AllPictureIOSecurityPrecautionsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool PixelSerializer_SkSerialImageProc(SkImage* img, SkWStream* stream, void* ctx) {
|
||||||
|
SkASSERT(ctx);
|
||||||
|
sk_sp<SkData> enc = img->encodeToData(static_cast<SkPixelSerializer*>(ctx));
|
||||||
|
if (enc) {
|
||||||
|
stream->write(enc->data(), enc->size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_sp<SkImage> ImageDeserializer_SkDeserialImageProc(const void* data, size_t length, void* ctx) {
|
||||||
|
SkASSERT(ctx);
|
||||||
|
SkImageDeserializer* imd = static_cast<SkImageDeserializer*>(ctx);
|
||||||
|
const SkIRect* subset = nullptr;
|
||||||
|
return imd->makeFromMemory(data, length, subset);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
|
#include "SkReadBuffer.h"
|
||||||
|
#include "SkWriteBuffer.h"
|
||||||
|
|
||||||
|
void SkBinaryWriteBuffer::setPixelSerializer(sk_sp<SkPixelSerializer> ps) {
|
||||||
|
fPS = ps;
|
||||||
|
if (ps) {
|
||||||
|
fProcs.fImageProc = PixelSerializer_SkSerialImageProc;
|
||||||
|
fProcs.fImageCtx = ps.get();
|
||||||
|
} else {
|
||||||
|
fProcs.fImageProc = nullptr;
|
||||||
|
fProcs.fImageCtx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkReadBuffer::setImageDeserializer(SkImageDeserializer* factory) {
|
||||||
|
if (factory) {
|
||||||
|
fProcs.fImageProc = ImageDeserializer_SkDeserialImageProc;
|
||||||
|
fProcs.fImageCtx = factory;
|
||||||
|
} else {
|
||||||
|
fProcs.fImageProc = nullptr;
|
||||||
|
fProcs.fImageCtx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -141,4 +141,8 @@ struct SkPathCounter {
|
|||||||
|
|
||||||
int fNumSlowPathsAndDashEffects;
|
int fNumSlowPathsAndDashEffects;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool PixelSerializer_SkSerialImageProc(SkImage*, SkWStream*, void* sk_pixelserializer);
|
||||||
|
sk_sp<SkImage> ImageDeserializer_SkDeserialImageProc(const void*, size_t, void* imagedeserializer);
|
||||||
|
|
||||||
#endif // SkPictureCommon_DEFINED
|
#endif // SkPictureCommon_DEFINED
|
||||||
|
@ -278,8 +278,7 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureData::serialize(SkWStream* stream,
|
void SkPictureData::serialize(SkWStream* stream, const SkSerialProcs& procs,
|
||||||
SkPixelSerializer* pixelSerializer,
|
|
||||||
SkRefCntSet* topLevelTypeFaceSet) const {
|
SkRefCntSet* topLevelTypeFaceSet) const {
|
||||||
// This can happen at pretty much any time, so might as well do it first.
|
// 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());
|
write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
|
||||||
@ -294,7 +293,7 @@ void SkPictureData::serialize(SkWStream* stream,
|
|||||||
SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
|
SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
|
||||||
SkBinaryWriteBuffer buffer(SkBinaryWriteBuffer::kCrossProcess_Flag);
|
SkBinaryWriteBuffer buffer(SkBinaryWriteBuffer::kCrossProcess_Flag);
|
||||||
buffer.setFactoryRecorder(&factSet);
|
buffer.setFactoryRecorder(&factSet);
|
||||||
buffer.setPixelSerializer(sk_ref_sp(pixelSerializer));
|
buffer.setSerialProcs(procs);
|
||||||
buffer.setTypefaceRecorder(typefaceSet);
|
buffer.setTypefaceRecorder(typefaceSet);
|
||||||
this->flattenToBuffer(buffer);
|
this->flattenToBuffer(buffer);
|
||||||
|
|
||||||
@ -307,7 +306,7 @@ void SkPictureData::serialize(SkWStream* stream,
|
|||||||
size_t bytesWritten() const override { return fBytesWritten; }
|
size_t bytesWritten() const override { return fBytesWritten; }
|
||||||
} devnull;
|
} devnull;
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
for (int i = 0; i < fPictureCount; i++) {
|
||||||
fPictureRefs[i]->serialize(&devnull, pixelSerializer, typefaceSet);
|
fPictureRefs[i]->serialize(&devnull, procs, typefaceSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to write factories before we write the buffer.
|
// We need to write factories before we write the buffer.
|
||||||
@ -325,7 +324,7 @@ void SkPictureData::serialize(SkWStream* stream,
|
|||||||
if (fPictureCount > 0) {
|
if (fPictureCount > 0) {
|
||||||
write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
|
write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
|
||||||
for (int i = 0; i < fPictureCount; i++) {
|
for (int i = 0; i < fPictureCount; i++) {
|
||||||
fPictureRefs[i]->serialize(stream, pixelSerializer, typefaceSet);
|
fPictureRefs[i]->serialize(stream, procs, typefaceSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +382,7 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
|
|||||||
bool SkPictureData::parseStreamTag(SkStream* stream,
|
bool SkPictureData::parseStreamTag(SkStream* stream,
|
||||||
uint32_t tag,
|
uint32_t tag,
|
||||||
uint32_t size,
|
uint32_t size,
|
||||||
SkImageDeserializer* factory,
|
const SkDeserialProcs& procs,
|
||||||
SkTypefacePlayback* topLevelTFPlayback) {
|
SkTypefacePlayback* topLevelTFPlayback) {
|
||||||
/*
|
/*
|
||||||
* By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
|
* By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
|
||||||
@ -436,7 +435,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
|||||||
fPictureCount = 0;
|
fPictureCount = 0;
|
||||||
fPictureRefs = new const SkPicture* [size];
|
fPictureRefs = new const SkPicture* [size];
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
fPictureRefs[i] = SkPicture::MakeFromStream(stream, factory, topLevelTFPlayback).release();
|
fPictureRefs[i] = SkPicture::MakeFromStream(stream, procs, topLevelTFPlayback).release();
|
||||||
if (!fPictureRefs[i]) {
|
if (!fPictureRefs[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -458,7 +457,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fFactoryPlayback->setupBuffer(buffer);
|
fFactoryPlayback->setupBuffer(buffer);
|
||||||
buffer.setImageDeserializer(factory);
|
buffer.setDeserialProcs(procs);
|
||||||
|
|
||||||
if (fTFPlayback.count() > 0) {
|
if (fTFPlayback.count() > 0) {
|
||||||
// .skp files <= v43 have typefaces serialized with each sub picture.
|
// .skp files <= v43 have typefaces serialized with each sub picture.
|
||||||
@ -602,14 +601,14 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
|
|||||||
|
|
||||||
SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
|
SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
|
||||||
const SkPictInfo& info,
|
const SkPictInfo& info,
|
||||||
SkImageDeserializer* factory,
|
const SkDeserialProcs& procs,
|
||||||
SkTypefacePlayback* topLevelTFPlayback) {
|
SkTypefacePlayback* topLevelTFPlayback) {
|
||||||
std::unique_ptr<SkPictureData> data(new SkPictureData(info));
|
std::unique_ptr<SkPictureData> data(new SkPictureData(info));
|
||||||
if (!topLevelTFPlayback) {
|
if (!topLevelTFPlayback) {
|
||||||
topLevelTFPlayback = &data->fTFPlayback;
|
topLevelTFPlayback = &data->fTFPlayback;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data->parseStream(stream, factory, topLevelTFPlayback)) {
|
if (!data->parseStream(stream, procs, topLevelTFPlayback)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return data.release();
|
return data.release();
|
||||||
@ -627,7 +626,7 @@ SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SkPictureData::parseStream(SkStream* stream,
|
bool SkPictureData::parseStream(SkStream* stream,
|
||||||
SkImageDeserializer* factory,
|
const SkDeserialProcs& procs,
|
||||||
SkTypefacePlayback* topLevelTFPlayback) {
|
SkTypefacePlayback* topLevelTFPlayback) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t tag = stream->readU32();
|
uint32_t tag = stream->readU32();
|
||||||
@ -636,7 +635,7 @@ bool SkPictureData::parseStream(SkStream* stream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = stream->readU32();
|
uint32_t size = stream->readU32();
|
||||||
if (!this->parseStreamTag(stream, tag, size, factory, topLevelTFPlayback)) {
|
if (!this->parseStreamTag(stream, tag, size, procs, topLevelTFPlayback)) {
|
||||||
return false; // we're invalid
|
return false; // we're invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
class SkData;
|
class SkData;
|
||||||
class SkPictureRecord;
|
class SkPictureRecord;
|
||||||
class SkPixelSerializer;
|
|
||||||
class SkReader32;
|
class SkReader32;
|
||||||
|
struct SkSerialProcs;
|
||||||
class SkStream;
|
class SkStream;
|
||||||
class SkWStream;
|
class SkWStream;
|
||||||
class SkBBoxHierarchy;
|
class SkBBoxHierarchy;
|
||||||
@ -79,13 +79,13 @@ public:
|
|||||||
// Does not affect ownership of SkStream.
|
// Does not affect ownership of SkStream.
|
||||||
static SkPictureData* CreateFromStream(SkStream*,
|
static SkPictureData* CreateFromStream(SkStream*,
|
||||||
const SkPictInfo&,
|
const SkPictInfo&,
|
||||||
SkImageDeserializer*,
|
const SkDeserialProcs&,
|
||||||
SkTypefacePlayback*);
|
SkTypefacePlayback*);
|
||||||
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
|
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
|
||||||
|
|
||||||
virtual ~SkPictureData();
|
virtual ~SkPictureData();
|
||||||
|
|
||||||
void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet*) const;
|
void serialize(SkWStream*, const SkSerialProcs&, SkRefCntSet*) const;
|
||||||
void flatten(SkWriteBuffer&) const;
|
void flatten(SkWriteBuffer&) const;
|
||||||
|
|
||||||
bool containsBitmaps() const;
|
bool containsBitmaps() const;
|
||||||
@ -100,7 +100,7 @@ protected:
|
|||||||
explicit SkPictureData(const SkPictInfo& info);
|
explicit SkPictureData(const SkPictInfo& info);
|
||||||
|
|
||||||
// Does not affect ownership of SkStream.
|
// Does not affect ownership of SkStream.
|
||||||
bool parseStream(SkStream*, SkImageDeserializer*, SkTypefacePlayback*);
|
bool parseStream(SkStream*, const SkDeserialProcs&, SkTypefacePlayback*);
|
||||||
bool parseBuffer(SkReadBuffer& buffer);
|
bool parseBuffer(SkReadBuffer& buffer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -172,7 +172,7 @@ private:
|
|||||||
// 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,
|
||||||
SkImageDeserializer*, SkTypefacePlayback*);
|
const SkDeserialProcs&, SkTypefacePlayback*);
|
||||||
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
|
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
|
||||||
void flattenToBuffer(SkWriteBuffer&) const;
|
void flattenToBuffer(SkWriteBuffer&) const;
|
||||||
|
|
||||||
|
@ -44,9 +44,6 @@ static uint32_t default_flags() {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This has an empty constructor and destructor, and is thread-safe, so we can use a singleton.
|
|
||||||
static SkImageDeserializer gDefaultImageDeserializer;
|
|
||||||
|
|
||||||
SkReadBuffer::SkReadBuffer() {
|
SkReadBuffer::SkReadBuffer() {
|
||||||
fFlags = default_flags();
|
fFlags = default_flags();
|
||||||
fVersion = 0;
|
fVersion = 0;
|
||||||
@ -57,7 +54,6 @@ SkReadBuffer::SkReadBuffer() {
|
|||||||
|
|
||||||
fFactoryArray = nullptr;
|
fFactoryArray = nullptr;
|
||||||
fFactoryCount = 0;
|
fFactoryCount = 0;
|
||||||
fImageDeserializer = &gDefaultImageDeserializer;
|
|
||||||
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
fDecodedBitmapIndex = -1;
|
fDecodedBitmapIndex = -1;
|
||||||
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
@ -74,7 +70,6 @@ SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
|
|||||||
|
|
||||||
fFactoryArray = nullptr;
|
fFactoryArray = nullptr;
|
||||||
fFactoryCount = 0;
|
fFactoryCount = 0;
|
||||||
fImageDeserializer = &gDefaultImageDeserializer;
|
|
||||||
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
fDecodedBitmapIndex = -1;
|
fDecodedBitmapIndex = -1;
|
||||||
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
@ -93,7 +88,6 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
|
|||||||
|
|
||||||
fFactoryArray = nullptr;
|
fFactoryArray = nullptr;
|
||||||
fFactoryCount = 0;
|
fFactoryCount = 0;
|
||||||
fImageDeserializer = &gDefaultImageDeserializer;
|
|
||||||
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
fDecodedBitmapIndex = -1;
|
fDecodedBitmapIndex = -1;
|
||||||
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
@ -103,8 +97,8 @@ SkReadBuffer::~SkReadBuffer() {
|
|||||||
sk_free(fMemoryPtr);
|
sk_free(fMemoryPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkReadBuffer::setImageDeserializer(SkImageDeserializer* deserializer) {
|
void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
|
||||||
fImageDeserializer = deserializer ? deserializer : &gDefaultImageDeserializer;
|
fProcs = procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkReadBuffer::readBool() {
|
bool SkReadBuffer::readBool() {
|
||||||
@ -131,6 +125,14 @@ int32_t SkReadBuffer::read32() {
|
|||||||
return fReader.readInt();
|
return fReader.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkReadBuffer::readPad32(void* buffer, size_t bytes) {
|
||||||
|
if (!fReader.isAvailable(bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fReader.read(buffer, bytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t SkReadBuffer::peekByte() {
|
uint8_t SkReadBuffer::peekByte() {
|
||||||
SkASSERT(fReader.available() > 0);
|
SkASSERT(fReader.available() > 0);
|
||||||
return *((uint8_t*) fReader.peek());
|
return *((uint8_t*) fReader.peek());
|
||||||
@ -235,10 +237,16 @@ sk_sp<SkImage> SkReadBuffer::readImage() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t encoded_size = this->getArrayCount();
|
/*
|
||||||
|
* What follows is a 32bit encoded size.
|
||||||
|
* 0 : failure, nothing else to do
|
||||||
|
* <0 : negative (int32_t) of a custom encoded blob using SerialProcs
|
||||||
|
* >0 : standard encoded blob size (use MakeFromEncoded)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32_t encoded_size = this->read32();
|
||||||
if (encoded_size == 0) {
|
if (encoded_size == 0) {
|
||||||
// The image could not be encoded at serialization time - return an empty placeholder.
|
// The image could not be encoded at serialization time - return an empty placeholder.
|
||||||
(void)this->readUInt(); // Swallow that encoded_size == 0 sentinel.
|
|
||||||
return MakeEmptyImage(width, height);
|
return MakeEmptyImage(width, height);
|
||||||
}
|
}
|
||||||
if (encoded_size == 1) {
|
if (encoded_size == 1) {
|
||||||
@ -247,19 +255,33 @@ sk_sp<SkImage> SkReadBuffer::readImage() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The SkImage encoded itself.
|
size_t size = SkAbs32(encoded_size);
|
||||||
sk_sp<SkData> encoded(this->readByteArrayAsData());
|
sk_sp<SkData> data = SkData::MakeUninitialized(size);
|
||||||
|
if (!this->readPad32(data->writable_data(), size)) {
|
||||||
int originX = this->read32();
|
this->validate(false);
|
||||||
int originY = this->read32();
|
return nullptr;
|
||||||
|
}
|
||||||
|
int32_t originX = this->read32();
|
||||||
|
int32_t originY = this->read32();
|
||||||
if (originX < 0 || originY < 0) {
|
if (originX < 0 || originY < 0) {
|
||||||
this->validate(false);
|
this->validate(false);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height);
|
sk_sp<SkImage> image;
|
||||||
|
if (encoded_size < 0) { // custom encoded, need serial proc
|
||||||
sk_sp<SkImage> image = fImageDeserializer->makeFromData(encoded.get(), &subset);
|
if (fProcs.fImageProc) {
|
||||||
|
image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx);
|
||||||
|
} else {
|
||||||
|
// Nothing to do (no client proc), but since we've already "read" the custom data,
|
||||||
|
// wee just leave image as nullptr.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height);
|
||||||
|
image = SkImage::MakeFromEncoded(std::move(data), &subset);
|
||||||
|
}
|
||||||
|
// Question: are we correct to return an "empty" image instead of nullptr, if the decoder
|
||||||
|
// failed for some reason?
|
||||||
return image ? image : MakeEmptyImage(width, height);
|
return image ? image : MakeEmptyImage(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "SkColorFilter.h"
|
#include "SkColorFilter.h"
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
|
#include "SkSerialProcs.h"
|
||||||
#include "SkDrawLooper.h"
|
#include "SkDrawLooper.h"
|
||||||
#include "SkImageFilter.h"
|
#include "SkImageFilter.h"
|
||||||
#include "SkMaskFilter.h"
|
#include "SkMaskFilter.h"
|
||||||
@ -24,7 +25,6 @@
|
|||||||
#include "SkTHash.h"
|
#include "SkTHash.h"
|
||||||
#include "SkWriteBuffer.h"
|
#include "SkWriteBuffer.h"
|
||||||
|
|
||||||
class SkBitmap;
|
|
||||||
class SkImage;
|
class SkImage;
|
||||||
class SkInflator;
|
class SkInflator;
|
||||||
|
|
||||||
@ -157,6 +157,9 @@ public:
|
|||||||
sk_sp<SkRasterizer> readRasterizer() { return this->readFlattenable<SkRasterizer>(); }
|
sk_sp<SkRasterizer> readRasterizer() { return this->readFlattenable<SkRasterizer>(); }
|
||||||
sk_sp<SkShader> readShader() { return this->readFlattenable<SkShaderBase>(); }
|
sk_sp<SkShader> readShader() { return this->readFlattenable<SkShaderBase>(); }
|
||||||
|
|
||||||
|
// Reads SkAlign4(bytes), but will only copy bytes into the buffer.
|
||||||
|
virtual bool readPad32(void* buffer, size_t bytes);
|
||||||
|
|
||||||
// binary data and arrays
|
// binary data and arrays
|
||||||
virtual bool readByteArray(void* value, size_t size);
|
virtual bool readByteArray(void* value, size_t size);
|
||||||
virtual bool readColorArray(SkColor* colors, size_t size);
|
virtual bool readColorArray(SkColor* colors, size_t size);
|
||||||
@ -178,6 +181,9 @@ public:
|
|||||||
// helpers to get info about arrays and binary data
|
// helpers to get info about arrays and binary data
|
||||||
virtual uint32_t getArrayCount();
|
virtual uint32_t getArrayCount();
|
||||||
|
|
||||||
|
// If there is a real error (e.g. data is corrupted) this returns null. If the image cannot
|
||||||
|
// be created (e.g. it was not originally encoded) then this returns an image that doesn't
|
||||||
|
// draw.
|
||||||
sk_sp<SkImage> readImage();
|
sk_sp<SkImage> readImage();
|
||||||
virtual sk_sp<SkTypeface> readTypeface();
|
virtual sk_sp<SkTypeface> readTypeface();
|
||||||
|
|
||||||
@ -209,9 +215,11 @@ public:
|
|||||||
fCustomFactory.set(name, factory);
|
fCustomFactory.set(name, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If nullptr is passed, then the default deserializer will be used
|
void setDeserialProcs(const SkDeserialProcs& procs);
|
||||||
// which calls SkImage::MakeFromEncoded()
|
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_SERIAL_BUFFER_OBJECTS
|
||||||
void setImageDeserializer(SkImageDeserializer* factory);
|
void setImageDeserializer(SkImageDeserializer* factory);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Default impelementations don't check anything.
|
// Default impelementations don't check anything.
|
||||||
virtual bool validate(bool isValid) { return isValid; }
|
virtual bool validate(bool isValid) { return isValid; }
|
||||||
@ -274,8 +282,7 @@ private:
|
|||||||
// Only used if we do not have an fFactoryArray.
|
// Only used if we do not have an fFactoryArray.
|
||||||
SkTHashMap<SkString, SkFlattenable::Factory> fCustomFactory;
|
SkTHashMap<SkString, SkFlattenable::Factory> fCustomFactory;
|
||||||
|
|
||||||
// We do not own this ptr, we just use it (guaranteed to never be null)
|
SkDeserialProcs fProcs;
|
||||||
SkImageDeserializer* fImageDeserializer;
|
|
||||||
|
|
||||||
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
||||||
// Debugging counter to keep track of how many bitmaps we
|
// Debugging counter to keep track of how many bitmaps we
|
||||||
|
@ -130,13 +130,6 @@ bool SkBinaryWriteBuffer::writeToStream(SkWStream* stream) {
|
|||||||
return fWriter.writeToStream(stream);
|
return fWriter.writeToStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_encoded_bitmap(SkBinaryWriteBuffer* buffer, SkData* data,
|
|
||||||
const SkIPoint& origin) {
|
|
||||||
buffer->writeDataAsByteArray(data);
|
|
||||||
buffer->write32(origin.fX);
|
|
||||||
buffer->write32(origin.fY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBinaryWriteBuffer::writeImage(const SkImage* image) {
|
void SkBinaryWriteBuffer::writeImage(const SkImage* image) {
|
||||||
if (fDeduper) {
|
if (fDeduper) {
|
||||||
this->write32(fDeduper->findOrDefineImage(const_cast<SkImage*>(image)));
|
this->write32(fDeduper->findOrDefineImage(const_cast<SkImage*>(image)));
|
||||||
@ -146,12 +139,34 @@ void SkBinaryWriteBuffer::writeImage(const SkImage* image) {
|
|||||||
this->writeInt(image->width());
|
this->writeInt(image->width());
|
||||||
this->writeInt(image->height());
|
this->writeInt(image->height());
|
||||||
|
|
||||||
sk_sp<SkData> encoded = image->encodeToData(this->getPixelSerializer());
|
auto write_data = [this](sk_sp<SkData> data, int sign) {
|
||||||
if (encoded && encoded->size() > 0) {
|
if (data) {
|
||||||
write_encoded_bitmap(this, encoded.get(), SkIPoint::Make(0, 0));
|
size_t size = data->size();
|
||||||
return;
|
if (size && sk_64_isS32(size)) {
|
||||||
|
this->write32(SkToS32(size) * sign);
|
||||||
|
this->writePad32(data->data(), size); // does nothing if size == 0
|
||||||
|
this->write32(0); // origin-x
|
||||||
|
this->write32(0); // origin-y
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->write32(0); // no data or size too big
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What follows is a 32bit encoded size.
|
||||||
|
* 0 : failure, nothing else to do
|
||||||
|
* <0 : negative (int32_t) of a custom encoded blob using SerialProcs
|
||||||
|
* >0 : standard encoded blob size (use MakeFromEncoded)
|
||||||
|
*/
|
||||||
|
if (fProcs.fImageProc) {
|
||||||
|
SkDynamicMemoryWStream stream;
|
||||||
|
if (fProcs.fImageProc(const_cast<SkImage*>(image), &stream, fProcs.fImageCtx)) {
|
||||||
|
write_data(stream.detachAsData(), -1); // -1 signals custom encoder
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->writeUInt(0); // signal no pixels (in place of the size of the encoded data)
|
write_data(image->encodeToData(), 1); // +1 signals standard encoder
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkBinaryWriteBuffer::writeTypeface(SkTypeface* obj) {
|
void SkBinaryWriteBuffer::writeTypeface(SkTypeface* obj) {
|
||||||
@ -181,10 +196,6 @@ SkRefCntSet* SkBinaryWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
|
|||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkBinaryWriteBuffer::setPixelSerializer(sk_sp<SkPixelSerializer> serializer) {
|
|
||||||
fPixelSerializer = std::move(serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBinaryWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
|
void SkBinaryWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
|
||||||
if (nullptr == flattenable) {
|
if (nullptr == flattenable) {
|
||||||
this->write32(0);
|
this->write32(0);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "SkPathEffect.h"
|
#include "SkPathEffect.h"
|
||||||
#include "SkPipeCanvas.h"
|
#include "SkPipeCanvas.h"
|
||||||
#include "SkPipeFormat.h"
|
#include "SkPipeFormat.h"
|
||||||
|
#include "SkPixelSerializer.h"
|
||||||
#include "SkRSXform.h"
|
#include "SkRSXform.h"
|
||||||
#include "SkRasterizer.h"
|
#include "SkRasterizer.h"
|
||||||
#include "SkShader.h"
|
#include "SkShader.h"
|
||||||
|
93
tests/SerialProcsTest.cpp
Normal file
93
tests/SerialProcsTest.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "Resources.h"
|
||||||
|
#include "sk_tool_utils.h"
|
||||||
|
#include "SkCanvas.h"
|
||||||
|
#include "SkPicture.h"
|
||||||
|
#include "SkPictureRecorder.h"
|
||||||
|
#include "SkSerialProcs.h"
|
||||||
|
#include "SkSurface.h"
|
||||||
|
|
||||||
|
static sk_sp<SkImage> picture_to_image(sk_sp<SkPicture> pic) {
|
||||||
|
SkIRect r = pic->cullRect().round();
|
||||||
|
auto surf = SkSurface::MakeRasterN32Premul(r.width(), r.height());
|
||||||
|
surf->getCanvas()->drawPicture(pic);
|
||||||
|
return surf->makeImageSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
const char* fStr;
|
||||||
|
SkImage* fImg;
|
||||||
|
};
|
||||||
|
|
||||||
|
DEF_TEST(serial_procs_image, reporter) {
|
||||||
|
auto src_img = GetResourceAsImage("mandrill_128.png");
|
||||||
|
const char magic_str[] = "magic signature";
|
||||||
|
|
||||||
|
const SkSerialImageProc sprocs[] = {
|
||||||
|
[](SkImage* img, SkWStream* stream, void* ctx) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
[](SkImage* img, SkWStream* stream, void* ctx) {
|
||||||
|
auto d = img->encodeToData();
|
||||||
|
stream->write(d->data(), d->size());
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[](SkImage* img, SkWStream* stream, void* ctx) {
|
||||||
|
State* state = (State*)ctx;
|
||||||
|
stream->write(state->fStr, strlen(state->fStr));
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const SkDeserialImageProc dprocs[] = {
|
||||||
|
[](const void* data, size_t length, void*) -> sk_sp<SkImage> {
|
||||||
|
SK_ABORT("should not get called");
|
||||||
|
return nullptr;
|
||||||
|
},
|
||||||
|
[](const void* data, size_t length, void*) -> sk_sp<SkImage> {
|
||||||
|
return SkImage::MakeFromEncoded(SkData::MakeWithCopy(data, length));
|
||||||
|
},
|
||||||
|
[](const void* data, size_t length, void* ctx) -> sk_sp<SkImage> {
|
||||||
|
State* state = (State*)ctx;
|
||||||
|
if (length != strlen(state->fStr) || memcmp(data, state->fStr, length)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return sk_ref_sp(state->fImg);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
sk_sp<SkPicture> pic;
|
||||||
|
{
|
||||||
|
SkPictureRecorder rec;
|
||||||
|
SkCanvas* canvas = rec.beginRecording(128, 128);
|
||||||
|
canvas->drawImage(src_img, 0, 0, nullptr);
|
||||||
|
pic = rec.finishRecordingAsPicture();
|
||||||
|
}
|
||||||
|
|
||||||
|
State state = { magic_str, src_img.get() };
|
||||||
|
|
||||||
|
SkSerialProcs sproc;
|
||||||
|
sproc.fImageCtx = &state;
|
||||||
|
SkDeserialProcs dproc;
|
||||||
|
dproc.fImageCtx = &state;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < SK_ARRAY_COUNT(sprocs); ++i) {
|
||||||
|
sproc.fImageProc = sprocs[i];
|
||||||
|
auto data = pic->serialize(sproc);
|
||||||
|
REPORTER_ASSERT(reporter, data);
|
||||||
|
|
||||||
|
dproc.fImageProc = dprocs[i];
|
||||||
|
auto new_pic = SkPicture::MakeFromData(data, dproc);
|
||||||
|
REPORTER_ASSERT(reporter, data);
|
||||||
|
|
||||||
|
auto dst_img = picture_to_image(new_pic);
|
||||||
|
REPORTER_ASSERT(reporter, sk_tool_utils::equal_pixels(src_img.get(), dst_img.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ namespace sk_tool_utils {
|
|||||||
bool respectColorSpaces = false);
|
bool respectColorSpaces = false);
|
||||||
bool equal_pixels(const SkBitmap&, const SkBitmap&, unsigned maxDiff = 0,
|
bool equal_pixels(const SkBitmap&, const SkBitmap&, unsigned maxDiff = 0,
|
||||||
bool respectColorSpaces = false);
|
bool respectColorSpaces = false);
|
||||||
bool equal_pixels(const SkImage* a, const SkImage* b, unsigned maxDiff,
|
bool equal_pixels(const SkImage* a, const SkImage* b, unsigned maxDiff = 0,
|
||||||
bool respectColorSpaces = false);
|
bool respectColorSpaces = false);
|
||||||
|
|
||||||
// private to sk_tool_utils
|
// private to sk_tool_utils
|
||||||
|
Loading…
Reference in New Issue
Block a user