SkBlurDrawLooper.cpp revision c73dd5c6880739f26216f198c757028fd28df1a4
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"
11c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com#include "SkFlattenableBuffers.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
144868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org#include "SkColorFilter.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
17038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                   SkColor color, uint32_t flags)
18a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
20038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    SkASSERT(flags <= kAll_BlurFlag);
214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (radius > 0) {
2282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
2382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
24038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
25038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org
264868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        blurFlags |= flags & kHighQuality_BlurFlag ?
274868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kHighQuality_BlurFlag :
284868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            SkBlurMaskFilter::kNone_BlurFlag;
294868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = SkBlurMaskFilter::Create(radius,
314868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                                         SkBlurMaskFilter::kNormal_BlurStyle,
32038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org                                         blurFlags);
334e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlur = NULL;
354868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
364868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    if (flags & kOverrideColor_BlurFlag) {
38a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // Set alpha to 1 for the override since transparency will already
39a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        // be baked into the blurred mask.
40a6398911174d5445456ecb2f5f4f0565db2f100bjunov@google.com        SkColor opaqueColor = SkColorSetA(color, 255);
414868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                                       SkXfermode::kSrcIn_Mode);
444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    } else {
454868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        fColorFilter = NULL;
464868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
496bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
506bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com: INHERITED(buffer) {
516bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDx = buffer.readScalar();
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDy = buffer.readScalar();
54c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fBlurColor = buffer.readColor();
55c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fBlur = buffer.readFlattenableT<SkMaskFilter>();
56c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fColorFilter = buffer.readFlattenableT<SkColorFilter>();
57c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comSkBlurDrawLooper::~SkBlurDrawLooper() {
6182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fBlur);
624868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkSafeUnref(fColorFilter);
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6554924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comvoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
6654924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com    this->INHERITED::flatten(buffer);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDx);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fDy);
69c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    buffer.writeColor(fBlurColor);
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeFlattenable(fBlur);
714868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
72c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    buffer.writeUInt(fBlurFlags);
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comvoid SkBlurDrawLooper::init(SkCanvas* canvas) {
764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    fState = kBeforeEdge;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.combool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (fState) {
814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kBeforeEdge:
824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            // we do nothing if a maskfilter is already installed
834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (paint->getMaskFilter()) {
844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                fState = kDone;
854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                return false;
864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
8756c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
88f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            SkColor blurColor;
89f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            blurColor = fBlurColor;
90f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            if (SkColorGetA(blurColor) == 255) {
91f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com                blurColor = SkColorSetA(blurColor, paint->getAlpha());
92f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            }
93f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com            paint->setColor(blurColor);
94f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#else
954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColor(fBlurColor);
96f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setMaskFilter(fBlur);
984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            paint->setColorFilter(fColorFilter);
994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->save(SkCanvas::kMatrix_SaveFlag);
1004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
1014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                SkMatrix transform(canvas->getTotalMatrix());
1024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                transform.postTranslate(fDx, fDy);
1034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->setMatrix(transform);
1044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            } else {
1054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                canvas->translate(fDx, fDy);
1064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            }
1074e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kAfterEdge;
1084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
1094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        case kAfterEdge:
1104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            canvas->restore();
1114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fState = kDone;
1124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return true;
1134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        default:
1144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            SkASSERT(kDone == fState);
1154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            return false;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
121d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurDrawLooper)
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
123