aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/tests.gyp1
-rw-r--r--include/core/SkFlattenable.h52
-rw-r--r--include/pipe/SkGPipe.h1
-rw-r--r--src/core/SkFlattenable.cpp40
-rw-r--r--src/core/SkOrderedReadBuffer.cpp26
-rw-r--r--src/core/SkOrderedWriteBuffer.cpp37
-rw-r--r--src/core/SkPictureFlat.cpp4
-rw-r--r--src/core/SkPictureFlat.h9
-rw-r--r--src/pipe/SkGPipePriv.h1
-rw-r--r--src/pipe/SkGPipeRead.cpp14
-rw-r--r--src/pipe/SkGPipeWrite.cpp100
-rw-r--r--tests/FlatDataTest.cpp85
12 files changed, 267 insertions, 103 deletions
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index 8ea4ee8411..b30a749623 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -40,6 +40,7 @@
'../tests/DrawTextTest.cpp',
'../tests/EmptyPathTest.cpp',
'../tests/FillPathTest.cpp',
+ '../tests/FlatDataTest.cpp',
'../tests/FlateTest.cpp',
'../tests/FontHostStreamTest.cpp',
'../tests/FontHostTest.cpp',
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index 1828b42a45..bbd4a80edf 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -191,8 +191,8 @@ public:
/**
* Call this with an initially empty array, so the reader can cache each
- * factory it sees by name. Used by the pipe code in conjunction with
- * the writer's kInlineFactoryNames_Flag.
+ * factory it sees by name. Used by the pipe code in combination with
+ * setNamedFactoryRecorder.
*/
void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
fFactoryTDArray = array;
@@ -241,6 +241,33 @@ protected:
class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {};
+/**
+ * Similar to SkFactorySet, but only allows Factorys that have registered names.
+ * Also has a function to return the next added Factory's name.
+ */
+class SkNamedFactorySet : public SkRefCnt {
+public:
+ SkNamedFactorySet();
+
+ /**
+ * Find the specified Factory in the set. If it is not already in the set,
+ * and has registered its name, add it to the set, and return its index.
+ * If the Factory has no registered name, return 0.
+ */
+ uint32_t find(SkFlattenable::Factory);
+
+ /**
+ * If new Factorys have been added to the set, return the name of the first
+ * Factory added after the Factory name returned by the last call to this
+ * function.
+ */
+ const char* getNextAddedFactoryName();
+private:
+ int fNextAddedFactory;
+ SkFactorySet fFactorySet;
+ SkTDArray<const char*> fNames;
+};
+
class SkFlattenableWriteBuffer {
public:
SkFlattenableWriteBuffer();
@@ -285,14 +312,12 @@ public:
SkFactorySet* getFactoryRecorder() const { return fFactorySet; }
SkFactorySet* setFactoryRecorder(SkFactorySet*);
+ SkNamedFactorySet* getNamedFactoryRecorder() const { return fNamedFactorySet; }
+ SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
+
enum Flags {
kCrossProcess_Flag = 0x01,
/**
- * Instructs the writer to inline Factory names as there are seen the
- * first time (after that we store an index). The pipe code uses this.
- */
- kInlineFactoryNames_Flag = 0x02,
- /**
* Instructs the writer to always serialize bitmap pixel data.
*/
kForceFlattenBitmapPixels_Flag = 0x04
@@ -304,9 +329,6 @@ public:
bool isCrossProcess() const {
return SkToBool(fFlags & kCrossProcess_Flag);
}
- bool inlineFactoryNames() const {
- return SkToBool(fFlags & kInlineFactoryNames_Flag);
- }
bool persistBitmapPixels() const {
return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0;
@@ -322,10 +344,12 @@ protected:
obj->flatten(buffer);
}
- uint32_t fFlags;
- SkRefCntSet* fTFSet;
- SkRefCntSet* fRCSet;
- SkFactorySet* fFactorySet;
+ uint32_t fFlags;
+ SkRefCntSet* fTFSet;
+ SkRefCntSet* fRCSet;
+ SkFactorySet* fFactorySet;
+ SkNamedFactorySet* fNamedFactorySet;
+
};
#endif
diff --git a/include/pipe/SkGPipe.h b/include/pipe/SkGPipe.h
index a1f425c699..0a908d0480 100644
--- a/include/pipe/SkGPipe.h
+++ b/include/pipe/SkGPipe.h
@@ -128,7 +128,6 @@ public:
private:
SkGPipeCanvas* fCanvas;
- SkFactorySet* fFactorySet;
SkWriter32 fWriter;
};
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index edfc5aec02..60c04b14c7 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -46,17 +46,43 @@ SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
///////////////////////////////////////////////////////////////////////////////
+SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
+
+uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
+ uint32_t index = fFactorySet.find(factory);
+ if (index > 0) {
+ return index;
+ }
+ const char* name = SkFlattenable::FactoryToName(factory);
+ if (NULL == name) {
+ return 0;
+ }
+ *fNames.append() = name;
+ return fFactorySet.add(factory);
+}
+
+const char* SkNamedFactorySet::getNextAddedFactoryName() {
+ if (fNextAddedFactory < fNames.count()) {
+ return fNames[fNextAddedFactory++];
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
fFlags = (Flags)0;
fRCSet = NULL;
fTFSet = NULL;
fFactorySet = NULL;
+ fNamedFactorySet = NULL;
}
SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
SkSafeUnref(fRCSet);
SkSafeUnref(fTFSet);
SkSafeUnref(fFactorySet);
+ SkSafeUnref(fNamedFactorySet);
}
SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
@@ -71,6 +97,20 @@ SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
SkRefCnt_SafeAssign(fFactorySet, rec);
+ if (fNamedFactorySet != NULL) {
+ fNamedFactorySet->unref();
+ fNamedFactorySet = NULL;
+ }
+ return rec;
+}
+
+SkNamedFactorySet* SkFlattenableWriteBuffer::setNamedFactoryRecorder(
+ SkNamedFactorySet* rec) {
+ SkRefCnt_SafeAssign(fNamedFactorySet, rec);
+ if (fFactorySet != NULL) {
+ fFactorySet->unref();
+ fFactorySet = NULL;
+ }
return rec;
}
diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp
index f3ba4850b3..df949074fb 100644
--- a/src/core/SkOrderedReadBuffer.cpp
+++ b/src/core/SkOrderedReadBuffer.cpp
@@ -45,32 +45,16 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
if (0 == index) {
return NULL; // writer failed to give us the flattenable
}
- index = -index; // we stored the negative of the index
index -= 1; // we stored the index-base-1
SkASSERT(index < fFactoryCount);
factory = fFactoryArray[index];
} else if (fFactoryTDArray) {
- const int32_t* peek = (const int32_t*)fReader.peek();
- if (*peek <= 0) {
- int32_t index = fReader.readU32();
- if (0 == index) {
- return NULL; // writer failed to give us the flattenable
- }
- index = -index; // we stored the negative of the index
- index -= 1; // we stored the index-base-1
- factory = (*fFactoryTDArray)[index];
- } else {
- const char* name = fReader.readString();
- factory = SkFlattenable::NameToFactory(name);
- if (factory) {
- SkASSERT(fFactoryTDArray->find(factory) < 0);
- *fFactoryTDArray->append() = factory;
- } else {
-// SkDebugf("can't find factory for [%s]\n", name);
- }
- // if we didn't find a factory, that's our failure, not the writer's,
- // so we fall through, so we can skip the sizeRecorded data.
+ int32_t index = fReader.readU32();
+ if (0 == index) {
+ return NULL; // writer failed to give us the flattenable
}
+ index -= 1; // we stored the index-base-1
+ factory = (*fFactoryTDArray)[index];
} else {
factory = (SkFlattenable::Factory)readFunctionPtr();
if (NULL == factory) {
diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp
index 9c4303347a..fdfb6e3b15 100644
--- a/src/core/SkOrderedWriteBuffer.cpp
+++ b/src/core/SkOrderedWriteBuffer.cpp
@@ -23,8 +23,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
/*
* If we have a factoryset, then the first 32bits tell us...
* 0: failure to write the flattenable
- * <0: we store the negative of the (1-based) index
- * >0: the length of the name
+ * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet
* If we don't have a factoryset, then the first "ptr" is either the
* factory, or null for failure.
*
@@ -37,7 +36,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
factory = flattenable->getFactory();
}
if (NULL == factory) {
- if (fFactorySet) {
+ if (fFactorySet != NULL || fNamedFactorySet != NULL) {
this->write32(0);
} else {
this->writeFunctionPtr(NULL);
@@ -53,31 +52,17 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
* resolve the function-ptrs into strings for its reader. SkPicture
* does exactly this, by writing a table of names (matching the indices)
* up front in its serialized form.
- * 3. names : Reuse fFactorySet to store indices, but only after we've
- * written the name the first time. SkGPipe uses this technique, as it
- * doesn't require the reader to be told to know the table of names
- * up front.
+ * 3. index into fNamedFactorySet. fNamedFactorySet will also store the
+ * name. SkGPipe uses this technique so it can write the name to its
+ * stream before writing the flattenable.
*/
if (fFactorySet) {
- if (this->inlineFactoryNames()) {
- int index = fFactorySet->find(factory);
- if (index) {
- // we write the negative of the index, to distinguish it from
- // the length of a string
- this->write32(-index);
- } else {
- const char* name = SkFlattenable::FactoryToName(factory);
- if (NULL == name) {
- this->write32(0);
- return;
- }
- this->writeString(name);
- index = fFactorySet->add(factory);
- }
- } else {
- // we write the negative of the index, to distinguish it from
- // the length of a string
- this->write32(-(int)fFactorySet->add(factory));
+ this->write32(fFactorySet->add(factory));
+ } else if (fNamedFactorySet) {
+ int32_t index = fNamedFactorySet->find(factory);
+ this->write32(index);
+ if (0 == index) {
+ return;
}
} else {
this->writeFunctionPtr((void*)factory);
diff --git a/src/core/SkPictureFlat.cpp b/src/core/SkPictureFlat.cpp
index 763ed60c5c..b0c02cc728 100644
--- a/src/core/SkPictureFlat.cpp
+++ b/src/core/SkPictureFlat.cpp
@@ -63,7 +63,7 @@ SkRefCnt* SkRefCntPlayback::set(int index, SkRefCnt* obj) {
SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
int index, void (*flattenProc)(SkOrderedWriteBuffer&, const void*),
SkRefCntSet* refCntRecorder, SkRefCntSet* faceRecorder,
- uint32_t writeBufferflags, SkFactorySet* fset) {
+ uint32_t writeBufferflags, SkNamedFactorySet* fset) {
// a buffer of 256 bytes should be sufficient for most paints, regions,
// and matrices.
intptr_t storage[256];
@@ -75,7 +75,7 @@ SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
buffer.setTypefaceRecorder(faceRecorder);
}
buffer.setFlags(writeBufferflags);
- buffer.setFactoryRecorder(fset);
+ buffer.setNamedFactoryRecorder(fset);
flattenProc(buffer, obj);
uint32_t size = buffer.size();
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index bd3c4f89a6..ddcb100d6c 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -175,6 +175,7 @@ public:
* provided.
*/
virtual void unalloc(void* ptr) = 0;
+
};
class SkFlatData {
@@ -241,7 +242,7 @@ public:
SkRefCntSet* refCntRecorder = NULL,
SkRefCntSet* faceRecorder = NULL,
uint32_t writeBufferflags = 0,
- SkFactorySet* fset = NULL);
+ SkNamedFactorySet* fset = NULL);
void unflatten(void* result,
void (*unflattenProc)(SkOrderedReadBuffer&, void*),
@@ -291,7 +292,7 @@ class SkFlatDictionary {
public:
SkFlatDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL,
SkRefCntSet* typeFaceSet = NULL,
- SkFactorySet* factorySet = NULL)
+ SkNamedFactorySet* factorySet = NULL)
: fController(controller), fRefSet(refSet), fTypefaceSet(typeFaceSet)
, fFactorySet(factorySet) {
fFlattenProc = NULL;
@@ -444,7 +445,7 @@ private:
SkTDArray<const SkFlatData*> fData;
SkRefCntSet* fRefSet;
SkRefCntSet* fTypefaceSet;
- SkFactorySet* fFactorySet;
+ SkNamedFactorySet* fFactorySet;
const SkFlatData* findAndReturnFlat(const T& element,
uint32_t writeBufferflags) {
@@ -540,7 +541,7 @@ class SkBitmapDictionary : public SkFlatDictionary<SkBitmap> {
public:
SkBitmapDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL,
SkRefCntSet* typefaceSet = NULL,
- SkFactorySet* factorySet = NULL)
+ SkNamedFactorySet* factorySet = NULL)
: SkFlatDictionary<SkBitmap>(controller, refSet, typefaceSet, factorySet) {
fFlattenProc = &SkFlattenObjectProc<SkBitmap>;
fUnflattenProc = &SkUnflattenObjectProc<SkBitmap>;
diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h
index d9a36e9c86..1eb060429c 100644
--- a/src/pipe/SkGPipePriv.h
+++ b/src/pipe/SkGPipePriv.h
@@ -70,6 +70,7 @@ enum DrawOps {
kDef_Typeface_DrawOp,
kDef_Flattenable_DrawOp,
kDef_Bitmap_DrawOp,
+ kDef_Factory_DrawOp,
// these are signals to playback, not drawing verbs
kReportFlags_DrawOp,
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 41650b17fd..a8cba27b4c 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -104,6 +104,14 @@ public:
}
}
+ void defFactory(const char* name) {
+ SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
+ if (factory) {
+ SkASSERT(fFactoryArray.find(factory) < 0);
+ *fFactoryArray.append() = factory;
+ }
+ }
+
void addBitmap(int index) {
index--;
SkBitmap* bm;
@@ -551,6 +559,11 @@ static void def_Bitmap_rp(SkCanvas*, SkReader32*, uint32_t op32,
state->addBitmap(index);
}
+static void def_Factory_rp(SkCanvas*, SkReader32* reader, uint32_t,
+ SkGPipeState* state) {
+ state->defFactory(reader->readString());
+}
+
///////////////////////////////////////////////////////////////////////////////
static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
@@ -605,6 +618,7 @@ static const ReadProc gReadTable[] = {
def_Typeface_rp,
def_PaintFlat_rp,
def_Bitmap_rp,
+ def_Factory_rp,
reportflags_rp,
done_rp
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 9efc0b58bb..75f1affa54 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -28,6 +28,10 @@
#include "SkOrderedWriteBuffer.h"
#include "SkPictureFlat.h"
+static bool isCrossProcess(uint32_t flags) {
+ return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
+}
+
static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
SkASSERT(paintFlat < kCount_PaintFlats);
switch (paintFlat) {
@@ -61,7 +65,9 @@ static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
class FlattenableHeap : public SkFlatController {
public:
- FlattenableHeap(int numFlatsToKeep) : fNumFlatsToKeep(numFlatsToKeep) {}
+ FlattenableHeap(int numFlatsToKeep)
+ : fNumFlatsToKeep(numFlatsToKeep) {
+ }
~FlattenableHeap() {
fPointers.freeAll();
@@ -132,7 +138,7 @@ const SkFlatData* FlattenableHeap::flatToReplace() const {
class FlatDictionary : public SkFlatDictionary<SkFlattenable> {
public:
- FlatDictionary(FlattenableHeap* heap, SkFactorySet* factorySet)
+ FlatDictionary(FlattenableHeap* heap, SkNamedFactorySet* factorySet)
: SkFlatDictionary<SkFlattenable>(heap, NULL, NULL, factorySet) {
fFlattenProc = &flattenFlattenableProc;
// No need to define fUnflattenProc since the writer will never
@@ -365,7 +371,7 @@ BitmapInfo* SharedHeap::bitmapToReplace(const SkBitmap& bm) const {
class SkGPipeCanvas : public SkCanvas {
public:
- SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*, uint32_t flags);
+ SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags);
virtual ~SkGPipeCanvas();
void finish() {
@@ -439,16 +445,17 @@ private:
enum {
kNoSaveLayer = -1,
};
- int fFirstSaveLayerStackLevel;
- SharedHeap fSharedHeap;
+ SkNamedFactorySet* fFactorySet;
+ int fFirstSaveLayerStackLevel;
+ SharedHeap fSharedHeap;
SkGPipeController* fController;
- SkWriter32& fWriter;
- size_t fBlockSize; // amount allocated for writer
- size_t fBytesNotified;
- bool fDone;
- uint32_t fFlags;
+ SkWriter32& fWriter;
+ size_t fBlockSize; // amount allocated for writer
+ size_t fBytesNotified;
+ bool fDone;
+ uint32_t fFlags;
- SkRefCntSet fTypefaceSet;
+ SkRefCntSet fTypefaceSet;
uint32_t getTypefaceID(SkTypeface*);
@@ -472,6 +479,10 @@ private:
}
}
+ // Should be called after any calls to an SkFlatDictionary::findAndReplace
+ // if a new SkFlatData was added when in cross process mode
+ void flattenFactoryNames();
+
// These are only used when in cross process, but with no shared address
// space, so bitmaps are flattened.
FlattenableHeap fBitmapHeap;
@@ -509,18 +520,32 @@ private:
typedef SkCanvas INHERITED;
};
+void SkGPipeCanvas::flattenFactoryNames() {
+ const char* name;
+ while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
+ size_t len = strlen(name);
+ if (this->needOpBytes(len)) {
+ this->writeOp(kDef_Factory_DrawOp);
+ fWriter.writeString(name, len);
+ }
+ }
+}
+
int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
SkASSERT(shouldFlattenBitmaps(fFlags));
- uint32_t flags = SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
- | SkFlattenableWriteBuffer::kCrossProcess_Flag;
+ uint32_t flags = SkFlattenableWriteBuffer::kCrossProcess_Flag;
bool added, replaced;
const SkFlatData* flat = fBitmapDictionary.findAndReplace(
bitmap, flags, fBitmapHeap.flatToReplace(), &added, &replaced);
int index = flat->index();
- if (added && this->needOpBytes(flat->flatSize())) {
- this->writeOp(kDef_Bitmap_DrawOp, 0, index);
- fWriter.write(flat->data(), flat->flatSize());
+ if (added) {
+ this->flattenFactoryNames();
+ size_t flatSize = flat->flatSize();
+ if (this->needOpBytes(flatSize)) {
+ this->writeOp(kDef_Bitmap_DrawOp, 0, index);
+ fWriter.write(flat->data(), flatSize);
+ }
}
return index;
}
@@ -533,9 +558,8 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
}
uint32_t writeBufferFlags;
- if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) {
- writeBufferFlags = (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
- | SkFlattenableWriteBuffer::kCrossProcess_Flag);
+ if (isCrossProcess(fFlags)) {
+ writeBufferFlags = SkFlattenableWriteBuffer::kCrossProcess_Flag;
} else {
// Needed for bitmap shaders.
writeBufferFlags = SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag;
@@ -545,9 +569,15 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
const SkFlatData* flat = fFlatDictionary.findAndReplace(
*obj, writeBufferFlags, fFlattenableHeap.flatToReplace(), &added, &replaced);
int index = flat->index();
- if (added && this->needOpBytes(flat->flatSize())) {
- this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
- fWriter.write(flat->data(), flat->flatSize());
+ if (added) {
+ if (isCrossProcess(fFlags)) {
+ this->flattenFactoryNames();
+ }
+ size_t flatSize = flat->flatSize();
+ if (this->needOpBytes(flatSize)) {
+ this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
+ fWriter.write(flat->data(), flatSize);
+ }
}
if (replaced) {
index = ~index;
@@ -562,11 +592,15 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
#define FLATTENABLES_TO_KEEP 10
SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
- SkWriter32* writer, SkFactorySet* fset, uint32_t flags)
-: fSharedHeap(!(flags & SkGPipeWriter::kCrossProcess_Flag), controller->numberOfReaders())
-, fWriter(*writer), fFlags(flags)
-, fBitmapHeap(BITMAPS_TO_KEEP), fBitmapDictionary(&fBitmapHeap, NULL, NULL, fset)
-, fFlattenableHeap(FLATTENABLES_TO_KEEP), fFlatDictionary(&fFlattenableHeap, fset) {
+ SkWriter32* writer, uint32_t flags)
+: fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
+, fSharedHeap(!isCrossProcess(flags), controller->numberOfReaders())
+, fWriter(*writer)
+, fFlags(flags)
+, fBitmapHeap(BITMAPS_TO_KEEP)
+, fBitmapDictionary(&fBitmapHeap, NULL, NULL, fFactorySet)
+, fFlattenableHeap(FLATTENABLES_TO_KEEP)
+, fFlatDictionary(&fFlattenableHeap, fFactorySet) {
fController = controller;
fDone = false;
fBlockSize = 0; // need first block from controller
@@ -589,6 +623,7 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
SkGPipeCanvas::~SkGPipeCanvas() {
this->finish();
+ SkSafeUnref(fFactorySet);
}
bool SkGPipeCanvas::needOpBytes(size_t needed) {
@@ -1196,7 +1231,7 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
}
if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
- if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) {
+ if (isCrossProcess(fFlags)) {
uint32_t id = this->getTypefaceID(paint.getTypeface());
*ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
} else if (this->needOpBytes(sizeof(void*))) {
@@ -1255,23 +1290,18 @@ void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
///////////////////////////////////////////////////////////////////////////////
SkGPipeWriter::SkGPipeWriter()
-: fFactorySet(SkNEW(SkFactorySet))
-, fWriter(0) {
+: fWriter(0) {
fCanvas = NULL;
}
SkGPipeWriter::~SkGPipeWriter() {
this->endRecording();
- fFactorySet->unref();
}
SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
if (NULL == fCanvas) {
fWriter.reset(NULL, 0);
- fFactorySet->reset();
- fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
- (flags & kCrossProcess_Flag) ?
- fFactorySet : NULL, flags));
+ fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags));
}
controller->setCanvas(fCanvas);
return fCanvas;
diff --git a/tests/FlatDataTest.cpp b/tests/FlatDataTest.cpp
new file mode 100644
index 0000000000..755d8cd944
--- /dev/null
+++ b/tests/FlatDataTest.cpp
@@ -0,0 +1,85 @@
+
+/*
+ * 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 "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkColorFilter.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+#include "SkPictureFlat.h"
+#include "SkShader.h"
+#include "SkXfermode.h"
+#include "Test.h"
+
+static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer,
+ const void* obj) {
+ buffer.writeFlattenable((SkFlattenable*)obj);
+}
+
+/**
+ * Verify that two SkFlatData objects that created from the same object are
+ * identical when using an SkNamedFactorySet.
+ * @param reporter Object to report failures.
+ * @param obj Flattenable object to be flattened.
+ * @param flattenProc Function that flattens objects with the same type as obj.
+ */
+static void testCreate(skiatest::Reporter* reporter, const void* obj,
+ void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
+ SkChunkFlatController controller(1024);
+ SkNamedFactorySet factorySet;
+ // No need to delete data because that will be taken care of by the
+ // controller.
+ SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0, flattenProc,
+ NULL, NULL, 0, &factorySet);
+ data1->setSentinelInCache();
+ SkFlatData* data2 = SkFlatData::Create(&controller, obj, 0, flattenProc,
+ NULL, NULL, 0, &factorySet);
+ data2->setSentinelAsCandidate();
+ REPORTER_ASSERT(reporter, SkFlatData::Compare(data1, data2) == 0);
+}
+
+static void Tests(skiatest::Reporter* reporter) {
+ // Test flattening SkShader
+ SkPoint points[2];
+ points[0].set(0, 0);
+ points[1].set(SkIntToScalar(20), SkIntToScalar(20));
+ SkColor colors[2];
+ colors[0] = SK_ColorRED;
+ colors[1] = SK_ColorBLUE;
+ SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
+ 2, SkShader::kRepeat_TileMode);
+ SkAutoUnref aur(shader);
+ testCreate(reporter, shader, flattenFlattenableProc);
+
+ // Test SkBitmap
+ {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 50, 50);
+ bm.allocPixels();
+ SkCanvas canvas(bm);
+ SkPaint paint;
+ paint.setShader(shader);
+ canvas.drawPaint(paint);
+ testCreate(reporter, &bm, &SkFlattenObjectProc<SkBitmap>);
+ }
+
+ // Test SkColorFilter
+ SkColorFilter* cf = SkColorFilter::CreateLightingFilter(SK_ColorBLUE,
+ SK_ColorRED);
+ SkAutoUnref aurcf(cf);
+ testCreate(reporter, cf, &flattenFlattenableProc);
+
+ // Test SkXfermode
+ SkXfermode* xfer = SkXfermode::Create(SkXfermode::kDstOver_Mode);
+ SkAutoUnref aurxf(xfer);
+ testCreate(reporter, xfer, &flattenFlattenableProc);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("FlatData", FlatDataClass, Tests)