diff options
-rw-r--r-- | gyp/tests.gyp | 1 | ||||
-rw-r--r-- | include/core/SkFlattenable.h | 52 | ||||
-rw-r--r-- | include/pipe/SkGPipe.h | 1 | ||||
-rw-r--r-- | src/core/SkFlattenable.cpp | 40 | ||||
-rw-r--r-- | src/core/SkOrderedReadBuffer.cpp | 26 | ||||
-rw-r--r-- | src/core/SkOrderedWriteBuffer.cpp | 37 | ||||
-rw-r--r-- | src/core/SkPictureFlat.cpp | 4 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 9 | ||||
-rw-r--r-- | src/pipe/SkGPipePriv.h | 1 | ||||
-rw-r--r-- | src/pipe/SkGPipeRead.cpp | 14 | ||||
-rw-r--r-- | src/pipe/SkGPipeWrite.cpp | 100 | ||||
-rw-r--r-- | tests/FlatDataTest.cpp | 85 |
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) |