Builder class for SkLayerDrawLooper.
SkLayerDrawLooper provides methods like addLayer() to build up a linked list of layers. Working towards making this class immutable, this patch introduces the SkLayerDrawLooperBuilder class which is used to accumulate all the layers first. Once all layers are in place, it creates a new SkLayerDrawLooper object and hands over the list of layers to that object. For now we keep the addLayer methods in SkLayerDrawLooper so we don't break Chrome and Blink when this is landed. Once we've updated all users, we can remove the methods. BUG=skia:2141 R=reed@google.com, scroggo@google.com, mtklein@google.com, reed@chromium.org Author: dominikg@chromium.org Review URL: https://codereview.chromium.org/133813005 git-svn-id: http://skia.googlecode.com/svn/trunk@13448 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
02d6f54616
commit
74ba2f62dc
@ -107,10 +107,12 @@ public:
|
|||||||
virtual bool next(SkCanvas*, SkPaint* paint);
|
virtual bool next(SkCanvas*, SkPaint* paint);
|
||||||
|
|
||||||
SK_DEVELOPER_TO_STRING()
|
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:
|
protected:
|
||||||
SkLayerDrawLooper(SkReadBuffer&);
|
|
||||||
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -134,6 +136,44 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef SkDrawLooper INHERITED;
|
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
|
#endif
|
||||||
|
@ -221,14 +221,10 @@ void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
|
SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
|
||||||
: INHERITED(buffer),
|
|
||||||
fRecs(NULL),
|
|
||||||
fTopRec(NULL),
|
|
||||||
fCount(0),
|
|
||||||
fCurrRec(NULL) {
|
|
||||||
int count = buffer.readInt();
|
int count = buffer.readInt();
|
||||||
|
|
||||||
|
Builder builder;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
LayerInfo info;
|
LayerInfo info;
|
||||||
info.fFlagsMask = buffer.readInt();
|
info.fFlagsMask = buffer.readInt();
|
||||||
@ -236,13 +232,14 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
|
|||||||
info.fColorMode = (SkXfermode::Mode)buffer.readInt();
|
info.fColorMode = (SkXfermode::Mode)buffer.readInt();
|
||||||
buffer.readPoint(&info.fOffset);
|
buffer.readPoint(&info.fOffset);
|
||||||
info.fPostTranslate = buffer.readBool();
|
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
|
#ifdef SK_DEBUG
|
||||||
{
|
{
|
||||||
Rec* rec = fRecs;
|
Rec* rec = looper->fRecs;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (rec) {
|
while (rec) {
|
||||||
rec = rec->fNext;
|
rec = rec->fNext;
|
||||||
@ -251,6 +248,8 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer)
|
|||||||
SkASSERT(count == n);
|
SkASSERT(count == n);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return looper;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SK_DEVELOPER
|
#ifdef SK_DEVELOPER
|
||||||
@ -347,3 +346,68 @@ void SkLayerDrawLooper::toString(SkString* str) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
@ -35,21 +35,22 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void test_frontToBack(skiatest::Reporter* reporter) {
|
static void test_frontToBack(skiatest::Reporter* reporter) {
|
||||||
SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
|
SkLayerDrawLooper::Builder looperBuilder;
|
||||||
SkLayerDrawLooper::LayerInfo layerInfo;
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
||||||
|
|
||||||
// Add the front layer, with the defaults.
|
// Add the front layer, with the defaults.
|
||||||
(void)looper->addLayer(layerInfo);
|
(void)looperBuilder.addLayer(layerInfo);
|
||||||
|
|
||||||
// Add the back layer, with some layer info set.
|
// Add the back layer, with some layer info set.
|
||||||
layerInfo.fOffset.set(10.0f, 20.0f);
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
||||||
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
||||||
SkPaint* layerPaint = looper->addLayer(layerInfo);
|
SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
|
||||||
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||||
|
|
||||||
FakeDevice device;
|
FakeDevice device;
|
||||||
SkCanvas canvas(&device);
|
SkCanvas canvas(&device);
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
||||||
looper->init(&canvas);
|
looper->init(&canvas);
|
||||||
|
|
||||||
// The back layer should come first.
|
// The back layer should come first.
|
||||||
@ -72,21 +73,22 @@ static void test_frontToBack(skiatest::Reporter* reporter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_backToFront(skiatest::Reporter* reporter) {
|
static void test_backToFront(skiatest::Reporter* reporter) {
|
||||||
SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
|
SkLayerDrawLooper::Builder looperBuilder;
|
||||||
SkLayerDrawLooper::LayerInfo layerInfo;
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
||||||
|
|
||||||
// Add the back layer, with the defaults.
|
// Add the back layer, with the defaults.
|
||||||
(void)looper->addLayerOnTop(layerInfo);
|
(void)looperBuilder.addLayerOnTop(layerInfo);
|
||||||
|
|
||||||
// Add the front layer, with some layer info set.
|
// Add the front layer, with some layer info set.
|
||||||
layerInfo.fOffset.set(10.0f, 20.0f);
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
||||||
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
||||||
SkPaint* layerPaint = looper->addLayerOnTop(layerInfo);
|
SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
|
||||||
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||||
|
|
||||||
FakeDevice device;
|
FakeDevice device;
|
||||||
SkCanvas canvas(&device);
|
SkCanvas canvas(&device);
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
||||||
looper->init(&canvas);
|
looper->init(&canvas);
|
||||||
|
|
||||||
// The back layer should come first.
|
// The back layer should come first.
|
||||||
@ -109,21 +111,22 @@ static void test_backToFront(skiatest::Reporter* reporter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_mixed(skiatest::Reporter* reporter) {
|
static void test_mixed(skiatest::Reporter* reporter) {
|
||||||
SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper));
|
SkLayerDrawLooper::Builder looperBuilder;
|
||||||
SkLayerDrawLooper::LayerInfo layerInfo;
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
||||||
|
|
||||||
// Add the back layer, with the defaults.
|
// Add the back layer, with the defaults.
|
||||||
(void)looper->addLayer(layerInfo);
|
(void)looperBuilder.addLayer(layerInfo);
|
||||||
|
|
||||||
// Add the front layer, with some layer info set.
|
// Add the front layer, with some layer info set.
|
||||||
layerInfo.fOffset.set(10.0f, 20.0f);
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
||||||
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
||||||
SkPaint* layerPaint = looper->addLayerOnTop(layerInfo);
|
SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
|
||||||
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||||
|
|
||||||
FakeDevice device;
|
FakeDevice device;
|
||||||
SkCanvas canvas(&device);
|
SkCanvas canvas(&device);
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
||||||
looper->init(&canvas);
|
looper->init(&canvas);
|
||||||
|
|
||||||
// The back layer should come first.
|
// The back layer should come first.
|
||||||
|
Loading…
Reference in New Issue
Block a user