//@todo thudson 22 April 2011 when can we safely delete [] dst?
storage.copyTo(dst);
SkMemoryStream pictReadback(dst, streamSize);
- SkPicture* retval = new SkPicture (&pictReadback);
+ bool success;
+ // Pass a decoding bitmap function so that the factory GM (which has an SkBitmap with
+ // encoded data) does not fail.
+ SkPicture* retval = new SkPicture (&pictReadback, &success, &SkImageDecoder::DecodeMemory);
return retval;
}
setup_bitmap(gRec, size, &bitmap);
SkCanvas canvas(bitmap);
installFilter(&canvas);
- PipeController pipeController(&canvas);
+ // Pass a decoding function so the factory GM (which has an SkBitmap
+ // with encoded data) will not fail playback.
+ PipeController pipeController(&canvas, &SkImageDecoder::DecodeMemory);
SkGPipeWriter writer;
SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
gPipeWritingFlagCombos[i].flags,
setup_bitmap(gRec, size, &bitmap);
SkCanvas canvas(bitmap);
installFilter(&canvas);
- TiledPipeController pipeController(bitmap);
+ TiledPipeController pipeController(bitmap, &SkImageDecoder::DecodeMemory);
SkGPipeWriter writer;
SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
gPipeWritingFlagCombos[i].flags,
// V9 : Allow the reader and writer of an SKP disagree on whether to support
// SK_SUPPORT_HINTING_SCALE_FACTOR
// V10: add drawRRect, drawOval, clipRRect
- static const uint32_t PICTURE_VERSION = 10;
+ // V11: modify how readBitmap and writeBitmap store their info.
+ static const uint32_t PICTURE_VERSION = 11;
// fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
-
/*
* Copyright 2011 Google Inc.
*
#ifndef SkGPipe_DEFINED
#define SkGPipe_DEFINED
-#include "SkWriter32.h"
#include "SkFlattenable.h"
+#include "SkPicture.h"
+#include "SkWriter32.h"
class SkCanvas;
};
void setCanvas(SkCanvas*);
+
+ /**
+ * Set a function for decoding bitmaps that have encoded data.
+ */
+ void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; }
+
// data must be 4-byte aligned
// length must be a multiple of 4
Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
size_t* bytesRead = NULL);
private:
- SkCanvas* fCanvas;
- class SkGPipeState* fState;
+ SkCanvas* fCanvas;
+ class SkGPipeState* fState;
+ SkPicture::InstallPixelRefProc fProc;
};
///////////////////////////////////////////////////////////////////////////////
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkGraphics.h"
+#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkPaint.h"
#include "SkPicture.h"
fStatus = SkGPipeReader::kDone_Status;
fTotalWritten = 0;
fAtomsWritten = 0;
+ fReader.setBitmapDecoder(&SkImageDecoder::DecodeMemory);
}
SimplePC::~SimplePC() {
SkGPipeWriter writer;
SimplePC controller(canvas);
TiledPipeController tc(canvas->getDevice()->accessBitmap(false),
+ &SkImageDecoder::DecodeMemory,
&canvas->getTotalMatrix());
SkGPipeController* pc;
if (SkOSMenu::kMixedState == fPipeState) {
}
void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
- const size_t length = this->readUInt();
- if (length > 0) {
- // Bitmap was encoded.
- const void* data = this->skip(length);
- const int width = this->readInt();
- const int height = this->readInt();
- if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
- SkASSERT(bitmap->width() == width && bitmap->height() == height);
+ const int width = this->readInt();
+ const int height = this->readInt();
+ // The writer stored a boolean value to determine whether an SkBitmapHeap was used during
+ // writing.
+ if (this->readBool()) {
+ // An SkBitmapHeap was used for writing. Read the index from the stream and find the
+ // corresponding SkBitmap in fBitmapStorage.
+ const uint32_t index = fReader.readU32();
+ fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap)
+ if (fBitmapStorage) {
+ *bitmap = *fBitmapStorage->getBitmap(index);
+ fBitmapStorage->releaseRef(index);
+ return;
} else {
+ // The bitmap was stored in a heap, but there is no way to access it. Set an error and
+ // fall through to use a place holder bitmap.
+ SkErrorInternals::SetError(kParseError_SkError, "SkOrderedWriteBuffer::writeBitmap "
+ "stored the SkBitmap in an SkBitmapHeap, but "
+ "SkOrderedReadBuffer has no SkBitmapHeapReader to "
+ "retrieve the SkBitmap.");
+ }
+ } else {
+ // The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
+ const size_t length = this->readUInt();
+ if (length > 0) {
+ // A non-zero size means the SkBitmap was encoded.
+ const void* data = this->skip(length);
+ if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
+ SkASSERT(bitmap->width() == width && bitmap->height() == height);
+ return;
+ }
// This bitmap was encoded when written, but we are unable to decode, possibly due to
- // not having a decoder. Use a placeholder bitmap.
+ // not having a decoder.
SkErrorInternals::SetError(kParseError_SkError,
"Could not decode bitmap. Resulting bitmap will be red.");
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap->allocPixels();
- bitmap->eraseColor(SK_ColorRED);
- }
- } else {
- if (fBitmapStorage) {
- const uint32_t index = fReader.readU32();
- fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap)
- *bitmap = *fBitmapStorage->getBitmap(index);
- fBitmapStorage->releaseRef(index);
} else {
+ // A size of zero means the SkBitmap was simply flattened.
bitmap->unflatten(*this);
+ return;
}
}
+ // Could not read the SkBitmap. Use a placeholder bitmap.
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap->allocPixels();
+ bitmap->eraseColor(SK_ColorRED);
}
SkTypeface* SkOrderedReadBuffer::readTypeface() {
}
void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
+ // Record the width and height. This way if readBitmap fails a dummy bitmap can be drawn at the
+ // right size.
+ this->writeInt(bitmap.width());
+ this->writeInt(bitmap.height());
+
// Record information about the bitmap in one of three ways, in order of priority:
// 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the
- // bitmap entirely or serialize it later as desired.
- // 2. Write an encoded version of the bitmap. Afterwards the width and height are written, so
- // a reader without a decoder can draw a dummy bitmap of the right size.
+ // bitmap entirely or serialize it later as desired. A boolean value of true will be written
+ // to the stream to signify that a heap was used.
+ // 2. Write an encoded version of the bitmap. After writing a boolean value of false, signifying
+ // that a heap was not used, write the size of the encoded data. A non-zero size signifies
+ // that encoded data was written.
// A. If the bitmap has an encoded representation, write it to the stream.
// B. If there is a function for encoding bitmaps, use it.
- // 3. Call SkBitmap::flatten.
- // For an encoded bitmap, write the size first. Otherwise store a 0 so the reader knows not to
- // decode.
- if (fBitmapHeap != NULL) {
+ // 3. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was
+ // not used, write a zero to signify that the data was not encoded.
+ bool useBitmapHeap = fBitmapHeap != NULL;
+ // Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an
+ // SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way.
+ this->writeBool(useBitmapHeap);
+ if (useBitmapHeap) {
SkASSERT(NULL == fBitmapEncoder);
- // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
- this->writeUInt(0);
int32_t slot = fBitmapHeap->insert(bitmap);
fWriter.write32(slot);
// crbug.com/155875
// Write the length to indicate that the bitmap was encoded successfully, followed
// by the actual data. This must match the case where fBitmapEncoder is used so the
// reader need not know the difference.
- this->writeUInt(data->size());
+ this->writeUInt(SkToU32(data->size()));
fWriter.writePad(data->data(), data->size());
encoded = true;
}
// by the actual data. This must match the case where the original data is used so the
// reader need not know the difference.
size_t length = stream.getOffset();
- this->writeUInt(length);
+ this->writeUInt(SkToU32(length));
if (stream.read(fWriter.reservePad(length), 0, length)) {
encoded = true;
} else {
}
}
}
- if (encoded) {
- // Write the width and height in case the reader does not have a decoder.
- this->writeInt(bitmap.width());
- this->writeInt(bitmap.height());
- } else {
+ if (!encoded) {
// Bitmap was not encoded. Record a zero, implying that the reader need not decode.
this->writeUInt(0);
bitmap.flatten(*this);
}
}
+ /**
+ * Add a bitmap to the array of bitmaps, or replace an existing one.
+ * This is only used when in cross process mode without a shared heap.
+ */
void addBitmap(int index) {
+ SkASSERT(shouldFlattenBitmaps(fFlags));
SkBitmap* bm;
if(fBitmaps.count() == index) {
bm = SkNEW(SkBitmap);
} else {
bm = fBitmaps[index];
}
- bm->unflatten(*fReader);
+ fReader->readBitmap(bm);
}
/**
* Override of SkBitmapHeapReader, so that SkOrderedReadBuffer can use
- * these SkBitmaps for bitmap shaders.
+ * these SkBitmaps for bitmap shaders. Used only in cross process mode
+ * without a shared heap.
*/
virtual SkBitmap* getBitmap(int32_t index) const SK_OVERRIDE {
+ SkASSERT(shouldFlattenBitmaps(fFlags));
return fBitmaps[index];
}
this->updateReader();
}
+ /**
+ * Access the shared heap. Only used in the case when bitmaps are not
+ * flattened.
+ */
SkBitmapHeap* getSharedHeap() const {
+ SkASSERT(!shouldFlattenBitmaps(fFlags));
return fSharedHeap;
}
SkGPipeReader::SkGPipeReader() {
fCanvas = NULL;
fState = NULL;
+ fProc = NULL;
}
SkGPipeReader::SkGPipeReader(SkCanvas* target) {
fCanvas = NULL;
this->setCanvas(target);
fState = NULL;
+ fProc = NULL;
}
void SkGPipeReader::setCanvas(SkCanvas *target) {
const ReadProc* table = gReadTable;
SkOrderedReadBuffer reader(data, length);
+ reader.setBitmapDecoder(fProc);
SkCanvas* canvas = fCanvas;
Status status = kEOF_Status;
SkASSERT(shouldFlattenBitmaps(fFlags));
SkOrderedWriteBuffer buffer(1024);
buffer.setNamedFactoryRecorder(fFactorySet);
- bm.flatten(buffer);
+ buffer.writeBitmap(bm);
this->flattenFactoryNames();
uint32_t size = buffer.size();
if (this->needOpBytes(size)) {
#include "SkGPipe.h"
#include "SkMatrix.h"
-PipeController::PipeController(SkCanvas* target)
+PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc)
:fReader(target) {
fBlock = NULL;
fBlockSize = fBytesWritten = 0;
+ fReader.setBitmapDecoder(proc);
}
PipeController::~PipeController() {
////////////////////////////////////////////////////////////////////////////////
TiledPipeController::TiledPipeController(const SkBitmap& bitmap,
+ SkPicture::InstallPixelRefProc proc,
const SkMatrix* initial)
-: INHERITED(NULL) {
+: INHERITED(NULL, proc) {
int32_t top = 0;
int32_t bottom;
int32_t height = bitmap.height() / NumberOfTiles;
fReader.setCanvas(canvas);
} else {
fReaders[i - 1].setCanvas(canvas);
+ fReaders[i - 1].setBitmapDecoder(proc);
}
canvas->unref();
}
#include "SkBitmap.h"
#include "SkChunkAlloc.h"
#include "SkGPipe.h"
+#include "SkPicture.h"
#include "SkTDArray.h"
class SkCanvas;
class PipeController : public SkGPipeController {
public:
- PipeController(SkCanvas* target);
+ PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc = NULL);
virtual ~PipeController();
virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
class TiledPipeController : public PipeController {
public:
- TiledPipeController(const SkBitmap&, const SkMatrix* initialMatrix = NULL);
+ TiledPipeController(const SkBitmap&, SkPicture::InstallPixelRefProc proc = NULL,
+ const SkMatrix* initialMatrix = NULL);
virtual ~TiledPipeController() {};
virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
virtual int numberOfReaders() const SK_OVERRIDE { return NumberOfTiles; }