SkTCopyOnFirstWrite-based SkPaintFilterCanvas API

I find this version preferable because

1) it consolidates the in/out paint args without compromising
efficiency or flexibility

2) relieves overriders from having to set the SkTLazy explicitly

BUG=skia:4782
R=mtklein@google.com,reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1576183002

Review URL: https://codereview.chromium.org/1576183002
This commit is contained in:
fmalita 2016-01-12 07:21:11 -08:00 committed by Commit bot
parent a51e7782b2
commit 32cdc32522
6 changed files with 25 additions and 33 deletions

View File

@ -131,6 +131,8 @@ class SkTCopyOnFirstWrite {
public: public:
SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {} SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
// Constructor for delayed initialization. // Constructor for delayed initialization.
SkTCopyOnFirstWrite() : fObj(NULL) {} SkTCopyOnFirstWrite() : fObj(NULL) {}

View File

@ -49,22 +49,18 @@ public:
protected: protected:
/** /**
* Called with the paint that will be used to draw the specified type. * Called with the paint that will be used to draw the specified type.
* * The implementation may modify the paint as they wish (using SkTCopyOnFirstWrite::writable).
* Upon return, if filteredPaint is initialized it will replace the original paint
* for the current draw. Note that that implementation is responsible for
* initializing *filteredPaint (e.g. via set(*paint)).
* *
* The result bool is used to determine whether the draw op is to be * The result bool is used to determine whether the draw op is to be
* executed (true) or skipped (false). When the draw is skipped, filteredPaint is * executed (true) or skipped (false).
* ignored.
* *
* Note: The base implementation calls onFilter() for top-level/explicit paints only. * Note: The base implementation calls onFilter() for top-level/explicit paints only.
* To also filter encapsulated paints (e.g. SkPicture, SkTextBlob), clients may need to * To also filter encapsulated paints (e.g. SkPicture, SkTextBlob), clients may need to
* override the relevant methods (i.e. drawPicture, drawTextBlob). * override the relevant methods (i.e. drawPicture, drawTextBlob).
*/ */
virtual bool onFilter(const SkPaint* paint, Type type, SkTLazy<SkPaint>* filteredPaint) const { virtual bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const {
if (paint) { if (*paint) {
this->onFilterPaint(filteredPaint->set(*paint), type); this->onFilterPaint(paint->writable(), type);
} }
return true; return true;
} }

View File

@ -475,27 +475,25 @@ public:
} }
protected: protected:
bool onFilter(const SkPaint* paint, Type t, SkTLazy<SkPaint>* filteredPaint) const override { bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
if (!paint) { if (!*paint) {
return true; return true;
} }
filteredPaint->set(*paint);
if (kText_Type == t && SkOSMenu::kMixedState != fLCDState) { if (kText_Type == t && SkOSMenu::kMixedState != fLCDState) {
filteredPaint->get()->setLCDRenderText(SkOSMenu::kOnState == fLCDState); paint->writable()->setLCDRenderText(SkOSMenu::kOnState == fLCDState);
} }
if (SkOSMenu::kMixedState != fAAState) { if (SkOSMenu::kMixedState != fAAState) {
filteredPaint->get()->setAntiAlias(SkOSMenu::kOnState == fAAState); paint->writable()->setAntiAlias(SkOSMenu::kOnState == fAAState);
} }
if (0 != fFilterQualityIndex) { if (0 != fFilterQualityIndex) {
filteredPaint->get()->setFilterQuality( paint->writable()->setFilterQuality(gFilterQualityStates[fFilterQualityIndex].fQuality);
gFilterQualityStates[fFilterQualityIndex].fQuality);
} }
if (SkOSMenu::kMixedState != fSubpixelState) { if (SkOSMenu::kMixedState != fSubpixelState) {
filteredPaint->get()->setSubpixelText(SkOSMenu::kOnState == fSubpixelState); paint->writable()->setSubpixelText(SkOSMenu::kOnState == fSubpixelState);
} }
if (0 != fHintingState && fHintingState < (int)SK_ARRAY_COUNT(gHintingStates)) { if (0 != fHintingState && fHintingState < (int)SK_ARRAY_COUNT(gHintingStates)) {
filteredPaint->get()->setHinting(gHintingStates[fHintingState].hinting); paint->writable()->setHinting(gHintingStates[fHintingState].hinting);
} }
return true; return true;
} }

View File

@ -13,22 +13,19 @@
class SkPaintFilterCanvas::AutoPaintFilter { class SkPaintFilterCanvas::AutoPaintFilter {
public: public:
AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint* paint) AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint* paint)
: fOrigPaint(paint) { : fPaint(paint) {
fShouldDraw = canvas->onFilter(fOrigPaint, type, &fFilteredPaint); fShouldDraw = canvas->onFilter(&fPaint, type);
} }
AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint& paint) AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint& paint)
: AutoPaintFilter(canvas, type, &paint) { } : AutoPaintFilter(canvas, type, &paint) { }
const SkPaint* paint() const { const SkPaint* paint() const { return fPaint; }
return fFilteredPaint.isValid() ? fFilteredPaint.get() : fOrigPaint;
}
bool shouldDraw() const { return fShouldDraw; } bool shouldDraw() const { return fShouldDraw; }
private: private:
const SkPaint* fOrigPaint; SkTCopyOnFirstWrite<SkPaint> fPaint;
SkTLazy<SkPaint> fFilteredPaint;
bool fShouldDraw; bool fShouldDraw;
}; };

View File

@ -69,16 +69,15 @@ public:
, fFilterQuality(quality) {} , fFilterQuality(quality) {}
protected: protected:
bool onFilter(const SkPaint* paint, Type, SkTLazy<SkPaint>* filteredPaint) const override { bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
if (paint) { if (*paint) {
filteredPaint->set(*paint);
if (nullptr != fOverdrawXfermode.get()) { if (nullptr != fOverdrawXfermode.get()) {
filteredPaint->get()->setAntiAlias(false); paint->writable()->setAntiAlias(false);
filteredPaint->get()->setXfermode(fOverdrawXfermode.get()); paint->writable()->setXfermode(fOverdrawXfermode.get());
} }
if (fOverrideFilterQuality) { if (fOverrideFilterQuality) {
filteredPaint->get()->setFilterQuality(fFilterQuality); paint->writable()->setFilterQuality(fFilterQuality);
} }
} }
return true; return true;

View File

@ -730,7 +730,7 @@ public:
MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { } MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
protected: protected:
bool onFilter(const SkPaint*, Type, SkTLazy<SkPaint>*) const override { return true; } bool onFilter(SkTCopyOnFirstWrite<SkPaint>*, Type) const override { return true; }
private: private:
typedef SkPaintFilterCanvas INHERITED; typedef SkPaintFilterCanvas INHERITED;