Deserialize pictures with custom image-deserializer

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2187613002

Review-Url: https://codereview.chromium.org/2187613002
This commit is contained in:
reed 2016-08-11 03:55:15 -07:00 committed by Commit bot
parent 286a8657da
commit a9ca05ca5e
13 changed files with 210 additions and 177 deletions

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImageDeserializer_DEFINED
#define SkImageDeserializer_DEFINED
#include "SkRefCnt.h"
struct SkIRect;
class SkData;
class SkImage;
class SK_API SkImageDeserializer {
public:
virtual ~SkImageDeserializer() {}
/**
* Given a data containing serialized content, return an SkImage from it.
*
* @param data The data containing the encoded image. The subclass may ref this for later
* decoding, or read it and process it immediately.
* @param subset Optional rectangle represent the subset of the encoded data that is being
* requested to be turned into an image.
* @return The new image, or nullptr on failure.
*
* The default implementation is to call SkImage::MakeFromEncoded(...)
*/
virtual sk_sp<SkImage> makeFromData(SkData*, const SkIRect* subset);
virtual sk_sp<SkImage> makeFromMemory(const void* data, size_t length, const SkIRect* subset);
};
#endif

View File

@ -16,6 +16,9 @@ class GrContext;
class SkBigPicture;
class SkBitmap;
class SkCanvas;
class SkData;
class SkImage;
class SkImageDeserializer;
class SkPath;
class SkPictureData;
class SkPixelSerializer;
@ -49,6 +52,7 @@ public:
*/
typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst);
#ifdef SK_SUPPORT_LEGACY_PICTUREINSTALLPIXELREF
/**
* Recreate a picture that was serialized into a stream.
* @param SkStream Serialized picture data. Ownership is unchanged by this call.
@ -58,17 +62,18 @@ public:
* invalid.
*/
static sk_sp<SkPicture> MakeFromStream(SkStream*, InstallPixelRefProc proc);
static sk_sp<SkPicture> MakeFromStream(SkStream* stream, std::nullptr_t) {
return MakeFromStream(stream);
}
#endif
/**
* Recreate a picture that was serialized into a stream.
*
* Any serialized images in the stream will be passed to
* SkImageGenerator::NewFromEncoded.
*
* @param SkStream Serialized picture data. Ownership is unchanged by this call.
* @return A new SkPicture representing the serialized data, or NULL if the stream is
* invalid.
* Any serialized images in the stream will be passed the image-deserializer, or if that is
* null, to the default deserializer that will call SkImage::MakeFromEncoded().
*/
static sk_sp<SkPicture> MakeFromStream(SkStream*, SkImageDeserializer*);
static sk_sp<SkPicture> MakeFromStream(SkStream*);
/**
@ -188,7 +193,7 @@ private:
template <typename> friend class SkMiniPicture;
void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet* typefaces) const;
static sk_sp<SkPicture> MakeFromStream(SkStream*, InstallPixelRefProc, SkTypefacePlayback*);
static sk_sp<SkPicture> MakeFromStream(SkStream*, SkImageDeserializer*, SkTypefacePlayback*);
friend class SkPictureData;
virtual int numSlowPaths() const = 0;

View File

@ -6,6 +6,7 @@
*/
#include "SkAtomics.h"
#include "SkImageDeserializer.h"
#include "SkImageGenerator.h"
#include "SkMessageBus.h"
#include "SkPicture.h"
@ -23,6 +24,31 @@ static bool g_AllPictureIOSecurityPrecautionsEnabled = false;
DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage);
#ifdef SK_SUPPORT_LEGACY_PICTUREINSTALLPIXELREF
class InstallProcImageDeserializer : public SkImageDeserializer {
SkPicture::InstallPixelRefProc fProc;
public:
InstallProcImageDeserializer(SkPicture::InstallPixelRefProc proc) : fProc(proc) {}
sk_sp<SkImage> makeFromMemory(const void* data, size_t length, const SkIRect* subset) override {
SkBitmap bitmap;
if (fProc(data, length, &bitmap)) {
bitmap.setImmutable();
return SkImage::MakeFromBitmap(bitmap);
}
return nullptr;
}
sk_sp<SkImage> makeFromData(SkData* data, const SkIRect* subset) override {
return this->makeFromMemory(data->data(), data->size(), subset);
}
};
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, InstallPixelRefProc proc) {
InstallProcImageDeserializer deserializer(proc);
return MakeFromStream(stream, &deserializer);
}
#endif
/* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */
SkPicture::SkPicture() : fUniqueID(0) {}
@ -141,28 +167,23 @@ sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info,
return r.finishRecordingAsPicture();
}
static bool default_install(const void* src, size_t length, SkBitmap* dst) {
sk_sp<SkData> encoded(SkData::MakeWithCopy(src, length));
return encoded && SkDEPRECATED_InstallDiscardablePixelRef(
SkImageGenerator::NewFromEncoded(encoded.get()), dst);
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) {
return MakeFromStream(stream, factory, nullptr);
}
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
return MakeFromStream(stream, &default_install, nullptr);
SkImageDeserializer factory;
return MakeFromStream(stream, &factory);
}
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, InstallPixelRefProc proc) {
return MakeFromStream(stream, proc, nullptr);
}
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, InstallPixelRefProc proc,
sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory,
SkTypefacePlayback* typefaces) {
SkPictInfo info;
if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
return nullptr;
}
SkAutoTDelete<SkPictureData> data(
SkPictureData::CreateFromStream(stream, info, proc, typefaces));
SkPictureData::CreateFromStream(stream, info, factory, typefaces));
return Forwardport(info, data, nullptr);
}

