Simplify drawloopers and drawfilters. This allows the canvas to keep its

promise that const SkPaint& stay const (so we don't have bugs if a const paint
is referenced from two threads in pictures)



git-svn-id: http://skia.googlecode.com/svn/trunk@1074 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-04-07 14:18:59 +00:00
parent 591b6dadb0
commit 4e2b3d3fb1
9 changed files with 188 additions and 258 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,18 +19,15 @@
#include "SkRefCnt.h"
////////////////// EXPERIMENTAL //////////////////////////
class SkCanvas;
class SkPaint;
/** Right before something is being draw, filter() is called with the
current canvas and paint. If it returns true, then drawing proceeds
with the (possibly modified) canvas/paint, and then restore() is called
to restore the canvas/paint to their state before filter() was called.
If filter returns false, canvas/paint should not have been changed, and
restore() will not be called.
*/
/**
* Right before something is being draw, filter() is called with the
* paint. The filter may modify the paint as it wishes, which will then be
* used for the actual drawing. Note: this modification only lasts for the
* current draw, as a temporary copy of the paint is used.
*/
class SkDrawFilter : public SkRefCnt {
public:
enum Type {
@ -43,14 +40,11 @@ public:
kText_Type
};
/** Return true to allow the draw to continue (with possibly modified
canvas/paint). If true is returned, then restore() will be called.
*/
virtual bool filter(SkCanvas*, SkPaint*, Type) = 0;
/** If filter() returned true, then restore() will be called to restore the
canvas/paint to their previous states
*/
virtual void restore(SkCanvas*, SkPaint*, Type) = 0;
/**
* Called with the paint that will be used to draw the specified type.
* The implementation may modify the paint as they wish.
*/
virtual void filter(SkPaint*, Type) = 0;
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,8 +19,6 @@
#include "SkFlattenable.h"
////////////////// EXPERIMENTAL //////////////////////////
class SkCanvas;
class SkPaint;
@ -34,24 +32,25 @@ class SkPaint;
*/
class SK_API SkDrawLooper : public SkFlattenable {
public:
/** Called right before something is being drawn to the specified canvas
with the specified paint. Subclass that want to modify either parameter
can do so now.
*/
virtual void init(SkCanvas*, SkPaint*) {}
/** Called in a loop (after init()). Each time true is returned, the object
is drawn (possibly with a modified canvas and/or paint). When false is
finally returned, drawing for the object stops.
*/
virtual bool next() { return false; }
/** Called after the looper has finally returned false from next(), allowing
the looper to restore the canvas/paint to their original states.
is this required, since the subclass knows when it is done???
should we pass the canvas/paint here, and/or to the next call
so that subclasses don't need to retain pointers to them during the
loop?
*/
virtual void restore() {}
/**
* Called right before something is being drawn. This will be followed by
* calls to next() until next() returns false.
*/
virtual void init(SkCanvas*) = 0;
/**
* Called in a loop (after init()). Each time true is returned, the object
* is drawn (possibly with a modified canvas and/or paint). When false is
* finally returned, drawing for the object stops.
*
* On each call, the paint will be in its original state, but the canvas
* will be as it was following the previous call to next() or init().
*
* The implementation must ensure that, when next() finally returns false,
* that the canvas has been restored to the state it was initially, before
* init() was first called.
*/
virtual bool next(SkCanvas*, SkPaint* paint) = 0;
protected:
SkDrawLooper() {}

View File

@ -48,9 +48,8 @@ public:
virtual ~SkBlurDrawLooper();
// overrides from SkDrawLooper
virtual void init(SkCanvas*, SkPaint*);
virtual bool next();
virtual void restore();
virtual void init(SkCanvas*);
virtual bool next(SkCanvas*, SkPaint* paint);
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW_ARGS(SkBlurDrawLooper, (buffer));
@ -64,14 +63,10 @@ protected:
virtual Factory getFactory() { return CreateProc; }
private:
SkCanvas* fCanvas;
SkPaint* fPaint;
SkMaskFilter* fBlur;
SkColorFilter* fColorFilter;
SkScalar fDx, fDy;
SkColor fBlurColor;
SkColor fSavedColor; // remember the original
int fSaveCount;
uint32_t fBlurFlags;
enum State {

View File

@ -23,9 +23,8 @@ public:
}
// overrides from SkDrawLooper
virtual void init(SkCanvas*, SkPaint*);
virtual bool next();
virtual void restore();
virtual void init(SkCanvas*);
virtual bool next(SkCanvas*, SkPaint* paint);
// must be public for Registrar :(
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
@ -49,14 +48,9 @@ private:
};
Rec* fRecs;
int fCount;
struct Iter {
SkPaint fSavedPaint;
SkPaint* fPaint;
SkCanvas* fCanvas;
Rec* fRec;
};
Iter fIter;
// state-machine during the init/next cycle
Rec* fCurrRec;
class MyRegistrar : public SkFlattenable::Registrar {
public:

View File

@ -24,8 +24,7 @@ public:
SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags);
// overrides
virtual bool filter(SkCanvas*, SkPaint*, Type);
virtual void restore(SkCanvas*, SkPaint*, Type);
virtual void filter(SkPaint*, Type);
private:
uint32_t fPrevFlags; // local cache for filter/restore

View File

@ -280,65 +280,65 @@ private:
class AutoDrawLooper {
public:
AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
: fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
if ((fLooper = paint.getLooper()) != NULL) {
fLooper->init(canvas, (SkPaint*)&paint);
} else {
fOnce = true;
}
AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) {
fCanvas = canvas;
fLooper = paint.getLooper();
fFilter = canvas->getDrawFilter();
fNeedFilterRestore = false;
}
fPaint = NULL;
fSaveCount = canvas->getSaveCount();
fDone = false;
if (fLooper) {
fLooper->init(canvas);
}
}
~AutoDrawLooper() {
if (fNeedFilterRestore) {
SkASSERT(fFilter);
fFilter->restore(fCanvas, fPaint, fType);
}
if (NULL != fLooper) {
fLooper->restore();
}
SkASSERT(fCanvas->getSaveCount() == fSaveCount);
}
bool next() {
SkDrawFilter* filter = fFilter;
// if we drew earlier with a filter, then we need to restore first
if (fNeedFilterRestore) {
SkASSERT(filter);
filter->restore(fCanvas, fPaint, fType);
fNeedFilterRestore = false;
}
bool result;
if (NULL != fLooper) {
result = fLooper->next();
} else {
result = fOnce;
fOnce = false;
}
// if we're gonna draw, give the filter a chance to do its work
if (result && NULL != filter) {
fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
fType);
}
return result;
const SkPaint& paint() const {
SkASSERT(fPaint);
return *fPaint;
}
bool next(SkDrawFilter::Type drawType);
private:
SkDrawLooper* fLooper;
SkDrawFilter* fFilter;
SkCanvas* fCanvas;
SkPaint* fPaint;
SkDrawFilter::Type fType;
bool fOnce;
bool fNeedFilterRestore;
SkTLazy<SkPaint> fLazyPaint;
SkCanvas* fCanvas;
const SkPaint& fOrigPaint;
SkDrawLooper* fLooper;
SkDrawFilter* fFilter;
const SkPaint* fPaint;
int fSaveCount;
bool fDone;
};
bool AutoDrawLooper::next(SkDrawFilter::Type drawType) {
if (fDone) {
fPaint = NULL;
return false;
}
if (!fLooper && !fFilter) {
fDone = true;
fPaint = &fOrigPaint;
return true;
}
SkPaint* paint = fLazyPaint.set(fOrigPaint);
if (fLooper && !fLooper->next(fCanvas, paint)) {
fDone = true;
fPaint = NULL;
return false;
}
if (fFilter) {
fFilter->filter(paint, drawType);
}
fPaint = paint;
return true;
}
/* Stack helper for managing a SkBounder. In the destructor, if we were
given a bounder, we call its commit() method, signifying that we are
done accumulating bounds for that draw.
@ -380,14 +380,14 @@ private:
////////// macros to place around the internal draw calls //////////////////
#define ITER_BEGIN(paint, type) \
#define LOOPER_BEGIN(paint, type) \
/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \
AutoDrawLooper looper(this, paint, type); \
while (looper.next()) { \
AutoDrawLooper looper(this, paint); \
while (looper.next(type)) { \
SkAutoBounderCommit ac(fBounder); \
SkDrawIter iter(this);
#define ITER_END }
#define LOOPER_END }
////////////////////////////////////////////////////////////////////////////
@ -853,12 +853,12 @@ void SkCanvas::drawDevice(SkDevice* device, int x, int y,
paint = &tmp;
}
ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
while (iter.next()) {
iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
*paint);
looper.paint());
}
ITER_END
LOOPER_END
}
/////////////////////////////////////////////////////////////////////////////
@ -1190,13 +1190,13 @@ SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
//////////////////////////////////////////////////////////////////////////////
void SkCanvas::drawPaint(const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
while (iter.next()) {
iter.fDevice->drawPaint(iter, paint);
iter.fDevice->drawPaint(iter, looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
@ -1207,13 +1207,13 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
SkASSERT(pts != NULL);
ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
while (iter.next()) {
iter.fDevice->drawPoints(iter, mode, count, pts, paint);
iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
@ -1225,13 +1225,13 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
}
}
ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
while (iter.next()) {
iter.fDevice->drawRect(iter, r, paint);
iter.fDevice->drawRect(iter, r, looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@ -1244,13 +1244,13 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
}
}
ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
while (iter.next()) {
iter.fDevice->drawPath(iter, path, paint);
iter.fDevice->drawPath(iter, path, looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
@ -1328,13 +1328,13 @@ void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
const SkMatrix& matrix, const SkPaint& paint) {
SkDEBUGCODE(bitmap.validate();)
ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
while (iter.next()) {
iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint);
iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
@ -1350,13 +1350,13 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
paint = &tmp;
}
ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
while (iter.next()) {
iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
*paint);
looper.paint());
}
ITER_END
LOOPER_END
}
class SkDeviceFilteredPaint {
@ -1382,54 +1382,54 @@ private:
void SkCanvas::drawText(const void* text, size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, paint);
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, paint);
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
dfp.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, paint);
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
dfp.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
matrix, paint);
matrix, looper.paint());
}
ITER_END
LOOPER_END
}
#ifdef ANDROID
@ -1437,14 +1437,14 @@ void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint,
const SkPath& path, const SkMatrix* matrix) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
paint, path, matrix);
looper.paint(), path, matrix);
}
ITER_END
LOOPER_END
}
#endif
@ -1453,14 +1453,15 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
while (iter.next()) {
iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
colors, xmode, indices, indexCount, paint);
colors, xmode, indices, indexCount,
looper.paint());
}
ITER_END
LOOPER_END
}
void SkCanvas::drawData(const void* data, size_t length) {

View File

@ -7,11 +7,10 @@
SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
SkColor color, uint32_t flags)
: fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags)
{
: fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) {
SkASSERT(flags <= kAll_BlurFlag);
if (radius > 0)
{
if (radius > 0) {
uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
SkBlurMaskFilter::kNone_BlurFlag;
@ -23,28 +22,23 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
fBlur = SkBlurMaskFilter::Create(radius,
SkBlurMaskFilter::kNormal_BlurStyle,
blurFlags);
}
else
{
} else {
fBlur = NULL;
}
if (flags & kOverrideColor_BlurFlag)
{
if (flags & kOverrideColor_BlurFlag) {
// Set alpha to 1 for the override since transparency will already
// be baked into the blurred mask.
SkColor opaqueColor = SkColorSetA(color, 255);
//The SrcIn xfer mode will multiply 'color' by the incoming alpha
fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode);
}
else
{
fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
SkXfermode::kSrcIn_Mode);
} else {
fColorFilter = NULL;
}
}
SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
{
SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) {
fDx = buffer.readScalar();
fDy = buffer.readScalar();
fBlurColor = buffer.readU32();
@ -53,14 +47,12 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
fBlurFlags = buffer.readU32() & kAll_BlurFlag;
}
SkBlurDrawLooper::~SkBlurDrawLooper()
{
SkBlurDrawLooper::~SkBlurDrawLooper() {
SkSafeUnref(fBlur);
SkSafeUnref(fColorFilter);
}
void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
{
void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
buffer.writeScalar(fDx);
buffer.writeScalar(fDy);
buffer.write32(fBlurColor);
@ -69,63 +61,38 @@ void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
buffer.write32(fBlurFlags);
}
void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
{
// we do nothing if a maskfilter is already installed
if (paint->getMaskFilter() != NULL)
fState = kDone;
else
{
fState = kBeforeEdge;
fPaint = paint;
fCanvas = canvas;
fSaveCount = canvas->getSaveCount();
}
void SkBlurDrawLooper::init(SkCanvas* canvas) {
fState = kBeforeEdge;
}
bool SkBlurDrawLooper::next()
{
bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
switch (fState) {
case kBeforeEdge:
fSavedColor = fPaint->getColor();
fPaint->setColor(fBlurColor);
fPaint->setMaskFilter(fBlur);
fPaint->setColorFilter(fColorFilter);
fCanvas->save(SkCanvas::kMatrix_SaveFlag);
if (fBlurFlags & kIgnoreTransform_BlurFlag)
{
SkMatrix transform(fCanvas->getTotalMatrix());
transform.postTranslate(fDx, fDy);
fCanvas->setMatrix(transform);
}
else
{
fCanvas->translate(fDx, fDy);
}
fState = kAfterEdge;
return true;
case kAfterEdge:
fPaint->setColor(fSavedColor);
fPaint->setMaskFilter(NULL);
fPaint->setColorFilter(NULL);
fCanvas->restore(); // to remove the translate we did earlier
fState = kDone;
return true;
default:
SkASSERT(kDone == fState);
return false;
}
}
void SkBlurDrawLooper::restore()
{
if (kAfterEdge == fState)
{
fPaint->setColor(fSavedColor);
fPaint->setMaskFilter(NULL);
fPaint->setColorFilter(NULL);
fCanvas->restore(); // to remove the translate we did earlier
fState = kDone;
case kBeforeEdge:
// we do nothing if a maskfilter is already installed
if (paint->getMaskFilter()) {
fState = kDone;
return false;
}
paint->setColor(fBlurColor);
paint->setMaskFilter(fBlur);
paint->setColorFilter(fColorFilter);
canvas->save(SkCanvas::kMatrix_SaveFlag);
if (fBlurFlags & kIgnoreTransform_BlurFlag) {
SkMatrix transform(canvas->getTotalMatrix());
transform.postTranslate(fDx, fDy);
canvas->setMatrix(transform);
} else {
canvas->translate(fDx, fDy);
}
fState = kAfterEdge;
return true;
case kAfterEdge:
canvas->restore();
fState = kDone;
return true;
default:
SkASSERT(kDone == fState);
return false;
}
}

View File

@ -27,31 +27,21 @@ SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
return &rec->fPaint;
}
void SkLayerDrawLooper::init(SkCanvas* canvas, SkPaint* paint) {
fIter.fSavedPaint = *paint;
fIter.fPaint = paint;
fIter.fCanvas = canvas;
fIter.fRec = fRecs;
void SkLayerDrawLooper::init(SkCanvas* canvas) {
fCurrRec = fRecs;
canvas->save(SkCanvas::kMatrix_SaveFlag);
}
bool SkLayerDrawLooper::next() {
Rec* rec = fIter.fRec;
if (rec) {
*fIter.fPaint = rec->fPaint;
fIter.fCanvas->restore();
fIter.fCanvas->save(SkCanvas::kMatrix_SaveFlag);
fIter.fCanvas->translate(rec->fOffset.fX, rec->fOffset.fY);
fIter.fRec = rec->fNext;
return true;
bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
canvas->restore();
if (NULL == fCurrRec) {
return false;
}
return false;
}
void SkLayerDrawLooper::restore() {
fIter.fCanvas->restore();
*fIter.fPaint = fIter.fSavedPaint;
*paint = fCurrRec->fPaint;
canvas->save(SkCanvas::kMatrix_SaveFlag);
canvas->translate(fCurrRec->fOffset.fX, fCurrRec->fOffset.fY);
return true;
}
SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) {

View File

@ -2,21 +2,12 @@
#include "SkPaint.h"
SkPaintFlagsDrawFilter::SkPaintFlagsDrawFilter(uint32_t clearFlags,
uint32_t setFlags)
{
uint32_t setFlags) {
fClearFlags = SkToU16(clearFlags & SkPaint::kAllFlags);
fSetFlags = SkToU16(setFlags & SkPaint::kAllFlags);
}
bool SkPaintFlagsDrawFilter::filter(SkCanvas*, SkPaint* paint, Type)
{
fPrevFlags = paint->getFlags();
paint->setFlags((fPrevFlags & ~fClearFlags) | fSetFlags);
return true;
void SkPaintFlagsDrawFilter::filter(SkPaint* paint, Type) {
paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags);
}
void SkPaintFlagsDrawFilter::restore(SkCanvas*, SkPaint* paint, Type)
{
paint->setFlags(fPrevFlags);
}