blob: 901a4d343d4862cc139c7eda3a015647b25dbb1c [file] [log] [blame]
#include "SkBlurDrawLooper.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkMaskFilter.h"
#include "SkColorFilter.h"
SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
SkColor color, uint32_t flags)
: fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags)
{
SkASSERT(flags <= kAll_BlurFlag);
if (radius > 0)
{
uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
SkBlurMaskFilter::kNone_BlurFlag;
blurFlags |= flags & kHighQuality_BlurFlag ?
SkBlurMaskFilter::kHighQuality_BlurFlag :
SkBlurMaskFilter::kNone_BlurFlag;
fBlur = SkBlurMaskFilter::Create(radius,
SkBlurMaskFilter::kNormal_BlurStyle,
blurFlags);
}
else
{
fBlur = NULL;
}
if (flags & kOverrideColor_BlurFlag)
{
//The SrcIn xfer mode will multiply 'color' by the incoming alpha
fColorFilter = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
}
else
{
fColorFilter = NULL;
}
}
SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
{
fDx = buffer.readScalar();
fDy = buffer.readScalar();
fBlurColor = buffer.readU32();
fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
fBlurFlags = buffer.readU32() & kAll_BlurFlag;
}
SkBlurDrawLooper::~SkBlurDrawLooper()
{
SkSafeUnref(fBlur);
SkSafeUnref(fColorFilter);
}
void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
{
buffer.writeScalar(fDx);
buffer.writeScalar(fDy);
buffer.write32(fBlurColor);
buffer.writeFlattenable(fBlur);
buffer.writeFlattenable(fColorFilter);
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();
}
}
bool SkBlurDrawLooper::next()
{
SkColor blurColor;
SkAlpha alpha;
switch (fState) {
case kBeforeEdge:
fSavedColor = fPaint->getColor();
blurColor = fBlurColor;
alpha = SkColorGetA(blurColor);
if (alpha == 255) {
blurColor = SkColorSetA(blurColor, fPaint->getAlpha());
}
fPaint->setColor(blurColor);
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;
}
}
///////////////////////////////////////////////////////////////////////////////
static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
SkBlurDrawLooper::CreateProc);