SkBlurDrawLooper.cpp revision 54924243c1b65b3ee6d8fa064b50a9b1bb2a19a5
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurDrawLooper.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMaskFilter.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
134868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org#include "SkColorFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
16038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                   SkColor color, uint32_t flags)
17a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
19038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    SkASSERT(flags <= kAll_BlurFlag);
204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (radius > 0) {
2182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
2282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
23038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
24038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org
254868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        blurFlags |= flags & kHighQuality_BlurFlag ?
264868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kHighQuality_BlurFlag :
274868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
284868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = SkBlurMaskFilter::Create(radius,
304868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                                         SkBlurMaskFilter::kNormal_BlurStyle,
31038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                         blurFlags);
324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = NULL;
344868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
354868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (flags & kOverrideColor_BlurFlag) {
37a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // Set alpha to 1 for the override since transparency will already
38a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // be baked into the blurred mask.
39a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        SkColor opaqueColor = SkColorSetA(color, 255);
404868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                                       SkXfermode::kSrcIn_Mode);
434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
444868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = NULL;
454868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
486bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
496bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com: INHERITED(buffer) {
506bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDx = buffer.readScalar();
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDy = buffer.readScalar();
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlurColor = buffer.readU32();
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
554868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
56038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comSkBlurDrawLooper::~SkBlurDrawLooper() {
6082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fBlur);
614868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkSafeUnref(fColorFilter);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6454924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
6554924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com    this->INHERITED::flatten(buffer);
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDx);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDy);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.write32(fBlurColor);
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeFlattenable(fBlur);
704868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
71038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    buffer.write32(fBlurFlags);
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comvoid SkBlurDrawLooper::init(SkCanvas* canvas) {
754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    fState = kBeforeEdge;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.combool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (fState) {
804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kBeforeEdge:
814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            // we do nothing if a maskfilter is already installed
824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (paint->getMaskFilter()) {
834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                fState = kDone;
844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                return false;
854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
8656c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
87f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            SkColor blurColor;
88f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            blurColor = fBlurColor;
89f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            if (SkColorGetA(blurColor) == 255) {
90f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com                blurColor = SkColorSetA(blurColor, paint->getAlpha());
91f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            }
92f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            paint->setColor(blurColor);
93f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#else
944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColor(fBlurColor);
95f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setMaskFilter(fBlur);
974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColorFilter(fColorFilter);
984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->save(SkCanvas::kMatrix_SaveFlag);
994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
1004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                SkMatrix transform(canvas->getTotalMatrix());
1014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                transform.postTranslate(fDx, fDy);
1024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->setMatrix(transform);
1034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            } else {
1044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->translate(fDx, fDy);
1054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
1064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kAfterEdge;
1074e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
1084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kAfterEdge:
1094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->restore();
1104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kDone;
1114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
1124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        default:
1134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            SkASSERT(kDone == fState);
1144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return false;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
120d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurDrawLooper)
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
122