SkBlurDrawLooper.cpp revision a6398911174d5445456ecb2f5f4f0565db2f100b
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    {
34a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // Set alpha to 1 for the override since transparency will already
35a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // be baked into the blurred mask.
36a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        SkColor opaqueColor = SkColorSetA(color, 255);
374868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
38a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode);
394868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
404868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    else
414868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    {
424868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = NULL;
434868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDx = buffer.readScalar();
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDy = buffer.readScalar();
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlurColor = buffer.readU32();
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
524868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
53038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::~SkBlurDrawLooper()
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fBlur);
594868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkSafeUnref(fColorFilter);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDx);
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDy);
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.write32(fBlurColor);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeFlattenable(fBlur);
684868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
69038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    buffer.write32(fBlurFlags);
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // we do nothing if a maskfilter is already installed
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint->getMaskFilter() != NULL)
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kBeforeEdge;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas = canvas;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSaveCount = canvas->getSaveCount();
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBlurDrawLooper::next()
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (fState) {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kBeforeEdge:
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSavedColor = fPaint->getColor();
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fBlurColor);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(fBlur);
934868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(fColorFilter);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->save(SkCanvas::kMatrix_SaveFlag);
95038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        if (fBlurFlags & kIgnoreTransform_BlurFlag)
96038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        {
97038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkMatrix transform(fCanvas->getTotalMatrix());
98038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            transform.postTranslate(fDx, fDy);
99038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            fCanvas->setMatrix(transform);
100038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        }
101038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        else
102038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        {
103038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            fCanvas->translate(fDx, fDy);
104038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org        }
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kAfterEdge;
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kAfterEdge:
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fSavedColor);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(NULL);
1104868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(NULL);
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->restore(); // to remove the translate we did earlier
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(kDone == fState);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurDrawLooper::restore()
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (kAfterEdge == fState)
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setColor(fSavedColor);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint->setMaskFilter(NULL);
1264868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fPaint->setColorFilter(NULL);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas->restore(); // to remove the translate we did earlier
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fState = kDone;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkFlattenable::Registrar gReg("SkBlurDrawLooper",
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     SkBlurDrawLooper::CreateProc);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
137