SkBlurDrawLooper.cpp revision 4e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7b
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)
104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) {
114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
12038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    SkASSERT(flags <= kAll_BlurFlag);
134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (radius > 0) {
1482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
1582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
16038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
17038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org
184868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        blurFlags |= flags & kHighQuality_BlurFlag ?
194868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kHighQuality_BlurFlag :
204868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
214868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = SkBlurMaskFilter::Create(radius,
234868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                                         SkBlurMaskFilter::kNormal_BlurStyle,
24038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                         blurFlags);
254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = NULL;
274868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
284868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
294e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (flags & kOverrideColor_BlurFlag) {
30a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // Set alpha to 1 for the override since transparency will already
31a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // be baked into the blurred mask.
32a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        SkColor opaqueColor = SkColorSetA(color, 255);
334868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                                       SkXfermode::kSrcIn_Mode);
364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
374868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = NULL;
384868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDx = buffer.readScalar();
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDy = buffer.readScalar();
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlurColor = buffer.readU32();
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
464868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
47038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comSkBlurDrawLooper::~SkBlurDrawLooper() {
5182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fBlur);
524868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkSafeUnref(fColorFilter);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDx);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDy);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.write32(fBlurColor);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeFlattenable(fBlur);
604868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
61038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    buffer.write32(fBlurFlags);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comvoid SkBlurDrawLooper::init(SkCanvas* canvas) {
654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    fState = kBeforeEdge;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.combool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (fState) {
704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kBeforeEdge:
714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            // we do nothing if a maskfilter is already installed
724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (paint->getMaskFilter()) {
734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                fState = kDone;
744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                return false;
754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColor(fBlurColor);
774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setMaskFilter(fBlur);
784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColorFilter(fColorFilter);
794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->save(SkCanvas::kMatrix_SaveFlag);
804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                SkMatrix transform(canvas->getTotalMatrix());
824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                transform.postTranslate(fDx, fDy);
834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->setMatrix(transform);
844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            } else {
854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->translate(fDx, fDy);
864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kAfterEdge;
884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kAfterEdge:
904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->restore();
914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kDone;
924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        default:
944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            SkASSERT(kDone == fState);
954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return false;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkFlattenable::Registrar gReg("SkBlurDrawLooper",
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     SkBlurDrawLooper::CreateProc);
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104