aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/effects/SkLayerDrawLooper.h44
-rw-r--r--src/effects/SkLayerDrawLooper.cpp82
-rw-r--r--tests/LayerDrawLooperTest.cpp21
3 files changed, 127 insertions, 20 deletions
diff --git a/include/effects/SkLayerDrawLooper.h b/include/effects/SkLayerDrawLooper.h
index 6955192b53..e1fae57cb8 100644
--- a/include/effects/SkLayerDrawLooper.h
+++ b/include/effects/SkLayerDrawLooper.h
@@ -107,10 +107,12 @@ public:
virtual bool next(SkCanvas*, SkPaint* paint);
SK_DEVELOPER_TO_STRING()
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerDrawLooper)
+
+ /// Implements Flattenable.
+ virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; }
+ static SkFlattenable* CreateProc(SkReadBuffer& buffer);
protected:
- SkLayerDrawLooper(SkReadBuffer&);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
@@ -134,6 +136,44 @@ private:
};
typedef SkDrawLooper INHERITED;
+
+public:
+ class SK_API Builder {
+ public:
+ Builder();
+ ~Builder();
+
+ /**
+ * Call for each layer you want to add (from top to bottom).
+ * This returns a paint you can modify, but that ptr is only valid until
+ * the next call made to addLayer().
+ */
+ SkPaint* addLayer(const LayerInfo&);
+
+ /**
+ * This layer will draw with the original paint, at the specified offset
+ */
+ void addLayer(SkScalar dx, SkScalar dy);
+
+ /**
+ * This layer will with the original paint and no offset.
+ */
+ void addLayer() { this->addLayer(0, 0); }
+
+ /// Similar to addLayer, but adds a layer to the top.
+ SkPaint* addLayerOnTop(const LayerInfo&);
+
+ /**
+ * Pass list of layers on to newly built looper and return it. This will
+ * also reset the builder, so it can be used to build another looper.
+ */
+ SkLayerDrawLooper* detachLooper();
+
+ private:
+ Rec* fRecs;
+ Rec* fTopRec;
+ int fCount;
+ };
};
#endif
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index 6c7c3cef0c..49263fbbb5 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -221,14 +221,10 @@ void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
}
}
-SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
- : INHERITED(buffer),
- fRecs(NULL),
- fTopRec(NULL),
- fCount(0),
- fCurrRec(NULL) {
+SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
int count = buffer.readInt();
+ Builder builder;
for (int i = 0; i < count; i++) {
LayerInfo info;
info.fFlagsMask = buffer.readInt();
@@ -236,13 +232,14 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
info.fColorMode = (SkXfermode::Mode)buffer.readInt();
buffer.readPoint(&info.fOffset);
info.fPostTranslate = buffer.readBool();
- buffer.readPaint(this->addLayerOnTop(info));
+ buffer.readPaint(builder.addLayerOnTop(info));
}
- SkASSERT(count == fCount);
+ SkLayerDrawLooper* looper = builder.detachLooper();
+ SkASSERT(count == looper->fCount);
#ifdef SK_DEBUG
{
- Rec* rec = fRecs;
+ Rec* rec = looper->fRecs;
int n = 0;
while (rec) {
rec = rec->fNext;
@@ -251,6 +248,8 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
SkASSERT(count == n);
}
#endif
+
+ return looper;
}
#ifdef SK_DEVELOPER
@@ -347,3 +346,68 @@ void SkLayerDrawLooper::toString(SkString* str) const {
}
}
#endif
+
+SkLayerDrawLooper::Builder::Builder()
+ : fRecs(NULL),
+ fTopRec(NULL),
+ fCount(0) {
+}
+
+SkLayerDrawLooper::Builder::~Builder() {
+ Rec* rec = fRecs;
+ while (rec) {
+ Rec* next = rec->fNext;
+ SkDELETE(rec);
+ rec = next;
+ }
+}
+
+SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
+ fCount += 1;
+
+ Rec* rec = SkNEW(Rec);
+ rec->fNext = fRecs;
+ rec->fInfo = info;
+ fRecs = rec;
+ if (NULL == fTopRec) {
+ fTopRec = rec;
+ }
+
+ return &rec->fPaint;
+}
+
+void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
+ LayerInfo info;
+
+ info.fOffset.set(dx, dy);
+ (void)this->addLayer(info);
+}
+
+SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
+ fCount += 1;
+
+ Rec* rec = SkNEW(Rec);
+ rec->fNext = NULL;
+ rec->fInfo = info;
+ if (NULL == fRecs) {
+ fRecs = rec;
+ } else {
+ SkASSERT(NULL != fTopRec);
+ fTopRec->fNext = rec;
+ }
+ fTopRec = rec;
+
+ return &rec->fPaint;
+}
+
+SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() {
+ SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper);
+ looper->fCount = fCount;
+ looper->fRecs = fRecs;
+
+ fCount = 0;
+ fRecs = NULL;
+ fTopRec = NULL;
+
+ return looper;
+}
diff --git a/tests/LayerDrawLooperTest.cpp b/tests/LayerDrawLooperTest.cpp
index a1319a50de..8f8a6b6eb0 100644
--- a/tests/LayerDrawLooperTest.cpp
+++ b/tests/LayerDrawLooperTest.cpp
@@ -35,21 +35,22 @@ private:
};
static void test_frontToBack(skiatest::Reporter* reporter) {
- SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
+ SkLayerDrawLooper::Builder looperBuilder;
SkLayerDrawLooper::LayerInfo layerInfo;
// Add the front layer, with the defaults.
- (void)looper->addLayer(layerInfo);
+ (void)looperBuilder.addLayer(layerInfo);
// Add the back layer, with some layer info set.
layerInfo.fOffset.set(10.0f, 20.0f);
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
- SkPaint* layerPaint = looper->addLayer(layerInfo);
+ SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
FakeDevice device;
SkCanvas canvas(&device);
SkPaint paint;
+ SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
looper->init(&canvas);
// The back layer should come first.
@@ -72,21 +73,22 @@ static void test_frontToBack(skiatest::Reporter* reporter) {
}
static void test_backToFront(skiatest::Reporter* reporter) {
- SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
+ SkLayerDrawLooper::Builder looperBuilder;
SkLayerDrawLooper::LayerInfo layerInfo;
// Add the back layer, with the defaults.
- (void)looper->addLayerOnTop(layerInfo);
+ (void)looperBuilder.addLayerOnTop(layerInfo);
// Add the front layer, with some layer info set.
layerInfo.fOffset.set(10.0f, 20.0f);
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
- SkPaint* layerPaint = looper->addLayerOnTop(layerInfo);
+ SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
FakeDevice device;
SkCanvas canvas(&device);
SkPaint paint;
+ SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
looper->init(&canvas);
// The back layer should come first.
@@ -109,21 +111,22 @@ static void test_backToFront(skiatest::Reporter* reporter) {
}
static void test_mixed(skiatest::Reporter* reporter) {
- SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
+ SkLayerDrawLooper::Builder looperBuilder;
SkLayerDrawLooper::LayerInfo layerInfo;
// Add the back layer, with the defaults.
- (void)looper->addLayer(layerInfo);
+ (void)looperBuilder.addLayer(layerInfo);
// Add the front layer, with some layer info set.
layerInfo.fOffset.set(10.0f, 20.0f);
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
- SkPaint* layerPaint = looper->addLayerOnTop(layerInfo);
+ SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
FakeDevice device;
SkCanvas canvas(&device);
SkPaint paint;
+ SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
looper->init(&canvas);
// The back layer should come first.