SkBlurDrawLooper.cpp revision 4868e6b221a4a98e40f977851af5fcf09631ea15
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurDrawLooper.h"
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMaskFilter.h"
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
64868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org#include "SkColorFilter.h"
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
9038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                   SkColor color, uint32_t flags)
10038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags)
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
12038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    SkASSERT(flags <= kAll_BlurFlag);
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius > 0)
14038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    {
1582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
1682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
17038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
18038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org
194868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        blurFlags |= flags & kHighQuality_BlurFlag ?
204868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kHighQuality_BlurFlag :
214868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
224868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = SkBlurMaskFilter::Create(radius,
244868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                                         SkBlurMaskFilter::kNormal_BlurStyle,
25038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                         blurFlags);
26038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    }
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
284868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    {
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = NULL;
304868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
314868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
324868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    if (flags & kOverrideColor_BlurFlag)
334868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    {
344868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
354868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
364868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
374868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    else
384868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    {
394868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = NULL;
404868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDx = buffer.readScalar();
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDy = buffer.readScalar();
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlurColor = buffer.readU32();
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
494868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
50038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::~SkBlurDrawLooper()
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fBlur);
564868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkSafeUnref(fColorFilter);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDx);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDy);
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.write32(fBlurColor);
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeFlattenable(fBlur);
654868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
66038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    buffer.write32(fBlurFlags);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // we do nothing if a maskfilter is already installed
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint->getMaskFilter() != NULL)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kBeforeEdge;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas = canvas;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSaveCount = canvas->getSaveCount();
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBlurDrawLooper::next()
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (fState) {
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kBeforeEdge:
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSavedColor = fPaint->getColor();
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fBlurColor);
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(fBlur);
904868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(fColorFilter);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->save(SkCanvas::kMatrix_SaveFlag);
92038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        if (fBlurFlags & kIgnoreTransform_BlurFlag)
93038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        {
94038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkMatrix transform(fCanvas->getTotalMatrix());
95038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            transform.postTranslate(fDx, fDy);
96038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            fCanvas->setMatrix(transform);
97038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        }
98038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        else
99038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        {
100038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            fCanvas->translate(fDx, fDy);
101038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kAfterEdge;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kAfterEdge:
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fSavedColor);
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(NULL);
1074868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(NULL);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->restore(); // to remove the translate we did earlier
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(kDone == fState);
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::restore()
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (kAfterEdge == fState)
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fSavedColor);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(NULL);
1234868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(NULL);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->restore(); // to remove the translate we did earlier
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkFlattenable::Registrar gReg("SkBlurDrawLooper",
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     SkBlurDrawLooper::CreateProc);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134