зеркало из https://github.com/mozilla/moz-skia.git
Add the ability to provide function pointers to SkPicture serialization
and deserialization for encoding and decoding bitmaps. Remove kForceFlattenBitmapPixels_Flag, which is no longer used. When an SkOrderedReadBuffer needs to read a bitmap, if it does not have an image decoder, use a dummy bitmap. In GM, add a tolerance option for color differences, used when testing picture serialization, so it can assume two images are the same even though PNG encoding/decoding may have resulted in small differences. Create dummy implementations for SkImageDecoder and SkImageEncoder functions in SkImageDecoder_empty so that a project that does not want to include the images project it can still build. Allow ports to build without images project. In Mac's image encoder, copy 4444 to 8888 before encoding. Add SkWriter32::reservePad, to provide a pointer to write non 4 byte aligned data, padded with zeroes. In bench_ and render_ pictures, pass decode function to SkPicture creation from a stream. BUG=https://code.google.com/p/skia/issues/detail?id=842 Review URL: https://codereview.appspot.com/6551071 git-svn-id: http://skia.googlecode.com/svn/trunk@5818 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
94bc60f986
Коммит
5a7c6be72b
|
@ -171,7 +171,7 @@ static void compute_diff(const SkBitmap& target, const SkBitmap& base,
|
|||
static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
|
||||
const SkString& name,
|
||||
const char* renderModeDescriptor,
|
||||
SkBitmap* diff) {
|
||||
SkBitmap* diff, uint32_t tolerance) {
|
||||
SkBitmap copy;
|
||||
const SkBitmap* bm = ⌖
|
||||
if (target.config() != SkBitmap::kARGB_8888_Config) {
|
||||
|
@ -206,16 +206,20 @@ static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
|
|||
SkPMColor c0 = *bp->getAddr32(x, y);
|
||||
SkPMColor c1 = *bm->getAddr32(x, y);
|
||||
if (c0 != c1) {
|
||||
SkDebugf(
|
||||
SkPMColor trueDiff = compute_diff_pmcolor(c0, c1);
|
||||
if (SkGetPackedR32(trueDiff) > tolerance || SkGetPackedG32(trueDiff) > tolerance
|
||||
|| SkGetPackedB32(trueDiff) > tolerance) {
|
||||
SkDebugf(
|
||||
"----- %s pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
|
||||
renderModeDescriptor, name.c_str(), x, y, c0, c1);
|
||||
|
||||
if (diff) {
|
||||
diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
diff->allocPixels();
|
||||
compute_diff(*bm, *bp, diff);
|
||||
if (diff) {
|
||||
diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
diff->allocPixels();
|
||||
compute_diff(*bm, *bp, diff);
|
||||
}
|
||||
return ERROR_PIXEL_MISMATCH;
|
||||
}
|
||||
return ERROR_PIXEL_MISMATCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -438,11 +442,12 @@ static ErrorBitfield compare_to_reference_image(const SkString& name,
|
|||
SkBitmap &bitmap,
|
||||
const SkBitmap& comparisonBitmap,
|
||||
const char diffPath [],
|
||||
const char renderModeDescriptor []) {
|
||||
const char renderModeDescriptor [],
|
||||
uint32_t tolerance = 0) {
|
||||
ErrorBitfield errors;
|
||||
SkBitmap diffBitmap;
|
||||
errors = compare(bitmap, comparisonBitmap, name, renderModeDescriptor,
|
||||
diffPath ? &diffBitmap : NULL);
|
||||
diffPath ? &diffBitmap : NULL, tolerance);
|
||||
if ((ERROR_NONE != errors) && diffPath) {
|
||||
// write out the generated image
|
||||
SkString genName = make_filename(diffPath, "", name, "png");
|
||||
|
@ -482,7 +487,8 @@ static ErrorBitfield handle_test_results(GM* gm,
|
|||
const char renderModeDescriptor [],
|
||||
SkBitmap& bitmap,
|
||||
SkDynamicMemoryWStream* pdf,
|
||||
const SkBitmap* comparisonBitmap) {
|
||||
const SkBitmap* comparisonBitmap,
|
||||
uint32_t tolerance = 0) {
|
||||
SkString name = make_name(gm->shortName(), gRec.fName);
|
||||
ErrorBitfield retval = ERROR_NONE;
|
||||
|
||||
|
@ -497,7 +503,7 @@ static ErrorBitfield handle_test_results(GM* gm,
|
|||
if (comparisonBitmap) {
|
||||
retval |= compare_to_reference_image(name, bitmap,
|
||||
*comparisonBitmap, diffPath,
|
||||
renderModeDescriptor);
|
||||
renderModeDescriptor, tolerance);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
@ -513,6 +519,10 @@ static SkPicture* generate_new_picture(GM* gm) {
|
|||
return pict;
|
||||
}
|
||||
|
||||
static bool EncodeBitmap(SkWStream* wStream, const SkBitmap& bitmap) {
|
||||
return SkImageEncoder::EncodeStream(wStream, bitmap, SkImageEncoder::kPNG_Type, 100);
|
||||
}
|
||||
|
||||
static SkPicture* stream_to_new_picture(const SkPicture& src) {
|
||||
|
||||
// To do in-memory commiunications with a stream, we need to:
|
||||
|
@ -522,7 +532,7 @@ static SkPicture* stream_to_new_picture(const SkPicture& src) {
|
|||
// ?!?!
|
||||
|
||||
SkDynamicMemoryWStream storage;
|
||||
src.serialize(&storage);
|
||||
src.serialize(&storage, &EncodeBitmap);
|
||||
|
||||
int streamSize = storage.getOffset();
|
||||
SkAutoMalloc dstStorage(streamSize);
|
||||
|
@ -531,7 +541,7 @@ static SkPicture* stream_to_new_picture(const SkPicture& src) {
|
|||
//@todo thudson 22 April 2011 when can we safely delete [] dst?
|
||||
storage.copyTo(dst);
|
||||
SkMemoryStream pictReadback(dst, streamSize);
|
||||
SkPicture* retval = new SkPicture (&pictReadback);
|
||||
SkPicture* retval = SkNEW_ARGS(SkPicture, (&pictReadback, NULL, &SkImageDecoder::DecodeStream));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -623,8 +633,11 @@ static ErrorBitfield test_picture_serialization(GM* gm,
|
|||
if (kRaster_Backend == gRec.fBackend) {
|
||||
SkBitmap bitmap;
|
||||
generate_image_from_picture(gm, gRec, repict, &bitmap);
|
||||
// Allow for slight differences in color due to PNG encoding bitmaps, which does not restore
|
||||
// our premultiplied alpha properly.
|
||||
static const uint32_t tolerance = 50;
|
||||
return handle_test_results(gm, gRec, NULL, NULL, diffPath,
|
||||
"-serialize", bitmap, NULL, &comparisonBitmap);
|
||||
"-serialize", bitmap, NULL, &comparisonBitmap, tolerance);
|
||||
} else {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
'../src/images/SkImageRefPool.cpp',
|
||||
'../src/images/SkImageRefPool.h',
|
||||
'../src/images/SkImageRef_GlobalPool.cpp',
|
||||
'../src/images/SkImages.cpp',
|
||||
'../src/images/SkJpegUtility.cpp',
|
||||
'../src/images/SkMovie.cpp',
|
||||
'../src/images/SkMovie_gif.cpp',
|
||||
|
|
|
@ -154,11 +154,6 @@ public:
|
|||
|
||||
enum Flags {
|
||||
kCrossProcess_Flag = 0x01,
|
||||
|
||||
/**
|
||||
* Instructs the writer to always serialize bitmap pixel data.
|
||||
*/
|
||||
kForceFlattenBitmapPixels_Flag = 0x04,
|
||||
};
|
||||
|
||||
uint32_t getFlags() const { return fFlags; }
|
||||
|
@ -168,10 +163,6 @@ public:
|
|||
return SkToBool(fFlags & kCrossProcess_Flag);
|
||||
}
|
||||
|
||||
bool persistBitmapPixels() const {
|
||||
return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0;
|
||||
}
|
||||
|
||||
bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define SkPicture_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkSerializationHelpers.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkCanvas;
|
||||
|
@ -40,8 +41,10 @@ public:
|
|||
/**
|
||||
* Recreate a picture that was serialized into a stream. *success is set to
|
||||
* true if the picture was deserialized successfully and false otherwise.
|
||||
* decoder is used to decode any SkBitmaps that were encoded into the stream.
|
||||
*/
|
||||
explicit SkPicture(SkStream*, bool* success = NULL);
|
||||
explicit SkPicture(SkStream*, bool* success = NULL,
|
||||
SkSerializationHelpers::DecodeBitmap decoder = NULL);
|
||||
virtual ~SkPicture();
|
||||
|
||||
/**
|
||||
|
@ -132,7 +135,11 @@ public:
|
|||
*/
|
||||
int height() const { return fHeight; }
|
||||
|
||||
void serialize(SkWStream*) const;
|
||||
/**
|
||||
* Serialize to a stream. If non NULL, encoder will be used to encode
|
||||
* any bitmaps in the picture.
|
||||
*/
|
||||
void serialize(SkWStream*, SkSerializationHelpers::EncodeBitmap encoder = NULL) const;
|
||||
|
||||
/** Signals that the caller is prematurely done replaying the drawing
|
||||
commands. This can be called from a canvas virtual while the picture
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkSerializationHelpers_DEFINED
|
||||
#define SkSerializationHelpers_DEFINED
|
||||
|
||||
class SkBitmap;
|
||||
class SkStream;
|
||||
class SkWStream;
|
||||
|
||||
namespace SkSerializationHelpers {
|
||||
/**
|
||||
* Function to encode an SkBitmap to an SkWStream. A function with this signature can be passed
|
||||
* to SkPicture::serialize() and SkOrderedWriteBuffer. The function should return true if it
|
||||
* succeeds. Otherwise it should return false so that SkOrderedWriteBuffer can switch to
|
||||
* another method of storing SkBitmaps.
|
||||
*/
|
||||
typedef bool (*EncodeBitmap)(SkWStream*, const SkBitmap&);
|
||||
|
||||
/**
|
||||
* Function to decode an SkBitmap from an SkStream. A function with this signature can be
|
||||
* passed to the SkStream constructor for SkPicture and SkOrderedReadBuffer to decode SkBitmaps
|
||||
* which were previously encoded. The function should return true if it succeeds. Otherwise it
|
||||
* should return false so that SkOrderedReadBuffer can skip the data and provide a dummy
|
||||
* SkBitmap.
|
||||
*/
|
||||
typedef bool (*DecodeBitmap)(SkStream*, SkBitmap*);
|
||||
}
|
||||
|
||||
#endif // SkSerializationHelpers_DEFINED
|
|
@ -143,6 +143,15 @@ public:
|
|||
memcpy(this->reserve(size), values, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
|
||||
* filled in with zeroes.
|
||||
*/
|
||||
uint32_t* reservePad(size_t size);
|
||||
|
||||
/**
|
||||
* Write size bytes from src, and pad to 4 byte alignment with zeroes.
|
||||
*/
|
||||
void writePad(const void* src, size_t size);
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
class SkImages {
|
||||
public:
|
||||
/**
|
||||
* Initializes flattenables in the images project.
|
||||
*/
|
||||
static void InitializeFlattenables();
|
||||
};
|
|
@ -20,6 +20,7 @@ SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() {
|
|||
fFactoryTDArray = NULL;
|
||||
fFactoryArray = NULL;
|
||||
fFactoryCount = 0;
|
||||
fBitmapDecoder = NULL;
|
||||
}
|
||||
|
||||
SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() {
|
||||
|
@ -33,6 +34,7 @@ SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERI
|
|||
fFactoryTDArray = NULL;
|
||||
fFactoryArray = NULL;
|
||||
fFactoryCount = 0;
|
||||
fBitmapDecoder = NULL;
|
||||
}
|
||||
|
||||
SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
|
||||
|
@ -48,6 +50,7 @@ SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
|
|||
fFactoryTDArray = NULL;
|
||||
fFactoryArray = NULL;
|
||||
fFactoryCount = 0;
|
||||
fBitmapDecoder = NULL;
|
||||
}
|
||||
|
||||
SkOrderedReadBuffer::~SkOrderedReadBuffer() {
|
||||
|
@ -164,12 +167,31 @@ uint32_t SkOrderedReadBuffer::getArrayCount() {
|
|||
}
|
||||
|
||||
void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
|
||||
if (fBitmapStorage) {
|
||||
const uint32_t index = fReader.readU32();
|
||||
*bitmap = *fBitmapStorage->getBitmap(index);
|
||||
fBitmapStorage->releaseRef(index);
|
||||
size_t length = this->readUInt();
|
||||
if (length > 0) {
|
||||
// Bitmap was encoded.
|
||||
SkMemoryStream stream(const_cast<void*>(this->skip(length)), length, false);
|
||||
if (fBitmapDecoder != NULL && fBitmapDecoder(&stream, bitmap)) {
|
||||
// Skip the width and height, which were written in case of failure.
|
||||
fReader.skip(2 * sizeof(int));
|
||||
} else {
|
||||
// This bitmap was encoded when written, but we are unable to decode, possibly due to
|
||||
// not having a decoder. Use a placeholder bitmap.
|
||||
SkDebugf("Could not decode bitmap. Resulting bitmap will be red.\n");
|
||||
int width = this->readInt();
|
||||
int height = this->readInt();
|
||||
bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
||||
bitmap->allocPixels();
|
||||
bitmap->eraseColor(SK_ColorRED);
|
||||
}
|
||||
} else {
|
||||
bitmap->unflatten(*this);
|
||||
if (fBitmapStorage) {
|
||||
const uint32_t index = fReader.readU32();
|
||||
*bitmap = *fBitmapStorage->getBitmap(index);
|
||||
fBitmapStorage->releaseRef(index);
|
||||
} else {
|
||||
bitmap->unflatten(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
#include "SkBitmap.h"
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkFlattenableBuffers.h"
|
||||
#include "SkReader32.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkReader32.h"
|
||||
#include "SkSerializationHelpers.h"
|
||||
|
||||
class SkOrderedReadBuffer : public SkFlattenableReadBuffer {
|
||||
public:
|
||||
|
@ -97,6 +98,15 @@ public:
|
|||
fFactoryCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a function to decode an SkBitmap from an SkStream. 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(SkSerializationHelpers::DecodeBitmap bitmapDecoder) {
|
||||
fBitmapDecoder = bitmapDecoder;
|
||||
}
|
||||
|
||||
private:
|
||||
SkReader32 fReader;
|
||||
void* fMemoryPtr;
|
||||
|
@ -109,6 +119,8 @@ private:
|
|||
SkFlattenable::Factory* fFactoryArray;
|
||||
int fFactoryCount;
|
||||
|
||||
SkSerializationHelpers::DecodeBitmap fBitmapDecoder;
|
||||
|
||||
typedef SkFlattenableReadBuffer INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "SkOrderedWriteBuffer.h"
|
||||
#include "SkPtrRecorder.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTypeface.h"
|
||||
|
||||
SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
|
||||
|
@ -16,7 +17,8 @@ SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
|
|||
, fNamedFactorySet(NULL)
|
||||
, fWriter(minSize)
|
||||
, fBitmapHeap(NULL)
|
||||
, fTFSet(NULL) {
|
||||
, fTFSet(NULL)
|
||||
, fBitmapEncoder(NULL) {
|
||||
}
|
||||
|
||||
SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize)
|
||||
|
@ -25,7 +27,8 @@ SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t
|
|||
, fNamedFactorySet(NULL)
|
||||
, fWriter(minSize, storage, storageSize)
|
||||
, fBitmapHeap(NULL)
|
||||
, fTFSet(NULL) {
|
||||
, fTFSet(NULL)
|
||||
, fBitmapEncoder(NULL) {
|
||||
}
|
||||
|
||||
SkOrderedWriteBuffer::~SkOrderedWriteBuffer() {
|
||||
|
@ -134,10 +137,37 @@ bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) {
|
|||
}
|
||||
|
||||
void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
||||
if (fBitmapHeap) {
|
||||
fWriter.write32(fBitmapHeap->insert(bitmap));
|
||||
} else {
|
||||
bitmap.flatten(*this);
|
||||
bool encoded = false;
|
||||
if (fBitmapEncoder != NULL) {
|
||||
SkDynamicMemoryWStream pngStream;
|
||||
if (fBitmapEncoder(&pngStream, bitmap)) {
|
||||
encoded = true;
|
||||
if (encoded) {
|
||||
uint32_t offset = fWriter.bytesWritten();
|
||||
// Write the length to indicate that the bitmap was encoded successfully.
|
||||
size_t length = pngStream.getOffset();
|
||||
this->writeUInt(length);
|
||||
// Now write the stream.
|
||||
if (pngStream.read(fWriter.reservePad(length), 0, length)) {
|
||||
// Write the width and height in case the reader does not have a decoder.
|
||||
this->writeInt(bitmap.width());
|
||||
this->writeInt(bitmap.height());
|
||||
} else {
|
||||
// Writing the stream failed, so go back to original state to store another way.
|
||||
fWriter.rewindToOffset(offset);
|
||||
encoded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!encoded) {
|
||||
// Bitmap was not encoded. Record a zero, implying that the reader need not decode.
|
||||
this->writeUInt(0);
|
||||
if (fBitmapHeap) {
|
||||
fWriter.write32(fBitmapHeap->insert(bitmap));
|
||||
} else {
|
||||
bitmap.flatten(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "SkBitmap.h"
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkSerializationHelpers.h"
|
||||
#include "SkWriter32.h"
|
||||
|
||||
class SkFlattenable;
|
||||
|
@ -78,6 +79,16 @@ public:
|
|||
SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a function to encode an SkBitmap to an SkStream. writeBitmap will attempt to use
|
||||
* bitmapEncoder to store the SkBitmap. Takes priority over the SkBitmapHeap. If the reader does
|
||||
* not provide a function to decode, it will not be able to restore SkBitmaps, but will still be
|
||||
* able to read the rest of the stream.
|
||||
*/
|
||||
void setBitmapEncoder(SkSerializationHelpers::EncodeBitmap bitmapEncoder) {
|
||||
fBitmapEncoder = bitmapEncoder;
|
||||
}
|
||||
|
||||
private:
|
||||
SkFactorySet* fFactorySet;
|
||||
SkNamedFactorySet* fNamedFactorySet;
|
||||
|
@ -86,6 +97,8 @@ private:
|
|||
SkBitmapHeap* fBitmapHeap;
|
||||
SkRefCntSet* fTFSet;
|
||||
|
||||
SkSerializationHelpers::EncodeBitmap fBitmapEncoder;
|
||||
|
||||
typedef SkFlattenableWriteBuffer INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -243,9 +243,10 @@ void SkPicture::draw(SkCanvas* surface) {
|
|||
// V5 : don't read/write FunctionPtr on cross-process (we can detect that)
|
||||
// V6 : added serialization of SkPath's bounds (and packed its flags tighter)
|
||||
// V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect)
|
||||
#define PICTURE_VERSION 7
|
||||
// V8 : PNG encode bitmaps
|
||||
#define PICTURE_VERSION 8
|
||||
|
||||
SkPicture::SkPicture(SkStream* stream, bool* success) : SkRefCnt() {
|
||||
SkPicture::SkPicture(SkStream* stream, bool* success, SkSerializationHelpers::DecodeBitmap decoder) : SkRefCnt() {
|
||||
if (success) {
|
||||
*success = false;
|
||||
}
|
||||
|
@ -264,7 +265,7 @@ SkPicture::SkPicture(SkStream* stream, bool* success) : SkRefCnt() {
|
|||
|
||||
if (stream->readBool()) {
|
||||
bool isValid = false;
|
||||
fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream, info, &isValid));
|
||||
fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream, info, &isValid, decoder));
|
||||
if (!isValid) {
|
||||
SkDELETE(fPlayback);
|
||||
fPlayback = NULL;
|
||||
|
@ -280,7 +281,7 @@ SkPicture::SkPicture(SkStream* stream, bool* success) : SkRefCnt() {
|
|||
}
|
||||
}
|
||||
|
||||
void SkPicture::serialize(SkWStream* stream) const {
|
||||
void SkPicture::serialize(SkWStream* stream, SkSerializationHelpers::EncodeBitmap encoder) const {
|
||||
SkPicturePlayback* playback = fPlayback;
|
||||
|
||||
if (NULL == playback && fRecord) {
|
||||
|
@ -303,7 +304,7 @@ void SkPicture::serialize(SkWStream* stream) const {
|
|||
stream->write(&info, sizeof(info));
|
||||
if (playback) {
|
||||
stream->writeBool(true);
|
||||
playback->serialize(stream);
|
||||
playback->serialize(stream, encoder);
|
||||
// delete playback if it is a local version (i.e. cons'd up just now)
|
||||
if (playback != fPlayback) {
|
||||
SkDELETE(playback);
|
||||
|
|
|
@ -364,7 +364,8 @@ void SkPicturePlayback::flattenToBuffer(SkOrderedWriteBuffer& buffer) const {
|
|||
}
|
||||
}
|
||||
|
||||
void SkPicturePlayback::serialize(SkWStream* stream) const {
|
||||
void SkPicturePlayback::serialize(SkWStream* stream,
|
||||
SkSerializationHelpers::EncodeBitmap encoder) const {
|
||||
writeTagSize(stream, PICT_READER_TAG, fOpData->size());
|
||||
stream->write(fOpData->bytes(), fOpData->size());
|
||||
|
||||
|
@ -386,6 +387,7 @@ void SkPicturePlayback::serialize(SkWStream* stream) const {
|
|||
buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
|
||||
buffer.setTypefaceRecorder(&typefaceSet);
|
||||
buffer.setFactoryRecorder(&factSet);
|
||||
buffer.setBitmapEncoder(encoder);
|
||||
|
||||
this->flattenToBuffer(buffer);
|
||||
|
||||
|
@ -428,7 +430,8 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
|
|||
}
|
||||
|
||||
bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
|
||||
uint32_t tag, size_t size) {
|
||||
uint32_t tag, size_t size,
|
||||
SkSerializationHelpers::DecodeBitmap decoder) {
|
||||
/*
|
||||
* 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
|
||||
|
@ -481,6 +484,7 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
|
|||
|
||||
fFactoryPlayback->setupBuffer(buffer);
|
||||
fTFPlayback.setupBuffer(buffer);
|
||||
buffer.setBitmapDecoder(decoder);
|
||||
|
||||
while (!buffer.eof()) {
|
||||
tag = buffer.readUInt();
|
||||
|
@ -532,7 +536,7 @@ bool SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
|
|||
}
|
||||
|
||||
SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
|
||||
bool* isValid) {
|
||||
bool* isValid, SkSerializationHelpers::DecodeBitmap decoder) {
|
||||
this->init();
|
||||
|
||||
*isValid = false; // wait until we're done parsing to mark as true
|
||||
|
@ -543,7 +547,7 @@ SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
|
|||
}
|
||||
|
||||
uint32_t size = stream->readU32();
|
||||
if (!this->parseStreamTag(stream, info, tag, size)) {
|
||||
if (!this->parseStreamTag(stream, info, tag, size, decoder)) {
|
||||
return; // we're invalid
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "SkPathHeap.h"
|
||||
#include "SkRegion.h"
|
||||
#include "SkPictureFlat.h"
|
||||
#include "SkSerializationHelpers.h"
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
#include "SkThread.h"
|
||||
|
@ -61,13 +62,14 @@ public:
|
|||
SkPicturePlayback();
|
||||
SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL);
|
||||
explicit SkPicturePlayback(const SkPictureRecord& record, bool deepCopy = false);
|
||||
SkPicturePlayback(SkStream*, const SkPictInfo&, bool* isValid);
|
||||
SkPicturePlayback(SkStream*, const SkPictInfo&, bool* isValid,
|
||||
SkSerializationHelpers::DecodeBitmap decoder);
|
||||
|
||||
virtual ~SkPicturePlayback();
|
||||
|
||||
void draw(SkCanvas& canvas);
|
||||
|
||||
void serialize(SkWStream*) const;
|
||||
void serialize(SkWStream*, SkSerializationHelpers::EncodeBitmap) const;
|
||||
|
||||
void dumpSize() const;
|
||||
|
||||
|
@ -176,7 +178,8 @@ public:
|
|||
#endif
|
||||
|
||||
private: // these help us with reading/writing
|
||||
bool parseStreamTag(SkStream*, const SkPictInfo&, uint32_t tag, size_t size);
|
||||
bool parseStreamTag(SkStream*, const SkPictInfo&, uint32_t tag, size_t size,
|
||||
SkSerializationHelpers::DecodeBitmap decoder);
|
||||
bool parseBufferTag(SkOrderedReadBuffer&, uint32_t tag, size_t size);
|
||||
void flattenToBuffer(SkOrderedWriteBuffer&) const;
|
||||
|
||||
|
|
|
@ -226,14 +226,21 @@ void SkWriter32::flatten(void* dst) const {
|
|||
SkASSERT(total == fSize);
|
||||
}
|
||||
|
||||
void SkWriter32::writePad(const void* src, size_t size) {
|
||||
uint32_t* SkWriter32::reservePad(size_t size) {
|
||||
if (size > 0) {
|
||||
size_t alignedSize = SkAlign4(size);
|
||||
char* dst = (char*)this->reserve(alignedSize);
|
||||
// Pad the last four bytes with zeroes in one step. Some (or all) will
|
||||
// be overwritten by the memcpy.
|
||||
// Pad the last four bytes with zeroes in one step.
|
||||
uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4));
|
||||
*padding = 0;
|
||||
return (uint32_t*) dst;
|
||||
}
|
||||
return this->reserve(0);
|
||||
}
|
||||
|
||||
void SkWriter32::writePad(const void* src, size_t size) {
|
||||
if (size > 0) {
|
||||
char* dst = (char*)this->reservePad(size);
|
||||
// Copy the actual data.
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkFlattenable.h"
|
||||
#include "SkFlipPixelRef.h"
|
||||
#include "SkImageRef_GlobalPool.h"
|
||||
#include "SkImages.h"
|
||||
|
||||
void SkImages::InitializeFlattenables() {
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkFlipPixelRef)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_GlobalPool)
|
||||
}
|
|
@ -8,9 +8,7 @@
|
|||
#include "SkTypes.h"
|
||||
|
||||
#include "SkBitmapProcShader.h"
|
||||
#include "SkFlipPixelRef.h"
|
||||
#include "SkImageRef_ashmem.h"
|
||||
#include "SkImageRef_GlobalPool.h"
|
||||
#include "SkMallocPixelRef.h"
|
||||
#include "SkPathEffect.h"
|
||||
#include "SkPixelRef.h"
|
||||
|
@ -37,6 +35,7 @@
|
|||
#include "SkEmbossMaskFilter.h"
|
||||
#include "SkFlattenable.h"
|
||||
#include "SkGradientShader.h"
|
||||
#include "SkImages.h"
|
||||
#include "SkLayerDrawLooper.h"
|
||||
#include "SkLayerRasterizer.h"
|
||||
#include "SkLightingImageFilter.h"
|
||||
|
@ -85,14 +84,12 @@ void SkFlattenable::InitializeFlattenables() {
|
|||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMergeImageFilter)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkColorFilterImageFilter)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDownSampleImageFilter)
|
||||
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkFlipPixelRef)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_GlobalPool)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef)
|
||||
|
||||
SkBlurMaskFilter::InitializeFlattenables();
|
||||
SkColorFilter::InitializeFlattenables();
|
||||
SkGradientShader::InitializeFlattenables();
|
||||
SkImages::InitializeFlattenables();
|
||||
SkLightingImageFilter::InitializeFlattenables();
|
||||
SkTableColorFilter::InitializeFlattenables();
|
||||
SkXfermode::InitializeFlattenables();
|
||||
|
|
|
@ -150,12 +150,25 @@ private:
|
|||
*/
|
||||
bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
|
||||
int quality) {
|
||||
// Used for converting a bitmap to 8888.
|
||||
const SkBitmap* bmPtr = &bm;
|
||||
SkBitmap bitmap8888;
|
||||
|
||||
CFStringRef type;
|
||||
switch (fType) {
|
||||
case kJPEG_Type:
|
||||
type = kUTTypeJPEG;
|
||||
break;
|
||||
case kPNG_Type:
|
||||
// PNG encoding an ARGB_4444 bitmap gives the following errors in GM:
|
||||
// <Error>: CGImageDestinationAddImage image could not be converted to destination
|
||||
// format.
|
||||
// <Error>: CGImageDestinationFinalize image destination does not have enough images
|
||||
// So instead we copy to 8888.
|
||||
if (bm.getConfig() == SkBitmap::kARGB_4444_Config) {
|
||||
bm.copyTo(&bitmap8888, SkBitmap::kARGB_8888_Config);
|
||||
bmPtr = &bitmap8888;
|
||||
}
|
||||
type = kUTTypePNG;
|
||||
break;
|
||||
default:
|
||||
|
@ -168,7 +181,7 @@ bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
|
|||
}
|
||||
SkAutoTCallVProc<const void, CFRelease> ardst(dst);
|
||||
|
||||
CGImageRef image = SkCreateCGImageRef(bm);
|
||||
CGImageRef image = SkCreateCGImageRef(*bmPtr);
|
||||
if (NULL == image) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,92 +8,64 @@
|
|||
|
||||
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkImageEncoder.h"
|
||||
#include "SkMovie.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
extern SkImageDecoder* SkImageDecoder_GIF_Factory(SkStream*);
|
||||
extern SkImageDecoder* SkImageDecoder_BMP_Factory(SkStream*);
|
||||
extern SkImageDecoder* SkImageDecoder_ICO_Factory(SkStream*);
|
||||
extern SkImageDecoder* SkImageDecoder_PNG_Factory(SkStream*);
|
||||
extern SkImageDecoder* SkImageDecoder_WBMP_Factory(SkStream*);
|
||||
extern SkImageDecoder* SkImageDecoder_JPEG_Factory(SkStream*);
|
||||
|
||||
typedef SkImageDecoder* (*SkImageDecoderFactoryProc)(SkStream*);
|
||||
|
||||
struct CodecFormat {
|
||||
SkImageDecoderFactoryProc fProc;
|
||||
SkImageDecoder::Format fFormat;
|
||||
};
|
||||
|
||||
static const CodecFormat gPairs[] = {
|
||||
#if 0
|
||||
{ SkImageDecoder_GIF_Factory, SkImageDecoder::kGIF_Format },
|
||||
{ SkImageDecoder_PNG_Factory, SkImageDecoder::kPNG_Format },
|
||||
{ SkImageDecoder_ICO_Factory, SkImageDecoder::kICO_Format },
|
||||
{ SkImageDecoder_WBMP_Factory, SkImageDecoder::kWBMP_Format },
|
||||
{ SkImageDecoder_BMP_Factory, SkImageDecoder::kBMP_Format },
|
||||
{ SkImageDecoder_JPEG_Factory, SkImageDecoder::kJPEG_Format }
|
||||
#endif
|
||||
};
|
||||
class SkBitmap;
|
||||
class SkStream;
|
||||
|
||||
SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
|
||||
SkImageDecoder* codec = gPairs[i].fProc(stream);
|
||||
stream->rewind();
|
||||
if (NULL != codec) {
|
||||
return codec;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SkImageDecoder::SupportsFormat(Format format) {
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
|
||||
if (gPairs[i].fFormat == format) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SkImageDecoder::DecodeFile(const char file[], SkBitmap*, SkBitmap::Config,
|
||||
SkImageDecoder::Mode, SkImageDecoder::Format*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkImageDecoder::decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkImageDecoder::DecodeStream(SkStream*, SkBitmap*, SkBitmap::Config, SkImageDecoder::Mode,
|
||||
SkImageDecoder::Format*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkImageDecoder::DecodeMemory(const void*, size_t, SkBitmap*, SkBitmap::Config,
|
||||
SkImageDecoder::Mode, SkImageDecoder::Format*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkImageDecoder* CreateJPEGImageDecoder() {
|
||||
return NULL;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkMovie* SkMovie::DecodeStream(SkStream* stream) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkImageEncoder* SkImageEncoder::Create(Type t) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SkImageEncoder::EncodeFile(const char file[], const SkBitmap&, Type, int quality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkImageEncoder::EncodeStream(SkWStream*, const SkBitmap&, SkImageEncoder::Type, int) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkImageEncoder::encodeStream(SkWStream*, const SkBitmap&, int) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef SkMovie* (*SkMovieFactoryProc)(SkStream*);
|
||||
|
||||
extern SkMovie* SkMovie_GIF_Factory(SkStream*);
|
||||
|
||||
static const SkMovieFactoryProc gMovieProcs[] = {
|
||||
#if 0
|
||||
SkMovie_GIF_Factory
|
||||
#endif
|
||||
};
|
||||
|
||||
SkMovie* SkMovie::DecodeStream(SkStream* stream) {
|
||||
for (unsigned i = 0; i < SK_ARRAY_COUNT(gMovieProcs); i++) {
|
||||
SkMovie* movie = gMovieProcs[i](stream);
|
||||
if (NULL != movie) {
|
||||
return movie;
|
||||
}
|
||||
stream->rewind();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern SkImageEncoder* SkImageEncoder_JPEG_Factory();
|
||||
extern SkImageEncoder* SkImageEncoder_PNG_Factory();
|
||||
|
||||
SkImageEncoder* SkImageEncoder::Create(Type t) {
|
||||
switch (t) {
|
||||
#if 0
|
||||
case kJPEG_Type:
|
||||
return SkImageEncoder_JPEG_Factory();
|
||||
case kPNG_Type:
|
||||
return SkImageEncoder_PNG_Factory();
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#include "SkImages.h"
|
||||
|
||||
void SkImages::InitializeFlattenables() {}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "SkBenchLogger.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkMath.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkPicture.h"
|
||||
|
@ -109,7 +110,7 @@ static bool run_single_benchmark(const SkString& inputPath,
|
|||
}
|
||||
|
||||
bool success = false;
|
||||
SkPicture picture(&inputStream, &success);
|
||||
SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
|
||||
if (!success) {
|
||||
SkString err;
|
||||
err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "SkCanvas.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkMath.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkPicture.h"
|
||||
|
@ -96,7 +97,7 @@ static bool render_picture(const SkString& inputPath, const SkString& outputDir,
|
|||
}
|
||||
|
||||
bool success = false;
|
||||
SkPicture picture(&inputStream, &success);
|
||||
SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
|
||||
if (!success) {
|
||||
SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
|
||||
return false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче