SkBlurDrawLooper.cpp revision 71531ca1f484da5837be8017a0c83e5bff701587
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurDrawLooper.h"
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMaskFilter.h"
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkCanvas.h"
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h"
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
671531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger#include "SkColorFilter.h"
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                   SkColor color, uint32_t flags)
1040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags)
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(flags <= kAll_BlurFlag);
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (radius > 0)
1440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    {
1540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
1640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
1740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkBlurMaskFilter::kNone_BlurFlag;
1840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1971531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        blurFlags |= flags & kHighQuality_BlurFlag ?
2071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger            SkBlurMaskFilter::kHighQuality_BlurFlag :
2171531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger            SkBlurMaskFilter::kNone_BlurFlag;
2271531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBlur = SkBlurMaskFilter::Create(radius,
2471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger                                         SkBlurMaskFilter::kNormal_BlurStyle,
2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                         blurFlags);
2640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
2871531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    {
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBlur = NULL;
3071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    }
3171531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger
3271531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    if (flags & kOverrideColor_BlurFlag)
3371531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    {
3471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
3571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fColorFilter = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
3671531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    }
3771531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    else
3871531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    {
3971531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fColorFilter = NULL;
4071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    }
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDx = buffer.readScalar();
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDy = buffer.readScalar();
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlurColor = buffer.readU32();
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
4971531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkBlurDrawLooper::~SkBlurDrawLooper()
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fBlur);
5671531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    SkSafeUnref(fColorFilter);
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fDx);
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fDy);
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fBlurColor);
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeFlattenable(fBlur);
6571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    buffer.writeFlattenable(fColorFilter);
6640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    buffer.write32(fBlurFlags);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we do nothing if a maskfilter is already installed
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (paint->getMaskFilter() != NULL)
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fState = kDone;
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fState = kBeforeEdge;
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint = paint;
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCanvas = canvas;
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fSaveCount = canvas->getSaveCount();
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBlurDrawLooper::next()
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
8502b2438fea16e164afb80c0a778af46089cefb10Romain Guy    SkColor blurColor;
8602b2438fea16e164afb80c0a778af46089cefb10Romain Guy    SkAlpha alpha;
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (fState) {
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kBeforeEdge:
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fSavedColor = fPaint->getColor();
9002b2438fea16e164afb80c0a778af46089cefb10Romain Guy        blurColor = fBlurColor;
9102b2438fea16e164afb80c0a778af46089cefb10Romain Guy        alpha = SkColorGetA(blurColor);
9202b2438fea16e164afb80c0a778af46089cefb10Romain Guy        if (alpha == 255) {
9302b2438fea16e164afb80c0a778af46089cefb10Romain Guy            blurColor = SkColorSetA(blurColor, fPaint->getAlpha());
9402b2438fea16e164afb80c0a778af46089cefb10Romain Guy        }
9502b2438fea16e164afb80c0a778af46089cefb10Romain Guy        fPaint->setColor(blurColor);
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setMaskFilter(fBlur);
9771531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fPaint->setColorFilter(fColorFilter);
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCanvas->save(SkCanvas::kMatrix_SaveFlag);
9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (fBlurFlags & kIgnoreTransform_BlurFlag)
10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        {
10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkMatrix transform(fCanvas->getTotalMatrix());
10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            transform.postTranslate(fDx, fDy);
10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            fCanvas->setMatrix(transform);
10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        else
10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        {
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            fCanvas->translate(fDx, fDy);
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fState = kAfterEdge;
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kAfterEdge:
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setColor(fSavedColor);
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setMaskFilter(NULL);
11471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fPaint->setColorFilter(NULL);
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCanvas->restore(); // to remove the translate we did earlier
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fState = kDone;
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    default:
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(kDone == fState);
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkBlurDrawLooper::restore()
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kAfterEdge == fState)
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setColor(fSavedColor);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setMaskFilter(NULL);
13071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fPaint->setColorFilter(NULL);
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCanvas->restore(); // to remove the translate we did earlier
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fState = kDone;
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkFlattenable::Registrar gReg("SkBlurDrawLooper",
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkBlurDrawLooper::CreateProc);
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
141