View File

@ -43,7 +43,6 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
fContentInfo.set(record.fContentInfo);
fBitmaps.reset(); // we never make bitmaps (anymore) during recording
fPaints = record.fPaints;
fPaths.reset(record.fPaths.count());
@ -135,7 +134,7 @@ SkPictureData::~SkPictureData() {
}
bool SkPictureData::containsBitmaps() const {
if (fBitmaps.count() > 0 || fImageCount > 0) {
if (fBitmapImageCount > 0 || fImageCount > 0) {
return true;
}
for (int i = 0; i < fPictureCount; ++i) {
@ -223,9 +222,6 @@ void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
int i, n;
// we never record bitmaps anymore, only images
SkASSERT(fBitmaps.count() == 0);
if ((n = fPaints.count()) > 0) {
write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
for (i = 0; i < n; i++) {
@ -361,7 +357,7 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
bool SkPictureData::parseStreamTag(SkStream* stream,
uint32_t tag,
uint32_t size,
SkPicture::InstallPixelRefProc proc,
SkImageDeserializer* factory,
SkTypefacePlayback* topLevelTFPlayback) {
/*
* By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
@ -414,7 +410,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
fPictureCount = 0;
fPictureRefs = new const SkPicture* [size];
for (uint32_t i = 0; i < size; i++) {
fPictureRefs[i] = SkPicture::MakeFromStream(stream, proc, topLevelTFPlayback).release();
fPictureRefs[i] = SkPicture::MakeFromStream(stream, factory, topLevelTFPlayback).release();
if (!fPictureRefs[i]) {
return false;
}
@ -436,7 +432,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
return false;
}
fFactoryPlayback->setupBuffer(buffer);
buffer.setBitmapDecoder(proc);
buffer.setImageDeserializer(factory);
if (fTFPlayback.count() > 0) {
// .skp files <= v43 have typefaces serialized with each sub picture.
@ -463,7 +459,11 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
}
static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) {
return buffer.readImage();
return buffer.readImage().release();
}
static const SkImage* create_bitmap_image_from_buffer(SkReadBuffer& buffer) {
return buffer.readBitmapAsImage().release();
}
// Need a shallow wrapper to return const SkPicture* to match the other factories,
@ -512,18 +512,12 @@ bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
switch (tag) {
case SK_PICT_BITMAP_BUFFER_TAG: {
const int count = SkToInt(size);
fBitmaps.reset(count);
for (int i = 0; i < count; ++i) {
SkBitmap* bm = &fBitmaps[i];
if (buffer.readBitmap(bm)) {
bm->setImmutable();
} else {
case SK_PICT_BITMAP_BUFFER_TAG:
if (!new_array_from_buffer(buffer, size, &fBitmapImageRefs, &fBitmapImageCount,
create_bitmap_image_from_buffer)) {
return false;
}
}
} break;
break;
case SK_PICT_PAINT_BUFFER_TAG: {
const int count = SkToInt(size);
fPaints.reset(count);
@ -581,14 +575,14 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
const SkPictInfo& info,
SkPicture::InstallPixelRefProc proc,
SkImageDeserializer* factory,
SkTypefacePlayback* topLevelTFPlayback) {
SkAutoTDelete<SkPictureData> data(new SkPictureData(info));
if (!topLevelTFPlayback) {
topLevelTFPlayback = &data->fTFPlayback;
}
if (!data->parseStream(stream, proc, topLevelTFPlayback)) {
if (!data->parseStream(stream, factory, topLevelTFPlayback)) {
return nullptr;
}
return data.release();
@ -606,7 +600,7 @@ SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
}
bool SkPictureData::parseStream(SkStream* stream,
SkPicture::InstallPixelRefProc proc,
SkImageDeserializer* factory,
SkTypefacePlayback* topLevelTFPlayback) {
for (;;) {
uint32_t tag = stream->readU32();
@ -615,7 +609,7 @@ bool SkPictureData::parseStream(SkStream* stream,
}
uint32_t size = stream->readU32();
if (!this->parseStreamTag(stream, tag, size, proc, topLevelTFPlayback)) {
if (!this->parseStreamTag(stream, tag, size, factory, topLevelTFPlayback)) {
return false; // we're invalid
}
}

View File

@ -64,7 +64,7 @@ public:
// Does not affect ownership of SkStream.
static SkPictureData* CreateFromStream(SkStream*,
const SkPictInfo&,
SkPicture::InstallPixelRefProc,
SkImageDeserializer*,
SkTypefacePlayback*);
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
@ -85,13 +85,13 @@ protected:
explicit SkPictureData(const SkPictInfo& info);
// Does not affect ownership of SkStream.
bool parseStream(SkStream*, SkPicture::InstallPixelRefProc, SkTypefacePlayback*);
bool parseStream(SkStream*, SkImageDeserializer*, SkTypefacePlayback*);
bool parseBuffer(SkReadBuffer& buffer);
public:
const SkBitmap& getBitmap(SkReadBuffer* reader) const {
const SkImage* getBitmapAsImage(SkReadBuffer* reader) const {
const int index = reader->readInt();
return reader->validateIndex(index, fBitmaps.count()) ? fBitmaps[index] : fEmptyBitmap;
return reader->validateIndex(index, fBitmapImageCount) ? fBitmapImageRefs[index] : nullptr;
}
const SkImage* getImage(SkReadBuffer* reader) const {
@ -149,11 +149,10 @@ private:
// these help us with reading/writing
// Does not affect ownership of SkStream.
bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size,
SkPicture::InstallPixelRefProc, SkTypefacePlayback*);
SkImageDeserializer*, SkTypefacePlayback*);
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
void flattenToBuffer(SkWriteBuffer&) const;
SkTArray<SkBitmap> fBitmaps;
SkTArray<SkPaint> fPaints;
SkTArray<SkPath> fPaths;
@ -170,6 +169,8 @@ private:
int fTextBlobCount;
const SkImage** fImageRefs;
int fImageCount;
const SkImage** fBitmapImageRefs;
int fBitmapImageCount;
SkPictureContentInfo fContentInfo;

View File

@ -80,11 +80,6 @@ void get_text(SkReadBuffer* reader, TextContainer* text) {
text->fText = (const char*)reader->skip(length);
}
// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
static SkBitmap shallow_copy(const SkBitmap& bitmap) {
return bitmap;
}
void SkPicturePlayback::draw(SkCanvas* canvas,
SkPicture::AbortCallback* callback,
const SkReadBuffer* buffer) {
@ -214,39 +209,43 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
} break;
case DRAW_BITMAP: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
const SkImage* image = fPictureData->getBitmapAsImage(reader);
SkPoint loc;
reader->readPoint(&loc);
canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
canvas->drawImage(image, loc.fX, loc.fY, paint);
} break;
case DRAW_BITMAP_RECT: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
const SkImage* image = fPictureData->getBitmapAsImage(reader);
SkRect storage;
const SkRect* src = get_rect_ptr(reader, &storage); // may be null
SkRect dst;
reader->readRect(&dst); // required
SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
canvas->legacy_drawBitmapRect(bitmap, src, dst, paint, constraint);
if (src) {
canvas->drawImageRect(image, *src, dst, paint, constraint);
} else {
canvas->drawImageRect(image, dst, paint, constraint);
}
} break;
case DRAW_BITMAP_MATRIX: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
const SkImage* image = fPictureData->getBitmapAsImage(reader);
SkMatrix matrix;
reader->readMatrix(&matrix);
SkAutoCanvasRestore acr(canvas, true);
canvas->concat(matrix);
canvas->drawBitmap(bitmap, 0, 0, paint);
canvas->drawImage(image, 0, 0, paint);
} break;
case DRAW_BITMAP_NINE: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
const SkImage* image = fPictureData->getBitmapAsImage(reader);
SkIRect src;
reader->readIRect(&src);
SkRect dst;
reader->readRect(&dst);
canvas->drawBitmapNine(bitmap, src, dst, paint);
canvas->drawImageNine(image, src, dst, paint);
} break;
case DRAW_CLEAR:
canvas->clear(reader->readInt());
@ -465,7 +464,7 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
} break;
case DRAW_SPRITE: {
/* const SkPaint* paint = */ fPictureData->getPaint(reader);
/* const SkBitmap bitmap = */ shallow_copy(fPictureData->getBitmap(reader));
/* const SkImage* image = */ fPictureData->getBitmapAsImage(reader);
/* int left = */ reader->readInt();
/* int top = */ reader->readInt();
// drawSprite removed dec-2015

View File

@ -209,20 +209,6 @@ protected:
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
// NEVER CALL -- SkRecord should have already turned these into image draws
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override {
sk_throw();
}
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
SrcRectConstraint) override {
sk_throw();
}
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override {
sk_throw();
}
#ifdef SK_EXPERIMENTAL_SHADOWING
void onDrawShadowedPicture(const SkPicture*,
const SkMatrix*,
@ -252,10 +238,22 @@ protected:
void recordSaveLayer(const SaveLayerRec&);
void recordRestore(bool fillInSkips = true);
// SHOULD NEVER BE CALLED
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override {
sk_throw();
}
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
SrcRectConstraint) override {
sk_throw();
}
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override {
sk_throw();
}
private:
SkPictureContentInfo fContentInfo;
// SkTArray<SkBitmap> fBitmaps;
SkTArray<SkPaint> fPaints;
struct PathHash {

View File

@ -8,11 +8,32 @@
#include "SkBitmap.h"
#include "SkErrorInternals.h"
#include "SkImage.h"
#include "SkImageDeserializer.h"
#include "SkImageGenerator.h"
#include "SkReadBuffer.h"
#include "SkStream.h"
#include "SkTypeface.h"
namespace {
// This generator intentionally should always fail on all attempts to get its pixels,
// simulating a bad or empty codec stream.
class EmptyImageGenerator final : public SkImageGenerator {
public:
EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
private:
typedef SkImageGenerator INHERITED;
};
static sk_sp<SkImage> MakeEmptyImage(int width, int height) {
return SkImage::MakeFromGenerator(
new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height)));
}
} // anonymous namespace
static uint32_t default_flags() {
uint32_t flags = 0;
flags |= SkReadBuffer::kScalarIsFloat_Flag;
@ -22,6 +43,9 @@ static uint32_t default_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() {
fFlags = default_flags();
fVersion = 0;
@ -32,7 +56,7 @@ SkReadBuffer::SkReadBuffer() {
fFactoryArray = nullptr;
fFactoryCount = 0;
fBitmapDecoder = nullptr;
fImageDeserializer = &gDefaultImageDeserializer;
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
fDecodedBitmapIndex = -1;
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
@ -49,7 +73,7 @@ SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
fFactoryArray = nullptr;
fFactoryCount = 0;
fBitmapDecoder = nullptr;
fImageDeserializer = &gDefaultImageDeserializer;
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
fDecodedBitmapIndex = -1;
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
@ -68,7 +92,7 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
fFactoryArray = nullptr;
fFactoryCount = 0;
fBitmapDecoder = nullptr;
fImageDeserializer = &gDefaultImageDeserializer;
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
fDecodedBitmapIndex = -1;
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
@ -78,6 +102,10 @@ SkReadBuffer::~SkReadBuffer() {
sk_free(fMemoryPtr);
}
void SkReadBuffer::setImageDeserializer(SkImageDeserializer* deserializer) {
fImageDeserializer = deserializer ? deserializer : &gDefaultImageDeserializer;
}
bool SkReadBuffer::readBool() {
return fReader.readBool();
}
@ -179,7 +207,7 @@ uint32_t SkReadBuffer::getArrayCount() {
return *(uint32_t*)fReader.peek();
}
bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
sk_sp<SkImage> SkReadBuffer::readBitmapAsImage() {
const int width = this->readInt();
const int height = this->readInt();
@ -203,39 +231,12 @@ bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
const void* data = this->skip(length);
const int32_t xOffset = this->readInt();
const int32_t yOffset = this->readInt();
if (fBitmapDecoder != nullptr && fBitmapDecoder(data, length, bitmap)) {
if (bitmap->width() == width && bitmap->height() == height) {
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
if (0 != xOffset || 0 != yOffset) {
SkDebugf("SkReadBuffer::readBitmap: heights match,"
" but offset is not zero. \nInfo about the bitmap:"
"\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded"
" data size: %d\n\tOffset: (%d, %d)\n",
fDecodedBitmapIndex, width, height, length, xOffset,
yOffset);
}
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
// If the width and height match, there should be no offset.
SkASSERT(0 == xOffset && 0 == yOffset);
return true;
}
// This case can only be reached if extractSubset was called, so
// the recorded width and height must be smaller than or equal to
// the encoded width and height.
// FIXME (scroggo): This assert assumes that our decoder and the
// sources encoder agree on the width and height which may not
// always be the case. Removing until it can be investigated
// further.
//SkASSERT(width <= bitmap->width() && height <= bitmap->height());
SkBitmap subsetBm;
SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height);
if (bitmap->extractSubset(&subsetBm, subset)) {
bitmap->swap(subsetBm);
return true;
}
sk_sp<SkImage> image = fImageDeserializer->makeFromMemory(data, length, &subset);
if (image) {
return image;
}
// This bitmap was encoded when written, but we are unable to decode, possibly due to
// not having a decoder.
SkErrorInternals::SetError(kParseError_SkError,
@ -243,32 +244,20 @@ bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
// Even though we weren't able to decode the pixels, the readbuffer should still be
// intact, so we return true with an empty bitmap, so we don't force an abort of the
// larger deserialize.
bitmap->setInfo(SkImageInfo::MakeUnknown(width, height));
return true;
} else if (SkBitmap::ReadRawPixels(this, bitmap)) {
return true;
return MakeEmptyImage(width, height);
} else {
SkBitmap bitmap;
if (SkBitmap::ReadRawPixels(this, &bitmap)) {
bitmap.setImmutable();
return SkImage::MakeFromBitmap(bitmap);
}
}
}
// Could not read the SkBitmap. Use a placeholder bitmap.
bitmap->setInfo(SkImageInfo::MakeUnknown(width, height));
return false;
return nullptr;
}
namespace {
// This generator intentionally should always fail on all attempts to get its pixels,
// simulating a bad or empty codec stream.
class EmptyImageGenerator final : public SkImageGenerator {
public:
EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
private:
typedef SkImageGenerator INHERITED;
};
} // anonymous namespace
SkImage* SkReadBuffer::readImage() {
sk_sp<SkImage> SkReadBuffer::readImage() {
int width = this->read32();
int height = this->read32();
if (width <= 0 || height <= 0) { // SkImage never has a zero dimension
@ -276,25 +265,20 @@ SkImage* SkReadBuffer::readImage() {
return nullptr;
}
auto placeholder = [=] {
return SkImage::MakeFromGenerator(
new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height))).release();
};
uint32_t encoded_size = this->getArrayCount();
if (encoded_size == 0) {
// The image could not be encoded at serialization time - return an empty placeholder.
(void)this->readUInt(); // Swallow that encoded_size == 0 sentinel.
return placeholder();
return MakeEmptyImage(width, height);
}
if (encoded_size == 1) {
// We had to encode the image as raw pixels via SkBitmap.
(void)this->readUInt(); // Swallow that encoded_size == 1 sentinel.
SkBitmap bm;
if (SkBitmap::ReadRawPixels(this, &bm)) {
return SkImage::MakeFromBitmap(bm).release();
return SkImage::MakeFromBitmap(bm);
}
return placeholder();
return MakeEmptyImage(width, height);
}
// The SkImage encoded itself.
@ -308,13 +292,9 @@ SkImage* SkReadBuffer::readImage() {
}
const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height);
SkImage* image = SkImage::MakeFromEncoded(std::move(encoded), &subset).release();
if (image) {
return image;
}
return SkImage::MakeFromGenerator(
new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height))).release();
sk_sp<SkImage> image = fImageDeserializer->makeFromData(encoded.get(), &subset);
return image ? image : MakeEmptyImage(width, height);
}
SkTypeface* SkReadBuffer::readTypeface() {

View File

@ -167,12 +167,11 @@ public:
virtual uint32_t getArrayCount();
/**
* Returns false if the bitmap could not be completely read. In that case, it will be set
* Returns false if the image could not be completely read. In that case, it will be set
* to have width/height, but no pixels.
*/
bool readBitmap(SkBitmap* bitmap);
SkImage* readImage();
sk_sp<SkImage> readBitmapAsImage();
sk_sp<SkImage> readImage();
virtual SkTypeface* readTypeface();
@ -204,14 +203,9 @@ public:
fCustomFactory.set(name, factory);
}
/**
* Provide a function to decode an SkBitmap from encoded data. Only used if the writer
* encoded the SkBitmap. If the proper decoder cannot be used, a red bitmap with the
* appropriate size will be used.
*/
void setBitmapDecoder(SkPicture::InstallPixelRefProc bitmapDecoder) {
fBitmapDecoder = bitmapDecoder;
}
// If nullptr is passed, then the default deserializer will be used
// which calls SkImage::MakeFromEncoded()
void setImageDeserializer(SkImageDeserializer* factory);
// Default impelementations don't check anything.
virtual bool validate(bool isValid) { return isValid; }
@ -228,7 +222,6 @@ protected:
*/
int factoryCount() { return fFactoryCount; }
/**
* Checks if a custom factory has been set for a given flattenable.
* Returns the custom factory if it exists, or nullptr otherwise.
@ -260,7 +253,8 @@ private:
// Only used if we do not have an fFactoryArray.
SkTHashMap<SkString, SkFlattenable::Factory> fCustomFactory;
SkPicture::InstallPixelRefProc fBitmapDecoder;
// We do not own this ptr, we just use it (guaranteed to never be null)
SkImageDeserializer* fImageDeserializer;
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
// Debugging counter to keep track of how many bitmaps we

View File

@ -500,3 +500,14 @@ sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&, const GrMip
int mipLevelCount, SkBudgeted) {
return nullptr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkImageDeserializer.h"
sk_sp<SkImage> SkImageDeserializer::makeFromData(SkData* data, const SkIRect* subset) {
return SkImage::MakeFromEncoded(sk_ref_sp(data), subset);
}
sk_sp<SkImage> SkImageDeserializer::makeFromMemory(const void* data, size_t length,
const SkIRect* subset) {
return SkImage::MakeFromEncoded(SkData::MakeWithCopy(data, length), subset);
}

View File

@ -27,11 +27,11 @@ sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) {
const TileMode ty = (TileMode)buffer.readUInt();
SkMatrix matrix;
buffer.readMatrix(&matrix);
SkAutoTUnref<SkImage> img(buffer.readImage());
sk_sp<SkImage> img = buffer.readImage();
if (!img) {
return nullptr;
}
return SkImageShader::Make(img, tx, ty, &matrix);
return SkImageShader::Make(img.release(), tx, ty, &matrix);
}
void SkImageShader::flatten(SkWriteBuffer& buffer) const {
@ -248,14 +248,10 @@ sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
static sk_sp<SkFlattenable> SkBitmapProcShader_CreateProc(SkReadBuffer& buffer) {
SkMatrix lm;
buffer.readMatrix(&lm);
SkBitmap bm;
if (!buffer.readBitmap(&bm)) {
return nullptr;
}
bm.setImmutable();
sk_sp<SkImage> image = buffer.readBitmapAsImage();
SkShader::TileMode mx = (SkShader::TileMode)buffer.readUInt();
SkShader::TileMode my = (SkShader::TileMode)buffer.readUInt();
return SkShader::MakeBitmapShader(bm, mx, my, &lm);
return image ? image->makeShader(mx, my, &lm) : nullptr;
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShader)

View File

@ -23,11 +23,9 @@ sk_sp<SkFlattenable> SkBitmapSourceDeserializer::CreateProc(SkReadBuffer& buffer
SkRect src, dst;
buffer.readRect(&src);
buffer.readRect(&dst);
SkBitmap bitmap;
if (!buffer.readBitmap(&bitmap)) {
return nullptr;
sk_sp<SkImage> image = buffer.readBitmapAsImage();
if (image) {
return SkImageSource::Make(std::move(image), src, dst, filterQuality);
}
bitmap.setImmutable();
return SkImageSource::Make(SkImage::MakeFromBitmap(bitmap), src, dst, filterQuality);
return nullptr;
}

View File

@ -691,7 +691,7 @@ DEF_TEST(Picture_EncodedData, reporter) {
SkSetErrorCallback(assert_one_parse_error_cb, &context);
SkMemoryStream pictureStream(std::move(picture1));
SkClearLastError();
sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream, nullptr));
sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream));
REPORTER_ASSERT(reporter, pictureFromStream.get() != nullptr);
SkClearLastError();
SkSetErrorCallback(nullptr, nullptr);