aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkFlattenable.h17
-rw-r--r--include/core/SkPicture.h4
-rw-r--r--src/core/SkFlattenable.cpp10
-rw-r--r--src/core/SkOrderedReadBuffer.cpp2
-rw-r--r--src/core/SkOrderedWriteBuffer.cpp6
-rw-r--r--src/core/SkPicture.cpp3
-rw-r--r--src/core/SkPicturePlayback.cpp26
-rw-r--r--src/core/SkXfermode.cpp12
8 files changed, 66 insertions, 14 deletions
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index e6c56a330e..1828b42a45 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -127,9 +127,21 @@ class SkTypeface;
class SkFlattenableReadBuffer {
public:
+ enum Flags {
+ kCrossProcess_Flag = 1 << 0,
+ kScalarIsFloat_Flag = 1 << 1,
+ kPtrIs64Bit_Flag = 1 << 2,
+ };
+
SkFlattenableReadBuffer();
virtual ~SkFlattenableReadBuffer() {}
+ void setFlags(uint32_t flags) { fFlags = flags; }
+ uint32_t getFlags() const { return fFlags; }
+
+ bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
+ bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
+ bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
virtual uint8_t readU8() = 0;
virtual uint16_t readU16() = 0;
@@ -192,7 +204,7 @@ public:
virtual SkRefCnt* readRefCnt() = 0;
virtual void* readFunctionPtr() = 0;
virtual SkFlattenable* readFlattenable() = 0;
-
+
protected:
SkRefCnt** fRCArray;
int fRCCount;
@@ -203,6 +215,9 @@ protected:
SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
SkFlattenable::Factory* fFactoryArray;
int fFactoryCount;
+
+private:
+ uint32_t fFlags;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 51ed0d71ac..976c594cad 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -37,6 +37,10 @@ public:
this call, those elements will not appear in this picture.
*/
SkPicture(const SkPicture& src);
+ /**
+ * Recreate a picture that was serialized into a stream. If an error occurs
+ * the picture will be "empty" : width and height == 0
+ */
explicit SkPicture(SkStream*);
virtual ~SkPicture();
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index 0232f75292..920c4fd101 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -32,6 +32,16 @@ SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
fFactoryTDArray = NULL;
fFactoryArray = NULL;
fFactoryCount = 0;
+
+ // Set default values. These should be explicitly set by our client
+ // via setFlags() if the buffer came from serialization.
+ fFlags = 0;
+#ifdef SK_SCALAR_IS_FLOAT
+ fFlags |= kScalarIsFloat_Flag;
+#endif
+ if (8 == sizeof(void*)) {
+ fFlags |= kPtrIs64Bit_Flag;
+ }
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp
index 62404a1d48..f3ba4850b3 100644
--- a/src/core/SkOrderedReadBuffer.cpp
+++ b/src/core/SkOrderedReadBuffer.cpp
@@ -99,6 +99,8 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
}
void* SkOrderedReadBuffer::readFunctionPtr() {
+ SkASSERT(!this->isCrossProcess());
+
void* proc;
fReader.read(&proc, sizeof(proc));
return proc;
diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp
index 3fa9706023..9c4303347a 100644
--- a/src/core/SkOrderedWriteBuffer.cpp
+++ b/src/core/SkOrderedWriteBuffer.cpp
@@ -95,11 +95,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
}
void SkOrderedWriteBuffer::writeFunctionPtr(void* proc) {
-// enable this to catch writers who's function-ptrs will break if the
-// serialized buffer is read-back in a diff process
-#if 0
- SkASSERT(!proc || !this->isCrossProcess());
-#endif
+ SkASSERT(!this->isCrossProcess());
*(void**)this->reserve(sizeof(void*)) = proc;
}
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index bcc2236143..350784577a 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -202,7 +202,8 @@ void SkPicture::draw(SkCanvas* surface) {
// V2 : adds SkPixelRef's generation ID.
// V3 : PictInfo tag at beginning, and EOF tag at the end
// V4 : move SkPictInfo to be the header
-#define PICTURE_VERSION 4
+// V5 : don't read/write FunctionPtr on cross-process (we can detect that)
+#define PICTURE_VERSION 5
SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
fRecord = NULL;
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 2e88d35f18..d3c77af2d1 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -337,6 +337,7 @@ void SkPicturePlayback::serialize(SkWStream* stream) const {
buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
buffer.setTypefaceRecorder(&typefaceSet);
buffer.setFactoryRecorder(&factSet);
+
this->flattenToBuffer(buffer);
// We have to write these to sets into the stream *before* we write
@@ -354,6 +355,29 @@ void SkPicturePlayback::serialize(SkWStream* stream) const {
///////////////////////////////////////////////////////////////////////////////
+/**
+ * Return the corresponding SkFlattenableReadBuffer flags, given a set of
+ * SkPictInfo flags.
+ */
+static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
+ static const struct {
+ uint32_t fSrc;
+ uint32_t fDst;
+ } gSD[] = {
+ { SkPictInfo::kCrossProcess_Flag, SkFlattenableReadBuffer::kCrossProcess_Flag },
+ { SkPictInfo::kScalarIsFloat_Flag, SkFlattenableReadBuffer::kScalarIsFloat_Flag },
+ { SkPictInfo::kPtrIs64Bit_Flag, SkFlattenableReadBuffer::kPtrIs64Bit_Flag },
+ };
+
+ uint32_t rbMask = 0;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
+ if (pictInfoFlags & gSD[i].fSrc) {
+ rbMask |= gSD[i].fDst;
+ }
+ }
+ return rbMask;
+}
+
bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
uint32_t tag, size_t size) {
/*
@@ -403,6 +427,8 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
stream->read(storage.get(), size);
SkOrderedReadBuffer buffer(storage.get(), size);
+ buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
+
fFactoryPlayback->setupBuffer(buffer);
fTFPlayback.setupBuffer(buffer);
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 62e62a17c1..bb9dc79326 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -681,17 +681,15 @@ void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
: SkXfermode(buffer) {
- // Might be a NULL if the Xfermode is recorded using the CrossProcess flag
- fProc = (SkXfermodeProc)buffer.readFunctionPtr();
+ fProc = NULL;
+ if (!buffer.isCrossProcess()) {
+ fProc = (SkXfermodeProc)buffer.readFunctionPtr();
+ }
}
void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- if (buffer.isCrossProcess()) {
- // function pointer is only valid in the current process. Write a NULL
- // so it can't be accidentally used
- buffer.writeFunctionPtr(NULL);
- } else {
+ if (!buffer.isCrossProcess()) {
buffer.writeFunctionPtr((void*)fProc);
}
}